1398f872dSdrh# 2015-08-19 2398f872dSdrh# 3398f872dSdrh# The author disclaims copyright to this source code. In place of 4398f872dSdrh# a legal notice, here is a blessing: 5398f872dSdrh# 6398f872dSdrh# May you do good and not evil. 7398f872dSdrh# May you find forgiveness for yourself and forgive others. 8398f872dSdrh# May you share freely, never taking more than you give. 9398f872dSdrh# 10398f872dSdrh#*********************************************************************** 11398f872dSdrh# 12398f872dSdrh# This file implements tests for table-valued-functions implemented using 13398f872dSdrh# eponymous virtual tables. 14398f872dSdrh# 15398f872dSdrh 16398f872dSdrhset testdir [file dirname $argv0] 17398f872dSdrhsource $testdir/tester.tcl 18398f872dSdrhset testprefix tabfunc01 19398f872dSdrh 20398f872dSdrhifcapable !vtab { 21398f872dSdrh finish_test 22398f872dSdrh return 23398f872dSdrh} 24398f872dSdrhload_static_extension db series 252e3f87aeSdrhload_static_extension db carray 266bada272Sdrhload_static_extension db remember 27398f872dSdrh 28398f872dSdrhdo_execsql_test tabfunc01-1.1 { 29398f872dSdrh SELECT *, '|' FROM generate_series WHERE start=1 AND stop=9 AND step=2; 30398f872dSdrh} {1 | 3 | 5 | 7 | 9 |} 31bfbf7d9dSdrhdo_execsql_test tabfunc01-1.1b { 32bfbf7d9dSdrh PRAGMA table_xinfo(generate_series); 33bfbf7d9dSdrh} {0 value {} 0 {} 0 0 1 start {} 0 {} 0 1 2 stop {} 0 {} 0 1 3 step {} 0 {} 0 1} 34398f872dSdrhdo_execsql_test tabfunc01-1.2 { 35e46ec734Sdrh SELECT *, '|' FROM generate_series(0) LIMIT 5; 36398f872dSdrh} {0 | 1 | 2 | 3 | 4 |} 37e46ec734Sdrhdo_catchsql_test tabfunc01-1.2b { 38e46ec734Sdrh SELECT *, '|' FROM generate_series LIMIT 5; 39e46ec734Sdrh} {1 {first argument to "generate_series()" missing or unusable}} 40e46ec734Sdrhdo_catchsql_test tabfunc01-1.2c { 41e46ec734Sdrh SELECT *, '|' FROM generate_series(value) LIMIT 5; 42e46ec734Sdrh} {1 {first argument to "generate_series()" missing or unusable}} 43398f872dSdrhdo_catchsql_test tabfunc01-1.3 { 44398f872dSdrh CREATE VIRTUAL TABLE t1 USING generate_series; 458a48b9c0Sdrh} {1 {no such module: generate_series}} 4601d230ceSdrhdo_execsql_test tabfunc01-1.4 { 4701d230ceSdrh SELECT * FROM generate_series(1,9,2); 4801d230ceSdrh} {1 3 5 7 9} 4901d230ceSdrhdo_execsql_test tabfunc01-1.5 { 5001d230ceSdrh SELECT * FROM generate_series(1,9); 5101d230ceSdrh} {1 2 3 4 5 6 7 8 9} 5201d230ceSdrhdo_execsql_test tabfunc01-1.6 { 5301d230ceSdrh SELECT * FROM generate_series(1,10) WHERE step=3; 5401d230ceSdrh} {1 4 7 10} 5501d230ceSdrhdo_catchsql_test tabfunc01-1.7 { 5601d230ceSdrh SELECT * FROM generate_series(1,9,2,11); 57d8b1bfc6Sdrh} {1 {too many arguments on generate_series() - max 3}} 5801d230ceSdrh 59bc550df3Sdrhdo_execsql_test tabfunc01-1.8 { 60bc550df3Sdrh SELECT * FROM generate_series(0,32,5) ORDER BY rowid DESC; 61bc550df3Sdrh} {30 25 20 15 10 5 0} 62509c3fc0Sdrhdo_execsql_test tabfunc01-1.9 { 63509c3fc0Sdrh SELECT rowid, * FROM generate_series(0,32,5) ORDER BY value DESC; 64509c3fc0Sdrh} {1 30 2 25 3 20 4 15 5 10 6 5 7 0} 65509c3fc0Sdrhdo_execsql_test tabfunc01-1.10 { 66509c3fc0Sdrh SELECT rowid, * FROM generate_series(0,32,5) ORDER BY +value DESC; 67509c3fc0Sdrh} {7 30 6 25 5 20 4 15 3 10 2 5 1 0} 68bc550df3Sdrh 696230212fSdrhdo_execsql_test tabfunc01-1.20 { 706230212fSdrh CREATE VIEW v1(a,b) AS VALUES(1,2),(3,4); 716230212fSdrh SELECT * FROM v1; 726230212fSdrh} {1 2 3 4} 7320292310Sdrhdo_catchsql_test tabfunc01-1.21.1 { 746230212fSdrh SELECT * FROM v1(55); 756230212fSdrh} {1 {'v1' is not a function}} 7620292310Sdrhdo_catchsql_test tabfunc01-1.21.2 { 7720292310Sdrh SELECT * FROM v1(); 7820292310Sdrh} {1 {'v1' is not a function}} 796230212fSdrhdo_execsql_test tabfunc01-1.22 { 806230212fSdrh CREATE VIEW v2(x) AS SELECT value FROM generate_series(1,5); 816230212fSdrh SELECT * FROM v2; 826230212fSdrh} {1 2 3 4 5} 8320292310Sdrhdo_catchsql_test tabfunc01-1.23.1 { 846230212fSdrh SELECT * FROM v2(55); 856230212fSdrh} {1 {'v2' is not a function}} 8620292310Sdrhdo_catchsql_test tabfunc01-1.23.2 { 8720292310Sdrh SELECT * FROM v2(); 8820292310Sdrh} {1 {'v2' is not a function}} 8920292310Sdrhdo_execsql_test tabfunc01-1.24 { 9020292310Sdrh CREATE TABLE t0(x); 9120292310Sdrh INSERT INTO t0(x) VALUES(123),(456),(789); 9220292310Sdrh SELECT * FROM t0 ORDER BY x; 9320292310Sdrh} {123 456 789} 9420292310Sdrhdo_catchsql_test tabfunc01-1.25 { 9520292310Sdrh SELECT * FROM t0(55) ORDER BY x; 9620292310Sdrh} {1 {'t0' is not a function}} 9720292310Sdrhdo_catchsql_test tabfunc01-1.26 { 9820292310Sdrh WITH w0 AS (SELECT * FROM t0) 9920292310Sdrh INSERT INTO t0(x) SELECT * FROM w0() 10020292310Sdrh} {1 {'w0' is not a function}} 1016230212fSdrh 10201d230ceSdrhdo_execsql_test tabfunc01-2.1 { 10301d230ceSdrh CREATE TABLE t1(x); 10401d230ceSdrh INSERT INTO t1(x) VALUES(2),(3); 10501d230ceSdrh SELECT *, '|' FROM t1, generate_series(1,x) ORDER BY 1, 2 10601d230ceSdrh} {2 1 | 2 2 | 3 1 | 3 2 | 3 3 |} 107d10dbad5Sdrhdo_execsql_test tabfunc01-2.2 { 108d12b6363Sdrh SELECT *, '|' FROM (SELECT x FROM t1) AS y, generate_series(1,y.x) 109d12b6363Sdrh ORDER BY 1, 2; 110d12b6363Sdrh} {2 1 | 2 2 | 3 1 | 3 2 | 3 3 |} 111d12b6363Sdrh 112d12b6363Sdrhdo_execsql_test tabfunc01-2.50 { 113e46ec734Sdrh SELECT * FROM generate_series(0) LIMIT 5; 114d10dbad5Sdrh} {0 1 2 3 4} 115d10dbad5Sdrh 1161f2fc281Sdrhdo_execsql_test tabfunc01-3.1 { 1171f2fc281Sdrh SELECT DISTINCT value FROM generate_series(1,x), t1 ORDER BY 1; 1181f2fc281Sdrh} {1 2 3} 1191f2fc281Sdrh 12022f018c9Sdrhdo_eqp_test tabfunc01-3.10 { 12122f018c9Sdrh SELECT value FROM generate_series(1,10) ORDER BY value; 12222f018c9Sdrh} { 12322f018c9Sdrh QUERY PLAN 12422f018c9Sdrh `--SCAN generate_series VIRTUAL TABLE INDEX 19: 12522f018c9Sdrh} 12622f018c9Sdrhdo_eqp_test tabfunc01-3.11 { 12722f018c9Sdrh SELECT value FROM generate_series(1,10) ORDER BY +value; 12822f018c9Sdrh} { 12922f018c9Sdrh QUERY PLAN 13022f018c9Sdrh |--SCAN generate_series VIRTUAL TABLE INDEX 3: 13122f018c9Sdrh `--USE TEMP B-TREE FOR ORDER BY 13222f018c9Sdrh} 13322f018c9Sdrhdo_eqp_test tabfunc01-3.12 { 13422f018c9Sdrh SELECT value FROM generate_series(1,10) ORDER BY value, stop; 13522f018c9Sdrh} { 13622f018c9Sdrh QUERY PLAN 13722f018c9Sdrh `--SCAN generate_series VIRTUAL TABLE INDEX 19: 13822f018c9Sdrh} 13922f018c9Sdrhdo_eqp_test tabfunc01-3.13 { 14022f018c9Sdrh SELECT value FROM generate_series(1,10) ORDER BY stop, value; 14122f018c9Sdrh} { 14222f018c9Sdrh QUERY PLAN 14322f018c9Sdrh |--SCAN generate_series VIRTUAL TABLE INDEX 3: 14422f018c9Sdrh `--USE TEMP B-TREE FOR ORDER BY 14522f018c9Sdrh} 14622f018c9Sdrh 14722f018c9Sdrh 148*52576b78Sdrhdo_eqp_test tabfunc01-3.20 { 149*52576b78Sdrh WITH t1(a) AS ( 150*52576b78Sdrh SELECT value FROM generate_series(0,10,2) 151*52576b78Sdrh UNION ALL 152*52576b78Sdrh SELECT value FROM generate_series(9,18,3) 153*52576b78Sdrh ) 154*52576b78Sdrh SELECT * FROM t1 ORDER BY a; 155*52576b78Sdrh} { 156*52576b78Sdrh QUERY PLAN 157*52576b78Sdrh `--MERGE (UNION ALL) 158*52576b78Sdrh |--LEFT 159*52576b78Sdrh | `--SCAN generate_series VIRTUAL TABLE INDEX 23: 160*52576b78Sdrh `--RIGHT 161*52576b78Sdrh `--SCAN generate_series VIRTUAL TABLE INDEX 23: 162*52576b78Sdrh} 163*52576b78Sdrh 164*52576b78Sdrh 1659196c814Sdrh# Eponymous virtual table exists in all schemas. 166b4d472f6Sdrh# 167b4d472f6Sdrhdo_execsql_test tabfunc01-4.1 { 168b4d472f6Sdrh SELECT * FROM main.generate_series(1,4) 169b4d472f6Sdrh} {1 2 3 4} 1709196c814Sdrhdo_execsql_test tabfunc01-4.2 { 171b4d472f6Sdrh SELECT * FROM temp.generate_series(1,4) 1729196c814Sdrh} {1 2 3 4} 1739196c814Sdrhdo_execsql_test tabfunc01-4.3 { 174b4d472f6Sdrh ATTACH ':memory:' AS aux1; 175b4d472f6Sdrh CREATE TABLE aux1.t1(a,b,c); 176b4d472f6Sdrh SELECT * FROM aux1.generate_series(1,4) 1779196c814Sdrh} {1 2 3 4} 178d10dbad5Sdrh 1794a5cff73Sdrh# 2018-12-03: Fix bug reported by by private email. 1804a5cff73Sdrhdo_execsql_test tabfunc01-4.4 { 1814a5cff73Sdrh SELECT * FROM (generate_series(1,5,2)) AS x LIMIT 10; 1824a5cff73Sdrh} {1 3 5} 1834a5cff73Sdrh 184dbc49161Sdrh# The next series of tests is verifying that virtual table are able 185dbc49161Sdrh# to optimize the IN operator, even on terms that are not marked "omit". 186dbc49161Sdrh# When the generate_series virtual table is compiled for the testfixture, 187dbc49161Sdrh# the special -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 option is used, which 188dbc49161Sdrh# causes the xBestIndex method of generate_series to leave the 189dbc49161Sdrh# sqlite3_index_constraint_usage.omit flag set to 0, which should cause 190dbc49161Sdrh# the SQLite core to verify the start=, stop=, and step= constraints on 191dbc49161Sdrh# each step of output. At one point, the IN operator could not be used 192dbc49161Sdrh# by virtual tables unless omit was set. 193dbc49161Sdrh# 194dbc49161Sdrhdo_execsql_test tabfunc01-500 { 195dbc49161Sdrh SELECT * FROM generate_series WHERE start IN (1,7) AND stop=20 AND step=10 196dbc49161Sdrh ORDER BY +1; 197dbc49161Sdrh} {1 7 11 17} 198dbc49161Sdrh 1995fbab882Sdrh# Table-valued functions on the RHS of an IN operator 2005fbab882Sdrh# 2015fbab882Sdrhdo_execsql_test tabfunc01-600 { 2025fbab882Sdrh CREATE TABLE t600(a INTEGER PRIMARY KEY, b TEXT); 2035fbab882Sdrh WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) 2045fbab882Sdrh INSERT INTO t600(a,b) SELECT x, printf('(%03d)',x) FROM c; 2055fbab882Sdrh SELECT b FROM t600 WHERE a IN generate_series(2,52,10); 2065fbab882Sdrh} {(002) (012) (022) (032) (042) (052)} 2075fbab882Sdrh 2084841624aSdrh 2092e3f87aeSdrhdo_test tabfunc01-700 { 21059a40db3Sdrh set PTR1 [intarray_addr 5 7 13 17 23] 21164131c15Sdrh db eval { 2123561dd4aSdrh SELECT b FROM t600, carray(inttoptr($PTR1),5) WHERE a=value; 21364131c15Sdrh } 2142e3f87aeSdrh} {(005) (007) (013) (017) (023)} 2152e3f87aeSdrhdo_test tabfunc01-701 { 2162e3f87aeSdrh db eval { 2173561dd4aSdrh SELECT b FROM t600 WHERE a IN carray(inttoptr($PTR1),5,'int32'); 2182e3f87aeSdrh } 2192e3f87aeSdrh} {(005) (007) (013) (017) (023)} 2202e3f87aeSdrhdo_test tabfunc01-702 { 2212e3f87aeSdrh db eval { 2223561dd4aSdrh SELECT b FROM t600 WHERE a IN carray(inttoptr($PTR1),4,'int32'); 2232e3f87aeSdrh } 2242e3f87aeSdrh} {(005) (007) (013) (017)} 2252e3f87aeSdrhdo_catchsql_test tabfunc01-710 { 2263561dd4aSdrh SELECT b FROM t600 WHERE a IN carray(inttoptr($PTR1),5,'int33'); 2272e3f87aeSdrh} {1 {unknown datatype: 'int33'}} 22864131c15Sdrh 2292e3f87aeSdrhdo_test tabfunc01-720 { 23059a40db3Sdrh set PTR2 [int64array_addr 5 7 13 17 23] 2312e3f87aeSdrh db eval { 2323561dd4aSdrh SELECT b FROM t600, carray(inttoptr($PTR2),5,'int64') WHERE a=value; 2332e3f87aeSdrh } 2342e3f87aeSdrh} {(005) (007) (013) (017) (023)} 2356bada272Sdrhdo_test tabfunc01-721 { 2366bada272Sdrh db eval { 2373561dd4aSdrh SELECT remember(123,inttoptr($PTR2)); 2383561dd4aSdrh SELECT value FROM carray(inttoptr($PTR2),5,'int64'); 2396bada272Sdrh } 2406bada272Sdrh} {123 123 7 13 17 23} 2416bada272Sdrhdo_test tabfunc01-722 { 24259a40db3Sdrh set PTR3 [expr {$PTR2+16}] 2436bada272Sdrh db eval { 2443561dd4aSdrh SELECT remember(987,inttoptr($PTR3)); 2453561dd4aSdrh SELECT value FROM carray(inttoptr($PTR2),5,'int64'); 2466bada272Sdrh } 2476bada272Sdrh} {987 123 7 987 17 23} 2482d053314Sdrh 2492e3f87aeSdrhdo_test tabfunc01-730 { 25059a40db3Sdrh set PTR4 [doublearray_addr 5.0 7.0 13.0 17.0 23.0] 2512e3f87aeSdrh db eval { 2523561dd4aSdrh SELECT b FROM t600, carray(inttoptr($PTR4),5,'double') WHERE a=value; 2532e3f87aeSdrh } 2542e3f87aeSdrh} {(005) (007) (013) (017) (023)} 2552e3f87aeSdrh 2562e3f87aeSdrhdo_test tabfunc01-740 { 25759a40db3Sdrh set PTR5 [textarray_addr x5 x7 x13 x17 x23] 2582e3f87aeSdrh db eval { 2593561dd4aSdrh SELECT b FROM t600, carray(inttoptr($PTR5),5,'char*') 2603561dd4aSdrh WHERE a=trim(value,'x'); 2612e3f87aeSdrh } 2622e3f87aeSdrh} {(005) (007) (013) (017) (023)} 2632e3f87aeSdrh 26459a40db3Sdrhdo_test tabfunc01-750 { 26559a40db3Sdrh db eval { 26659a40db3Sdrh SELECT aa.value, bb.value, '|' 2673561dd4aSdrh FROM carray(inttoptr($PTR4),5,'double') AS aa 2683561dd4aSdrh JOIN carray(inttoptr($PTR5),5,'char*') AS bb ON aa.rowid=bb.rowid; 26959a40db3Sdrh } 27059a40db3Sdrh} {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |} 2712e3f87aeSdrh 2728103a036Sdrh# ticket https://www.sqlite.org/src/info/2ae0c599b735d59e 2738103a036Sdrhdo_test tabfunc01-751 { 2748103a036Sdrh db eval { 2758103a036Sdrh SELECT aa.value, bb.value, '|' 2768103a036Sdrh FROM carray(inttoptr($PTR4),5,'double') AS aa 2778103a036Sdrh LEFT JOIN carray(inttoptr($PTR5),5,'char*') AS bb ON aa.rowid=bb.rowid; 2788103a036Sdrh } 2798103a036Sdrh} {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |} 2808103a036Sdrh 2813d8c92d0Sdrhifcapable altertable { 2823d8c92d0Sdrh do_test tabfunc01-800 { 2833d8c92d0Sdrh catchsql { 2843d8c92d0Sdrh ALTER TABLE generate_series ADD COLUMN col2; 2853d8c92d0Sdrh } 2863d8c92d0Sdrh } {1 {virtual tables may not be altered}} 2873d8c92d0Sdrh do_test tabfunc01-810 { 2883d8c92d0Sdrh catchsql { 2893d8c92d0Sdrh ALTER TABLE generate_series RENAME TO flubber; 2903d8c92d0Sdrh } 2913d8c92d0Sdrh } {1 {table generate_series may not be altered}} 2923d8c92d0Sdrh do_test tabfunc01-820 { 2933d8c92d0Sdrh catchsql { 2943d8c92d0Sdrh ALTER TABLE generate_series RENAME start TO flubber; 2953d8c92d0Sdrh } 2963d8c92d0Sdrh } {1 {table generate_series may not be altered}} 2973d8c92d0Sdrh do_test tabfunc01-830 { 2983d8c92d0Sdrh catchsql { 2993d8c92d0Sdrh ALTER TABLE generate_series DROP COLUMN start; 3003d8c92d0Sdrh } 3013d8c92d0Sdrh } {1 {table generate_series may not be altered}} 3023d8c92d0Sdrh do_test tabfunc01-900 { 3033d8c92d0Sdrh catchsql { 3043d8c92d0Sdrh ALTER TABLE pragma_compile_options ADD COLUMN col2; 3053d8c92d0Sdrh } 3063d8c92d0Sdrh } {1 {virtual tables may not be altered}} 3073d8c92d0Sdrh do_test tabfunc01-910 { 3083d8c92d0Sdrh catchsql { 3093d8c92d0Sdrh ALTER TABLE pragma_compile_options RENAME TO flubber; 3103d8c92d0Sdrh } 3113d8c92d0Sdrh } {1 {table pragma_compile_options may not be altered}} 3123d8c92d0Sdrh do_test tabfunc01-920 { 3133d8c92d0Sdrh catchsql { 3143d8c92d0Sdrh ALTER TABLE pragma_compile_options RENAME start TO flubber; 3153d8c92d0Sdrh } 3163d8c92d0Sdrh } {1 {table pragma_compile_options may not be altered}} 3173d8c92d0Sdrh do_test tabfunc01-930 { 3183d8c92d0Sdrh catchsql { 3193d8c92d0Sdrh ALTER TABLE pragma_compile_options DROP COLUMN start; 3203d8c92d0Sdrh } 3213d8c92d0Sdrh } {1 {table pragma_compile_options may not be altered}} 3223d8c92d0Sdrh} 3233d8c92d0Sdrh 3243d8c92d0Sdrh 32559a40db3Sdrh# Free up memory allocations 3262e3f87aeSdrhintarray_addr 3272e3f87aeSdrhint64array_addr 3282e3f87aeSdrhdoublearray_addr 3292e3f87aeSdrhtextarray_addr 3304841624aSdrh 331398f872dSdrhfinish_test 332