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 array 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 140do_test tabfunc01-600 { 141 set TAIL {} 142 set VM [sqlite3_prepare db {SELECT * FROM intarray(?2,?3)} -1 TAIL] 143 set TAIL 144} {} 145do_test tabfunc01-610 { 146 sqlite3_bind_intarray $VM 2 11 22 33 44 55 147 sqlite3_bind_int $VM 3 4 148 sqlite3_step $VM 149} SQLITE_ROW 150do_test tabfunc01-620 { 151 sqlite3_column_int $VM 0 152} 11 153do_test tabfunc01-621 { 154 sqlite3_step $VM 155 sqlite3_column_int $VM 0 156} 22 157sqlite3_finalize $VM 158 159do_test tabfunc01-650 { 160 db eval { 161 DROP TABLE IF EXISTS t6; 162 CREATE TABLE t6(x INTEGER PRIMARY KEY, y BLOB); 163 WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) 164 INSERT INTO t6(x,y) SELECT x, randomblob(x) FROM c; 165 } 166 set TAIL {} 167 set VM [sqlite3_prepare db { 168 SELECT length(y) FROM t6 WHERE x IN (SELECT value FROM intarray(?1,3)); 169 } -1 TAIL] 170 string trim $TAIL 171} {} 172do_test tabfunc01-660 { 173 sqlite3_bind_intarray $VM 1 11 22 33 44 55 174 sqlite3_step $VM 175} SQLITE_ROW 176do_test tabfunc01-661 { 177 sqlite3_column_int $VM 0 178} 11 179sqlite3_finalize $VM 180 181do_test tabfunc01-670 { 182 set TAIL {} 183 set VM [sqlite3_prepare db { 184 SELECT length(y) FROM t6 WHERE x IN intarray(?1,3); 185 } -1 TAIL] 186 string trim $TAIL 187} {} 188do_test tabfunc01-671 { 189 sqlite3_bind_intarray $VM 1 11 22 33 44 55 190 sqlite3_step $VM 191} SQLITE_ROW 192do_test tabfunc01-672 { 193 sqlite3_column_int $VM 0 194} 11 195sqlite3_finalize $VM 196 197catch {sqlite3_bind_intarray} 198 199finish_test 200