mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Merge trunk enhancements into the begin-concurrent branch.
FossilOrigin-Name: 85054a8691cec593b0490b78715a506f25a8cbe04cbf673129c0e17f7f5fa912
This commit is contained in:
@@ -969,4 +969,13 @@ foreach {tn file rc} {
|
||||
db2 close
|
||||
}
|
||||
|
||||
# 2021-01-31 https://sqlite.org/forum/forumpost/8b39fbf3e7
|
||||
#
|
||||
do_test backup-11.1 {
|
||||
sqlite3 db1 :memory:
|
||||
sqlite3 db2 :memory:
|
||||
sqlite3_backup B db1 main db2 temp
|
||||
B finish
|
||||
} {SQLITE_OK}
|
||||
|
||||
finish_test
|
||||
|
@@ -29,7 +29,10 @@ proc vtab_command {method args} {
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set clist [lindex $args 0]
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
|
||||
if {[llength $clist]!=1} { error "unexpected constraint list" }
|
||||
catch { array unset C }
|
||||
array set C [lindex $clist 0]
|
||||
@@ -76,10 +79,13 @@ proc t1_vtab {mode method args} {
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
|
||||
set SQL_FILTER {SELECT * FROM t1x WHERE a='%1%'}
|
||||
set SQL_SCAN {SELECT * FROM t1x}
|
||||
|
||||
set clist [lindex $args 0]
|
||||
set idx 0
|
||||
for {set idx 0} {$idx < [llength $clist]} {incr idx} {
|
||||
array unset C
|
||||
@@ -177,7 +183,10 @@ proc vtab_command {method args} {
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set clist [lindex $args 0]
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
|
||||
#puts $clist
|
||||
set W [list]
|
||||
set U [list]
|
||||
@@ -287,12 +296,17 @@ proc vtab_command {method args} {
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set clist [lindex $args 0]
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
|
||||
lappend ::bestindex_calls $clist
|
||||
set ret "cost 1000000 idxnum 555"
|
||||
for {set i 0} {$i < [llength $clist]} {incr i} {
|
||||
array set C [lindex $clist $i]
|
||||
if {$C(usable)} { lappend ret use $i }
|
||||
if {$C(usable)} {
|
||||
lappend ret use $i
|
||||
}
|
||||
}
|
||||
return $ret
|
||||
}
|
||||
|
@@ -47,7 +47,10 @@ proc vtab_cmd {tbl cols method args} {
|
||||
return "CREATE TABLE $tbl ([join $cols ,])"
|
||||
}
|
||||
xBestIndex {
|
||||
foreach {clist orderby mask} $args {}
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
set mask [$hdl mask]
|
||||
|
||||
set cons [list]
|
||||
set used [list]
|
||||
|
@@ -34,7 +34,10 @@ proc vtab_cmd {bOmit method args} {
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
foreach {clist orderby mask} $args {}
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
set mask [$hdl mask]
|
||||
|
||||
set ret [list]
|
||||
set use use
|
||||
|
@@ -48,7 +48,10 @@ proc vtab_cmd {param method args} {
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
foreach {clist orderby mask} $args {}
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
set mask [$hdl mask]
|
||||
|
||||
set ret [list]
|
||||
|
||||
@@ -135,7 +138,11 @@ proc vtab_command {method args} {
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set clist [lindex $args 0]
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
set mask [$hdl mask]
|
||||
|
||||
if {[llength $clist]!=1} { error "unexpected constraint list" }
|
||||
catch { array unset C }
|
||||
array set C [lindex $clist 0]
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix bestindex4
|
||||
set testprefix bestindex5
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
@@ -44,7 +44,10 @@ proc vtab_cmd {method args} {
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
foreach {clist orderby mask} $args {}
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
set mask [$hdl mask]
|
||||
|
||||
set cost 1000000.0
|
||||
set ret [list]
|
||||
|
@@ -28,7 +28,11 @@ proc vtab_command {src method args} {
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set clist [lindex $args 0]
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
set mask [$hdl mask]
|
||||
|
||||
set wlist 1
|
||||
|
||||
set iCons 0
|
||||
|
@@ -28,7 +28,11 @@ proc vtab_command {src method args} {
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set clist [lindex $args 0]
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
set mask [$hdl mask]
|
||||
|
||||
set iCons 0
|
||||
set ret [list]
|
||||
foreach cons $clist {
|
||||
|
463
test/bestindex8.test
Normal file
463
test/bestindex8.test
Normal file
@@ -0,0 +1,463 @@
|
||||
# 2020-01-29
|
||||
#
|
||||
# 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 bestindex8
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
register_tcl_module db
|
||||
|
||||
proc vtab_command {src method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE xxx(a, b)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
lappend ::lBestIndexDistinct [$hdl distinct]
|
||||
|
||||
#puts "ORDERBY: $orderby"
|
||||
set iCons 0
|
||||
set ret [list]
|
||||
foreach cons $clist {
|
||||
catch { array unset C }
|
||||
array set C $cons
|
||||
if {$C(usable)} {
|
||||
lappend ret use $iCons
|
||||
}
|
||||
incr iCons
|
||||
}
|
||||
if {$orderby=="{column 0 desc 0} {column 1 desc 0}"
|
||||
|| $orderby=="{column 0 desc 0}"
|
||||
} {
|
||||
lappend ret orderby 1
|
||||
lappend ret idxnum 1
|
||||
set ::lOrderByConsumed 1
|
||||
}
|
||||
return $ret
|
||||
}
|
||||
|
||||
xFilter {
|
||||
set idxnum [lindex $args 0]
|
||||
if {$idxnum} {
|
||||
return [list sql "SELECT rowid, a, b FROM $src order by 2, 3"]
|
||||
}
|
||||
return [list sql "SELECT rowid, a, b FROM $src"]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
INSERT INTO t1 VALUES('a', 'b'), ('c', 'd');
|
||||
INSERT INTO t1 VALUES('a', 'b'), ('c', 'd');
|
||||
CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
|
||||
|
||||
CREATE TABLE t0(c0);
|
||||
INSERT INTO t0(c0) VALUES (1), (0);
|
||||
}
|
||||
|
||||
foreach {tn sql bDistinct idxinsert bConsumed res} {
|
||||
1 "SELECT a, b FROM vt1" 0 0 0 {a b c d a b c d}
|
||||
2 "SELECT DISTINCT a, b FROM vt1" 2 1 1 {a b c d}
|
||||
3 "SELECT DISTINCT a FROM vt1" 2 1 1 {a c}
|
||||
4 "SELECT DISTINCT b FROM vt1" 2 1 0 {b d}
|
||||
5 "SELECT DISTINCT b FROM vt1 ORDER BY a" 0 1 1 {b d}
|
||||
6 "SELECT DISTINCT t0.c0 FROM vt1, t0 ORDER BY vt1.a" 0 1 1 {1 0}
|
||||
7 "SELECT DISTINCT a, b FROM vt1 ORDER BY a, b" 1 0 1 {a b c d}
|
||||
8 "SELECT DISTINCT a, b FROM vt1 ORDER BY a" 0 1 1 {a b c d}
|
||||
9 "SELECT DISTINCT a FROM vt1 ORDER BY a, b" 0 1 1 {a c}
|
||||
|
||||
10 "SELECT DISTINCT a, b FROM vt1 WHERE b='b'" 2 1 1 {a b}
|
||||
11 "SELECT DISTINCT a, b FROM vt1 WHERE +b='b'" 2 1 1 {a b}
|
||||
} {
|
||||
set ::lBestIndexDistinct ""
|
||||
set ::lOrderByConsumed 0
|
||||
do_execsql_test 1.$tn.1 $sql $res
|
||||
do_test 1.$tn.2 {
|
||||
set ::lBestIndexDistinct
|
||||
} $bDistinct
|
||||
do_test 1.$tn.3 {
|
||||
expr {[lsearch [execsql "explain $sql"] IdxInsert]>=0}
|
||||
} $idxinsert
|
||||
do_test 1.$tn.4 {
|
||||
set ::lOrderByConsumed
|
||||
} $bConsumed
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
register_tcl_module db
|
||||
|
||||
proc vtab_command {src method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE xxx(a, b)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set hdl [lindex $args 0]
|
||||
set ret [list]
|
||||
|
||||
set iCons 0
|
||||
foreach cons [$hdl constraints] {
|
||||
array set C $cons
|
||||
if {($C(op)=="limit" || $C(op)=="offset") && $C(usable)} {
|
||||
lappend ret use $iCons
|
||||
}
|
||||
incr iCons
|
||||
}
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
||||
xFilter {
|
||||
lappend ::lFilterArgs [lindex $args 2]
|
||||
return [list sql "SELECT rowid, a, b FROM $src"]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
|
||||
}
|
||||
|
||||
do_test 2.1 {
|
||||
set ::lFilterArgs [list]
|
||||
execsql { SELECT * FROM vt1 LIMIT 10 }
|
||||
set ::lFilterArgs
|
||||
} {10}
|
||||
|
||||
do_test 2.2 {
|
||||
set ::lFilterArgs [list]
|
||||
execsql { SELECT * FROM vt1 LIMIT 5 OFFSET 50 }
|
||||
set ::lFilterArgs
|
||||
} {{5 50}}
|
||||
|
||||
do_test 2.3 {
|
||||
set ::lFilterArgs [list]
|
||||
execsql { SELECT * FROM vt1 ORDER BY a, b LIMIT 1 OFFSET 1 }
|
||||
set ::lFilterArgs
|
||||
} {{1 1}}
|
||||
|
||||
do_test 2.4 {
|
||||
set ::lFilterArgs [list]
|
||||
execsql { SELECT * FROM vt1 ORDER BY a, +b LIMIT 1 OFFSET 1 }
|
||||
set ::lFilterArgs
|
||||
} {{}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
register_tcl_module db
|
||||
|
||||
proc vtab_command {src method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE xxx(a, b)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set hdl [lindex $args 0]
|
||||
set lCons [$hdl constraints]
|
||||
|
||||
set ret [list]
|
||||
for {set i 0} {$i < [llength $lCons]} {incr i} {
|
||||
array set C [lindex $lCons $i]
|
||||
if {$C(usable)} {
|
||||
lappend ret use $i
|
||||
$hdl in $i 1
|
||||
}
|
||||
}
|
||||
return $ret
|
||||
}
|
||||
|
||||
xFilter {
|
||||
set lArg [lindex $args 2]
|
||||
lappend ::lFilterArg {*}$lArg
|
||||
return [list sql "SELECT rowid, a, b FROM $src"]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
|
||||
}
|
||||
|
||||
foreach {tn sql lfa} {
|
||||
1 "SELECT * FROM vt1 WHERE b IN (10, 20, 30)" {{10 20 30}}
|
||||
2 "SELECT * FROM vt1 WHERE b IN ('abc', 'def')" {{abc def}}
|
||||
3 "SELECT * FROM vt1 WHERE a IS NULL AND b IN ('abc', 'def')" {{} {abc def}}
|
||||
4 "SELECT * FROM vt1 WHERE a IN (1,2,3) AND b IN ('abc', 'def')"
|
||||
{{1 2 3} {abc def}}
|
||||
|
||||
5 "SELECT * FROM vt1
|
||||
WHERE a IN (SELECT 1 UNION SELECT 2) AND b IN ('abc', 'def')"
|
||||
{{1 2} {abc def}}
|
||||
|
||||
6 "SELECT * FROM vt1
|
||||
WHERE b IN ('abc', 'def') AND a IN (SELECT 1 UNION SELECT 2)"
|
||||
{{abc def} {1 2}}
|
||||
} {
|
||||
do_test 3.$tn {
|
||||
set ::lFilterArg [list]
|
||||
execsql $sql
|
||||
set ::lFilterArg
|
||||
} $lfa
|
||||
}
|
||||
|
||||
#explain_i { SELECT * FROM vt1 WHERE b IN (10, 20, 30) }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
register_tcl_module db
|
||||
|
||||
proc vtab_command {src method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE xxx(a, b, c)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set hdl [lindex $args 0]
|
||||
set lCons [$hdl constraints]
|
||||
|
||||
set ret [list]
|
||||
for {set i 0} {$i < [llength $lCons]} {incr i} {
|
||||
lappend ::lBestIndexRhs [$hdl rhs_value $i -]
|
||||
}
|
||||
return $ret
|
||||
}
|
||||
|
||||
xFilter {
|
||||
return [list sql "SELECT rowid, a, b, c FROM $src"]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
|
||||
}
|
||||
|
||||
foreach {tn sql lbir} {
|
||||
1 "SELECT * FROM vt1 WHERE b = 10" {10}
|
||||
2 "SELECT * FROM vt1 WHERE a = 'abc' AND b < 30" {abc 30}
|
||||
3 "SELECT * FROM vt1 WHERE a = 'abc' AND b < 30+2" {abc -}
|
||||
4 "SELECT * FROM vt1 WHERE a IN (1,2,3) AND b < 30+2" {- -}
|
||||
5 "SELECT * FROM vt1 WHERE a IS 111 AND b < 30+2" {111 -}
|
||||
} {
|
||||
do_test 4.$tn {
|
||||
set ::lBestIndexRhs [list]
|
||||
execsql $sql
|
||||
set ::lBestIndexRhs
|
||||
} $lbir
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
db cache size 0
|
||||
register_tcl_module db
|
||||
|
||||
set ::vtab_handle_in 1
|
||||
proc vtab_command {src method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE xxx(a, b, c)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set lCols [list a b c]
|
||||
|
||||
set hdl [lindex $args 0]
|
||||
set lCons [$hdl constraints]
|
||||
set lOrder [$hdl order]
|
||||
|
||||
set L ""
|
||||
set O ""
|
||||
set W [list]
|
||||
set a 0
|
||||
for {set i 0} {$i < [llength $lCons]} {incr i} {
|
||||
array set C [lindex $lCons $i]
|
||||
if {$C(usable)} {
|
||||
if { $C(op)=="eq" } {
|
||||
set bIn 0
|
||||
if {$::vtab_handle_in} { set bIn [$hdl in $i 1] }
|
||||
if {$bIn} {
|
||||
lappend W "[lindex $lCols $C(column)] IN (%I$a%)"
|
||||
} else {
|
||||
lappend W "[lindex $lCols $C(column)] = %$a%"
|
||||
}
|
||||
lappend ret omit $i
|
||||
}
|
||||
if { $C(op)=="limit" } { set L " LIMIT %$a%" ; lappend ret use $i }
|
||||
if { $C(op)=="offset" } { set O " OFFSET %$a%" ; lappend ret use $i }
|
||||
incr a
|
||||
}
|
||||
}
|
||||
|
||||
set order ""
|
||||
set selectlist "rowid, a, b, c"
|
||||
if {[llength $lOrder]} {
|
||||
array set sl [list]
|
||||
set lO [list]
|
||||
foreach s $lOrder {
|
||||
array set C $s
|
||||
set ad ""
|
||||
if {$C(desc)} { set ad " DESC" }
|
||||
lappend lO "[lindex $lCols $C(column)]$ad"
|
||||
set sl($C(column)) 1
|
||||
}
|
||||
if {[$hdl distinct]==2} {
|
||||
set selectlist "DISTINCT 0"
|
||||
foreach i {0 1 2} {
|
||||
if {[info exists sl($i)]} {
|
||||
append selectlist ", [lindex $lCols $i]"
|
||||
} else {
|
||||
append selectlist ", 0"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
set order " ORDER BY [join $lO ,]"
|
||||
}
|
||||
}
|
||||
|
||||
set where ""
|
||||
if {[llength $W]} { set where " WHERE [join $W { AND }]" }
|
||||
set sql "SELECT $selectlist FROM $src$where$order$L$O"
|
||||
|
||||
lappend ret idxStr $sql
|
||||
return $ret
|
||||
}
|
||||
|
||||
xFilter {
|
||||
foreach {idxnum idxstr lArg} $args {}
|
||||
set ii 0
|
||||
set sql $idxstr
|
||||
foreach a $lArg {
|
||||
set sql [string map [list %$ii% $a] $sql]
|
||||
set sql [string map [list %I$ii% [join $a ,]] $sql]
|
||||
incr ii
|
||||
}
|
||||
lappend ::lFilterSql $sql
|
||||
|
||||
if {[regexp {OFFSET (.*)$} $sql -> off]} {
|
||||
set real_sql "
|
||||
WITH c(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM c WHERE i<$off )
|
||||
SELECT 0,0,0,0 FROM c
|
||||
UNION ALL SELECT * FROM (
|
||||
$sql
|
||||
)
|
||||
"
|
||||
} else {
|
||||
set real_sql $sql
|
||||
}
|
||||
|
||||
return [list sql $real_sql]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t1 VALUES(2, 3, 4);
|
||||
INSERT INTO t1 VALUES(3, 4, 5);
|
||||
INSERT INTO t1 VALUES(1, 5, 6);
|
||||
INSERT INTO t1 VALUES(2, 6, 7);
|
||||
INSERT INTO t1 VALUES(3, 7, 8);
|
||||
INSERT INTO t1 VALUES(1, 8, 9);
|
||||
INSERT INTO t1 VALUES(2, 9, 0);
|
||||
}
|
||||
|
||||
proc do_vtab_test {tn sql vtsql {res {}}} {
|
||||
set ::lFilterSql [list]
|
||||
uplevel [list do_execsql_test $tn.1 $sql $res]
|
||||
uplevel [list do_test $tn.2 {set ::lFilterSql} [list {*}$vtsql]]
|
||||
}
|
||||
|
||||
do_vtab_test 5.1.1 {
|
||||
SELECT DISTINCT a FROM vt1
|
||||
} {
|
||||
{SELECT DISTINCT 0, a, 0, 0 FROM t1}
|
||||
} {1 2 3}
|
||||
|
||||
do_vtab_test 5.1.2 {
|
||||
SELECT DISTINCT a FROM vt1 ORDER BY a
|
||||
} {
|
||||
{SELECT rowid, a, b, c FROM t1 ORDER BY a}
|
||||
} {1 2 3}
|
||||
|
||||
do_vtab_test 5.1.3 {
|
||||
SELECT DISTINCT a FROM vt1 WHERE c IN (4,5,6,7,8)
|
||||
} {
|
||||
{SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c IN (4,5,6,7,8)}
|
||||
} {2 3 1}
|
||||
|
||||
set ::vtab_handle_in 0
|
||||
do_vtab_test 5.1.4 {
|
||||
SELECT DISTINCT a FROM vt1 WHERE c IN (4,5,6,7,8)
|
||||
} {
|
||||
{SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c = 4}
|
||||
{SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c = 5}
|
||||
{SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c = 6}
|
||||
{SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c = 7}
|
||||
{SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c = 8}
|
||||
} {2 3 1}
|
||||
|
||||
set ::vtab_handle_in 1
|
||||
do_vtab_test 5.1.5a {
|
||||
SELECT a, b, c FROM vt1 WHERE c IN (4,5,6,7,8) LIMIT 2 OFFSET 2
|
||||
} {
|
||||
{SELECT rowid, a, b, c FROM t1 WHERE c IN (4,5,6,7,8) LIMIT 2 OFFSET 2}
|
||||
} {1 5 6 2 6 7}
|
||||
|
||||
set ::vtab_handle_in 0
|
||||
do_vtab_test 5.1.5b {
|
||||
SELECT a, b, c FROM vt1 WHERE c IN (4,5,6,7,8) LIMIT 2 OFFSET 2
|
||||
} {
|
||||
{SELECT rowid, a, b, c FROM t1 WHERE c = 4}
|
||||
{SELECT rowid, a, b, c FROM t1 WHERE c = 5}
|
||||
{SELECT rowid, a, b, c FROM t1 WHERE c = 6}
|
||||
{SELECT rowid, a, b, c FROM t1 WHERE c = 7}
|
||||
} {1 5 6 2 6 7}
|
||||
set ::vtab_handle_in 1
|
||||
|
||||
finish_test
|
149
test/date3.test
Normal file
149
test/date3.test
Normal file
@@ -0,0 +1,149 @@
|
||||
# 2022-01-27
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing date and time functions.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Skip this whole file if date and time functions are omitted
|
||||
# at compile-time
|
||||
#
|
||||
ifcapable {!datetime} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc datetest {tnum expr result} {
|
||||
do_test date3-$tnum [subst {
|
||||
execsql "SELECT coalesce($expr,'NULL')"
|
||||
}] [list $result]
|
||||
}
|
||||
set tcl_precision 15
|
||||
|
||||
# EVIDENCE-OF: R-45708-63005 unixepoch(time-value, modifier, modifier,
|
||||
# ...)
|
||||
#
|
||||
datetest 1.1 {unixepoch('1970-01-01')} {0}
|
||||
datetest 1.2 {unixepoch('1969-12-31 23:59:59')} {-1}
|
||||
datetest 1.3 {unixepoch('2106-02-07 06:28:15')} {4294967295}
|
||||
datetest 1.4 {unixepoch('2106-02-07 06:28:16')} {4294967296}
|
||||
datetest 1.5 {unixepoch('9999-12-31 23:59:59')} {253402300799}
|
||||
datetest 1.6 {unixepoch('0000-01-01 00:00:00')} {-62167219200}
|
||||
|
||||
# EVIDENCE-OF: R-30877-63179 The unixepoch() function returns a unix
|
||||
# timestamp - the number of seconds since 1970-01-01 00:00:00 UTC.
|
||||
#
|
||||
for {set i 1} {$i<=100} {incr i} {
|
||||
set x [expr {int(rand()*0xfffffffff)-0xffffffff}]
|
||||
datetest 1.7.$i "unixepoch($x,'unixepoch')==$x" {1}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-62992-54137 The unixepoch() always returns an integer,
|
||||
# even if the input time-value has millisecond precision.
|
||||
#
|
||||
datetest 1.8 {unixepoch('2022-01-27 12:59:28.052')} {1643288368}
|
||||
|
||||
# EVIDENCE-OF: R-05412-24332 If the time-value is numeric (the
|
||||
# DDDDDDDDDD format) then the 'auto' modifier causes the time-value to
|
||||
# interpreted as either a julian day number or a unix timestamp,
|
||||
# depending on its magnitude.
|
||||
#
|
||||
# EVIDENCE-OF: R-56763-40111 If the value is between 0.0 and
|
||||
# 5373484.499999, then it is interpreted as a julian day number
|
||||
# (corresponding to dates between -4713-11-24 12:00:00 and 9999-12-31
|
||||
# 23:59:59, inclusive).
|
||||
#
|
||||
# EVIDENCE-OF: R-07289-49223 For numeric values outside of the range of
|
||||
# valid julian day numbers, but within the range of -210866760000 to
|
||||
# 253402300799, the 'auto' modifier causes the value to be interpreted
|
||||
# as a unix timestamp.
|
||||
#
|
||||
# EVIDENCE-OF: R-20795-34947 Other numeric values are out of range and
|
||||
# cause a NULL return.
|
||||
#
|
||||
foreach {tn jd date} {
|
||||
2.1 0.0 {-4713-11-24 12:00:00}
|
||||
2.2 5373484.4999999 {9999-12-31 23:59:59}
|
||||
2.3 2440587.5 {1970-01-01 00:00:00}
|
||||
2.4 2440587.49998843 {1969-12-31 23:59:59}
|
||||
2.5 2440615.7475463 {1970-01-29 05:56:28}
|
||||
|
||||
2.10 -1 {1969-12-31 23:59:59}
|
||||
2.11 5373485 {1970-03-04 04:38:05}
|
||||
2.12 -210866760000 {-4713-11-24 12:00:00}
|
||||
2.13 253402300799 {9999-12-31 23:59:59}
|
||||
|
||||
2.20 -210866760001 {NULL}
|
||||
2.21 253402300800 {NULL}
|
||||
} {
|
||||
datetest $tn "datetime($jd,'auto')" $date
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-38886-35357 The 'auto' modifier is a no-op for text
|
||||
# time-values.
|
||||
#
|
||||
datetest 2.30 {date('2022-01-29','auto')==date('2022-01-29')} {1}
|
||||
|
||||
# EVIDENCE-OF: R-53132-26856 The 'auto' modifier can be used to work
|
||||
# with date/time values even in cases where it is not known if the
|
||||
# julian day number or unix timestamp formats are in use.
|
||||
#
|
||||
do_execsql_test date3-2.40 {
|
||||
WITH tx(timeval,datetime) AS (
|
||||
VALUES('2022-01-27 13:15:44','2022-01-27 13:15:44'),
|
||||
(2459607.05260275,'2022-01-27 13:15:44'),
|
||||
(1643289344,'2022-01-27 13:15:44')
|
||||
)
|
||||
SELECT datetime(timeval,'auto') == datetime FROM tx;
|
||||
} {1 1 1}
|
||||
|
||||
# EVIDENCE-OF: R-49255-55373 The "unixepoch" modifier (11) only works if
|
||||
# it immediately follows a time value in the DDDDDDDDDD format.
|
||||
#
|
||||
# EVIDENCE-OF: R-23075-39245 This modifier causes the DDDDDDDDDD to be
|
||||
# interpreted not as a Julian day number as it normally would be, but as
|
||||
# Unix Time - the number of seconds since 1970.
|
||||
#
|
||||
datetest 3.1 {datetime(2459607.05,'+1 hour','unixepoch')} {NULL}
|
||||
datetest 3.2 {datetime(2459607.05,'unixepoch','+1 hour')} {1970-01-29 12:13:27}
|
||||
|
||||
# EVIDENCE-OF: R-21150-52363 The "julianday" modifier must immediately
|
||||
# follow the initial time-value which must be of the form DDDDDDDDD.
|
||||
#
|
||||
# EVIDENCE-OF: R-31176-64601 Any other use of the 'julianday' modifier
|
||||
# is an error and causes the function to return NULL.
|
||||
#
|
||||
# EVIDENCE-OF: R-32483-36353 The 'julianday' modifier forces the
|
||||
# time-value number to be interpreted as a julian-day number.
|
||||
#
|
||||
# EVIDENCE-OF: R-25859-20124 The only difference is that adding
|
||||
# 'julianday' forces the DDDDDDDDD time-value format, and causes a NULL
|
||||
# to be returned if any other time-value format is used.
|
||||
#
|
||||
datetest 4.1 {datetime(2459607,'julianday')} {2022-01-27 12:00:00}
|
||||
datetest 4.2 {datetime(2459607,'+1 hour','julianday')} {NULL}
|
||||
datetest 4.3 {datetime('2022-01-27','julianday')} {NULL}
|
||||
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-33431-18865 Unix timestamps for the first 63 days of
|
||||
# 1970 will be interpreted as julian day numbers.
|
||||
#
|
||||
do_execsql_test date3-5.0 {
|
||||
WITH inc(x) AS (VALUES(-10) UNION ALL SELECT x+1 FROM inc WHERE x<100)
|
||||
SELECT count(*) FROM inc
|
||||
WHERE datetime('1970-01-01',format('%+d days',x))
|
||||
<> datetime(unixepoch('1970-01-01',format('%+d days',x)),'auto');
|
||||
} {63}
|
||||
|
||||
finish_test
|
@@ -328,4 +328,18 @@ do_execsql_test 8.1 {
|
||||
2 10 2
|
||||
}
|
||||
|
||||
|
||||
# 2022-01-31 dbsqlfuzz 787d9bd73164c6f0c85469e2e48b2aff19af6938
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 9.1 {
|
||||
CREATE TABLE t1(a ,b FLOAT);
|
||||
INSERT INTO t1 VALUES(1,1);
|
||||
CREATE INDEX t1x1 ON t1(a,b,a,a,a,a,a,a,a,a,a,b);
|
||||
ANALYZE sqlite_schema;
|
||||
INSERT INTO sqlite_stat1 VALUES('t1','t1x1','648 324 81 81 81 81 81 81 81081 81 81 81');
|
||||
ANALYZE sqlite_schema;
|
||||
SELECT a FROM (SELECT a FROM t1 NATURAL LEFT JOIN t1) NATURAL LEFT JOIN t1 WHERE (rowid,1)<=(5,0);
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
@@ -15,11 +15,6 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !json1 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test json101-1.1.00 {
|
||||
SELECT json_array(1,2.5,null,'hello');
|
||||
} {[1,2.5,null,"hello"]}
|
||||
@@ -846,5 +841,13 @@ do_execsql_test json-16.30 {
|
||||
SELECT unicode(json_extract('"\uD834\uDD1E"','$'));
|
||||
} {119070}
|
||||
|
||||
# 2022-01-30 dbsqlfuzz 4678cf825d27f87c9b8343720121e12cf944b71a
|
||||
do_execsql_test json-17.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(a,b,c);
|
||||
CREATE TABLE t2(d);
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON (SELECT b FROM json_each ORDER BY 1);
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
@@ -18,11 +18,6 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !json1 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test json102-100 {
|
||||
SELECT json_object('ex','[52,3.14159]');
|
||||
} {{{"ex":"[52,3.14159]"}}}
|
||||
|
@@ -14,11 +14,6 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !json1 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test json103-100 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<100)
|
||||
|
@@ -15,11 +15,6 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix json104
|
||||
|
||||
ifcapable !json1 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# This is the example from pages 2 and 3 of RFC-7396
|
||||
do_execsql_test json104-100 {
|
||||
SELECT json_patch('{
|
||||
|
@@ -15,11 +15,6 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix json104
|
||||
|
||||
ifcapable !json1 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# This is the example from pages 2 and 3 of RFC-7396
|
||||
db eval {
|
||||
CREATE TABLE t1(j);
|
||||
|
@@ -708,5 +708,23 @@ do_execsql_test 31.2 {
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON b=NULL WHERE (c,d)==(SELECT 123, 456+a);
|
||||
} {}
|
||||
|
||||
# 2022-02-03 dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1
|
||||
reset_db
|
||||
do_execsql_test 32.1 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT);
|
||||
CREATE TABLE t2(d INTEGER PRIMARY KEY);
|
||||
INSERT INTO t1(a,b,c) VALUES(500,654,456);
|
||||
INSERT INTO t1(a,b,c) VALUES(501,655,456);
|
||||
INSERT INTO t1(a,b,c) VALUES(502,654,122);
|
||||
INSERT INTO t1(a,b,c) VALUES(503,654,221);
|
||||
INSERT INTO t1(a,b,c) VALUES(601,654,122);
|
||||
INSERT INTO t2(d) VALUES(456);
|
||||
INSERT INTO t2(d) VALUES(122);
|
||||
SELECT a FROM (
|
||||
SELECT t1.a FROM t2, t1
|
||||
WHERE (987, t1.b) = ( SELECT 987, 654 ) AND t2.d=t1.c
|
||||
) AS t3
|
||||
WHERE a=1234 OR a<=567;
|
||||
} {500 502}
|
||||
|
||||
finish_test
|
||||
|
@@ -46,7 +46,9 @@ proc vtab_command {method args} {
|
||||
set OP(glob) GLOB
|
||||
set OP(regexp) REGEXP
|
||||
|
||||
set clist [lindex $args 0]
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
|
||||
set ret [list]
|
||||
set elist [list]
|
||||
set i 0
|
||||
|
@@ -205,10 +205,10 @@ do_test shell1-2.2.4 {
|
||||
} {0 {}}
|
||||
do_test shell1-2.2.5 {
|
||||
catchcmd "test.db" ".mode \"insert FOO"
|
||||
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
|
||||
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}}
|
||||
do_test shell1-2.2.6 {
|
||||
catchcmd "test.db" ".mode \'insert FOO"
|
||||
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
|
||||
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}}
|
||||
|
||||
# check multiple tokens, and quoted tokens
|
||||
do_test shell1-2.3.1 {
|
||||
@@ -236,7 +236,7 @@ do_test shell1-2.3.7 {
|
||||
# check quoted args are unquoted
|
||||
do_test shell1-2.4.1 {
|
||||
catchcmd "test.db" ".mode FOO"
|
||||
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
|
||||
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}}
|
||||
do_test shell1-2.4.2 {
|
||||
catchcmd "test.db" ".mode csv"
|
||||
} {0 {}}
|
||||
@@ -437,7 +437,7 @@ do_test shell1-3.13.1 {
|
||||
} {0 {current output mode: list}}
|
||||
do_test shell1-3.13.2 {
|
||||
catchcmd "test.db" ".mode FOO"
|
||||
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
|
||||
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}}
|
||||
do_test shell1-3.13.3 {
|
||||
catchcmd "test.db" ".mode csv"
|
||||
} {0 {}}
|
||||
@@ -467,17 +467,6 @@ do_test shell1-3.13.11 {
|
||||
catchcmd "test.db" ".mode tcl BAD"
|
||||
} {0 {}}
|
||||
|
||||
# don't allow partial mode type matches
|
||||
do_test shell1-3.13.12 {
|
||||
catchcmd "test.db" ".mode l"
|
||||
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
|
||||
do_test shell1-3.13.13 {
|
||||
catchcmd "test.db" ".mode li"
|
||||
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown quote table tabs tcl}}
|
||||
do_test shell1-3.13.14 {
|
||||
catchcmd "test.db" ".mode lin"
|
||||
} {0 {}}
|
||||
|
||||
# .nullvalue STRING Print STRING in place of NULL values
|
||||
do_test shell1-3.14.1 {
|
||||
catchcmd "test.db" ".nullvalue"
|
||||
|
Reference in New Issue
Block a user