# 2024-04-26 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix bestindexC ifcapable !vtab { finish_test return } register_tcl_module db proc vtab_command {lVal method args} { switch -- $method { xConnect { return "CREATE TABLE t1(a)" } xBestIndex { set hdl [lindex $args 0] set clist [$hdl constraints] set orderby [$hdl orderby] set idxstr [list] set res [list] set idx 0 foreach c $clist { array set a $c if {$a(usable)==0} continue if {$a(op)=="limit" && ![info exists ::do_not_use_limit]} { lappend idxstr limit lappend res omit $idx } if {$a(op)=="offset" && ![info exists ::do_not_use_offset]} { lappend idxstr offset lappend res omit $idx } incr idx } return "cost 1000000 rows 1000000 idxnum 0 idxstr {$idxstr} $res" } xFilter { set idxstr [lindex $args 1] set LIMIT "" foreach a $idxstr b [lindex $args 2] { set x($a) $b } if {![info exists x(limit)]} { set x(limit) -1 } if {![info exists x(offset)]} { set x(offset) -1 } set LIMIT " LIMIT $x(limit) OFFSET $x(offset)" set idx 1 foreach v $lVal { lappend lRow "($idx, '$v')" incr idx } return [list sql " SELECT * FROM ( VALUES [join $lRow ,]) $LIMIT "] } } return {} } do_execsql_test 1.0 { CREATE VIRTUAL TABLE x1 USING tcl(vtab_command "a b c d e f"); CREATE VIRTUAL TABLE x2 USING tcl(vtab_command "A B C D E F a b"); } {} do_execsql_test 1.1 { CREATE TEMP TABLE t_unionall AS SELECT * FROM x1 UNION ALL SELECT * FROM x2; CREATE TEMP TABLE t_intersect AS SELECT * FROM x1 INTERSECT SELECT * FROM x2; CREATE TEMP TABLE t_union AS SELECT * FROM x1 UNION SELECT * FROM x2; CREATE TEMP TABLE t_except AS SELECT * FROM x1 EXCEPT SELECT * FROM x2; } foreach {tn limit} { 1 "LIMIT 8" 2 "LIMIT 4" 3 "LIMIT 4 OFFSET 2" 4 "LIMIT 8 OFFSET 4" } { foreach {op tbl} { "UNION ALL" t_unionall "UNION" t_union "INTERSECT" t_intersect "EXCEPT" t_except } { set expect [execsql "SELECT * FROM $tbl $limit"] do_execsql_test 1.2.$tbl.$tn "SELECT * FROM ( SELECT * FROM x1 $op SELECT * FROM x2 ) $limit" $expect } } #------------------------------------------------------------------------- reset_db register_tcl_module db do_execsql_test 2.0 { CREATE VIRTUAL TABLE x1 USING tcl(vtab_command "a b c d e f"); CREATE VIRTUAL TABLE x2 USING tcl(vtab_command "a b e f"); } {} do_execsql_test 2.1 { SELECT * FROM x1 EXCEPT SELECT * FROM x2 LIMIT 3 } {c d} #------------------------------------------------------------------------- reset_db register_tcl_module db do_execsql_test 3.0 { CREATE VIRTUAL TABLE y1 USING tcl(vtab_command "1 2 3 4 5 6 7 8 9 10"); } {} do_execsql_test 3.1 { SELECT * FROM y1 WHERE a = COALESCE('8', a) LIMIT 3 } {8} do_execsql_test 3.2 { SELECT * FROM y1 WHERE a = '2' LIMIT 3 } {2} load_static_extension db series do_execsql_test 3.3 { SELECT * FROM generate_series(1, 5) WHERE value = (value & 14) LIMIT 3 } {2 4} do_execsql_test 3.4 { SELECT value FROM generate_series(1,10) WHERE value>2 LIMIT 4 OFFSET 1; } {4 5 6 7} set ::do_not_use_limit 1 do_execsql_test 3.5 { SELECT * FROM y1 LIMIT 5 OFFSET 3 } {4 5 6 7 8} unset ::do_not_use_limit set ::do_not_use_offset 1 do_execsql_test 3.6 { SELECT * FROM y1 LIMIT 5 OFFSET 3 } {4 5 6 7 8} unset ::do_not_use_offset #------------------------------------------------------------------------- reset_db proc vtab_command {lVal method args} { switch -- $method { xConnect { error "not happy!" } } return {} } register_tcl_module db do_catchsql_test 4.0 { CREATE VIRTUAL TABLE y1 USING tcl(vtab_command 1); } {1 {not happy!}} do_test 4.1 { sqlite3_errcode db } SQLITE_ERROR proc vtab_command {lVal method args} { switch -- $method { xConnect { return $lVal } } return {} } do_catchsql_test 4.2 { CREATE VIRTUAL TABLE y1 USING tcl(vtab_command "PRAGMA page_size=1024"); } {1 {declare_vtab: syntax error}} do_catchsql_test 4.3 { CREATE VIRTUAL TABLE y1 USING tcl(vtab_command "CREATE TABLE x1("); } {1 {declare_vtab: incomplete input}} do_catchsql_test 4.4 { CREATE VIRTUAL TABLE y1 USING tcl(vtab_command "CREATE TABLE x1(insert)"); } {1 {declare_vtab: near "insert": syntax error}} finish_test