1# 2015-08-19 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# 12# This file implements tests for table-valued-functions implemented using 13# eponymous virtual tables. 14# 15 16set testdir [file dirname $argv0] 17source $testdir/tester.tcl 18set testprefix tabfunc01 19 20ifcapable !vtab { 21 finish_test 22 return 23} 24load_static_extension db series 25load_static_extension db carray 26 27do_execsql_test tabfunc01-1.1 { 28 SELECT *, '|' FROM generate_series WHERE start=1 AND stop=9 AND step=2; 29} {1 | 3 | 5 | 7 | 9 |} 30do_execsql_test tabfunc01-1.2 { 31 SELECT *, '|' FROM generate_series LIMIT 5; 32} {0 | 1 | 2 | 3 | 4 |} 33do_catchsql_test tabfunc01-1.3 { 34 CREATE VIRTUAL TABLE t1 USING generate_series; 35} {1 {no such module: generate_series}} 36do_execsql_test tabfunc01-1.4 { 37 SELECT * FROM generate_series(1,9,2); 38} {1 3 5 7 9} 39do_execsql_test tabfunc01-1.5 { 40 SELECT * FROM generate_series(1,9); 41} {1 2 3 4 5 6 7 8 9} 42do_execsql_test tabfunc01-1.6 { 43 SELECT * FROM generate_series(1,10) WHERE step=3; 44} {1 4 7 10} 45do_catchsql_test tabfunc01-1.7 { 46 SELECT * FROM generate_series(1,9,2,11); 47} {1 {too many arguments on generate_series() - max 3}} 48 49do_execsql_test tabfunc01-1.8 { 50 SELECT * FROM generate_series(0,32,5) ORDER BY rowid DESC; 51} {30 25 20 15 10 5 0} 52do_execsql_test tabfunc01-1.9 { 53 SELECT rowid, * FROM generate_series(0,32,5) ORDER BY value DESC; 54} {1 30 2 25 3 20 4 15 5 10 6 5 7 0} 55do_execsql_test tabfunc01-1.10 { 56 SELECT rowid, * FROM generate_series(0,32,5) ORDER BY +value DESC; 57} {7 30 6 25 5 20 4 15 3 10 2 5 1 0} 58 59do_execsql_test tabfunc01-1.20 { 60 CREATE VIEW v1(a,b) AS VALUES(1,2),(3,4); 61 SELECT * FROM v1; 62} {1 2 3 4} 63do_catchsql_test tabfunc01-1.21.1 { 64 SELECT * FROM v1(55); 65} {1 {'v1' is not a function}} 66do_catchsql_test tabfunc01-1.21.2 { 67 SELECT * FROM v1(); 68} {1 {'v1' is not a function}} 69do_execsql_test tabfunc01-1.22 { 70 CREATE VIEW v2(x) AS SELECT value FROM generate_series(1,5); 71 SELECT * FROM v2; 72} {1 2 3 4 5} 73do_catchsql_test tabfunc01-1.23.1 { 74 SELECT * FROM v2(55); 75} {1 {'v2' is not a function}} 76do_catchsql_test tabfunc01-1.23.2 { 77 SELECT * FROM v2(); 78} {1 {'v2' is not a function}} 79do_execsql_test tabfunc01-1.24 { 80 CREATE TABLE t0(x); 81 INSERT INTO t0(x) VALUES(123),(456),(789); 82 SELECT * FROM t0 ORDER BY x; 83} {123 456 789} 84do_catchsql_test tabfunc01-1.25 { 85 SELECT * FROM t0(55) ORDER BY x; 86} {1 {'t0' is not a function}} 87do_catchsql_test tabfunc01-1.26 { 88 WITH w0 AS (SELECT * FROM t0) 89 INSERT INTO t0(x) SELECT * FROM w0() 90} {1 {'w0' is not a function}} 91 92do_execsql_test tabfunc01-2.1 { 93 CREATE TABLE t1(x); 94 INSERT INTO t1(x) VALUES(2),(3); 95 SELECT *, '|' FROM t1, generate_series(1,x) ORDER BY 1, 2 96} {2 1 | 2 2 | 3 1 | 3 2 | 3 3 |} 97do_execsql_test tabfunc01-2.2 { 98 SELECT *, '|' FROM (SELECT x FROM t1) AS y, generate_series(1,y.x) 99 ORDER BY 1, 2; 100} {2 1 | 2 2 | 3 1 | 3 2 | 3 3 |} 101 102do_execsql_test tabfunc01-2.50 { 103 SELECT * FROM generate_series() LIMIT 5; 104} {0 1 2 3 4} 105 106do_execsql_test tabfunc01-3.1 { 107 SELECT DISTINCT value FROM generate_series(1,x), t1 ORDER BY 1; 108} {1 2 3} 109 110# Eponymous virtual table exists in the "main" schema only 111# 112do_execsql_test tabfunc01-4.1 { 113 SELECT * FROM main.generate_series(1,4) 114} {1 2 3 4} 115do_catchsql_test tabfunc01-4.2 { 116 SELECT * FROM temp.generate_series(1,4) 117} {1 {no such table: temp.generate_series}} 118do_catchsql_test tabfunc01-4.3 { 119 ATTACH ':memory:' AS aux1; 120 CREATE TABLE aux1.t1(a,b,c); 121 SELECT * FROM aux1.generate_series(1,4) 122} {1 {no such table: aux1.generate_series}} 123 124# The next series of tests is verifying that virtual table are able 125# to optimize the IN operator, even on terms that are not marked "omit". 126# When the generate_series virtual table is compiled for the testfixture, 127# the special -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 option is used, which 128# causes the xBestIndex method of generate_series to leave the 129# sqlite3_index_constraint_usage.omit flag set to 0, which should cause 130# the SQLite core to verify the start=, stop=, and step= constraints on 131# each step of output. At one point, the IN operator could not be used 132# by virtual tables unless omit was set. 133# 134do_execsql_test tabfunc01-500 { 135 SELECT * FROM generate_series WHERE start IN (1,7) AND stop=20 AND step=10 136 ORDER BY +1; 137} {1 7 11 17} 138 139# Table-valued functions on the RHS of an IN operator 140# 141do_execsql_test tabfunc01-600 { 142 CREATE TABLE t600(a INTEGER PRIMARY KEY, b TEXT); 143 WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) 144 INSERT INTO t600(a,b) SELECT x, printf('(%03d)',x) FROM c; 145 SELECT b FROM t600 WHERE a IN generate_series(2,52,10); 146} {(002) (012) (022) (032) (042) (052)} 147 148 149do_test tabfunc01-700 { 150 set PTR [intarray_addr 5 7 13 17 23] 151 db eval { 152 SELECT b FROM t600, carray($PTR,5) WHERE a=value; 153 } 154} {(005) (007) (013) (017) (023)} 155do_test tabfunc01-701 { 156 db eval { 157 SELECT b FROM t600 WHERE a IN carray($PTR,5,'int32'); 158 } 159} {(005) (007) (013) (017) (023)} 160do_test tabfunc01-702 { 161 db eval { 162 SELECT b FROM t600 WHERE a IN carray($PTR,4,'int32'); 163 } 164} {(005) (007) (013) (017)} 165do_catchsql_test tabfunc01-710 { 166 SELECT b FROM t600 WHERE a IN carray($PTR,5,'int33'); 167} {1 {unknown datatype: 'int33'}} 168 169do_test tabfunc01-720 { 170 set PTR [int64array_addr 5 7 13 17 23] 171 db eval { 172 SELECT b FROM t600, carray($PTR,5,'int64') WHERE a=value; 173 } 174} {(005) (007) (013) (017) (023)} 175 176do_test tabfunc01-730 { 177 set PTR [doublearray_addr 5.0 7.0 13.0 17.0 23.0] 178 db eval { 179 SELECT b FROM t600, carray($PTR,5,'double') WHERE a=value; 180 } 181} {(005) (007) (013) (017) (023)} 182 183do_test tabfunc01-740 { 184 set PTR [textarray_addr 5 7 13 17 23] 185 db eval { 186 SELECT b FROM t600, carray($PTR,5,'char*') WHERE a=value; 187 } 188} {(005) (007) (013) (017) (023)} 189 190 191intarray_addr 192int64array_addr 193doublearray_addr 194textarray_addr 195 196finish_test 197