Merge sqlite-release(3.15.2) into prerelease-integration

This commit is contained in:
Nick Parker
2016-12-06 13:10:27 -06:00
471 changed files with 45126 additions and 8286 deletions
+6 -6
View File
@@ -184,7 +184,7 @@ do_test alter3-3.2 {
if {!$has_codec} {
do_test alter3-3.3 {
get_file_format
} {4}
} {3}
}
ifcapable schema_version {
do_test alter3-3.4 {
@@ -220,7 +220,7 @@ do_test alter3-4.2 {
if {!$has_codec} {
do_test alter3-4.3 {
get_file_format
} {4}
} {3}
}
ifcapable schema_version {
do_test alter3-4.4 {
@@ -270,7 +270,7 @@ ifcapable attach {
if {!$has_codec} {
do_test alter3-5.5 {
list [get_file_format test2.db] [get_file_format]
} {4 4}
} {3 3}
}
do_test alter3-5.6 {
execsql {
@@ -347,19 +347,19 @@ if {!$has_codec} {
ALTER TABLE abc ADD d DEFAULT NULL;
}
get_file_format
} {4}
} {3}
do_test alter3-7.3 {
execsql {
ALTER TABLE abc ADD e DEFAULT 10;
}
get_file_format
} {4}
} {3}
do_test alter3-7.4 {
execsql {
ALTER TABLE abc ADD f DEFAULT NULL;
}
get_file_format
} {4}
} {3}
do_test alter3-7.5 {
execsql {
VACUUM;
+19
View File
@@ -355,4 +355,23 @@ do_execsql_test alter4-9.3 {
SELECT typeof(c), c FROM t5;
} {real 9.22337203685478e+18}
# Confirm that doing an ALTER TABLE on a legacy format database
# does not corrupt DESC indexes.
#
# Ticket https://www.sqlite.org/src/tktview/f68bf68513a1c
#
do_test alter4-10.1 {
db close
sqlite3 db :memory:
db eval {
PRAGMA legacy_file_format=on;
CREATE TABLE t1(a,b,c);
CREATE INDEX t1a ON t1(a DESC);
INSERT INTO t1 VALUES(1,2,3);
INSERT INTO t1 VALUES(2,3,4);
ALTER TABLE t1 ADD COLUMN d;
PRAGMA integrity_check;
}
} {ok}
finish_test
+1 -1
View File
@@ -1180,7 +1180,7 @@ do_execsql_test 26.1.3 {
#
# There should be no other samples that start with (x=10000). So it knows
# that (x=10000 AND y<50) must match somewhere between 0 and 99 rows, but
# know more than that. Guessing less than 20 is therefore unreasonable.
# no more than that. Guessing less than 20 is therefore unreasonable.
#
# At one point though, due to a problem in whereKeyStats(), the planner was
# estimating that (x=10000 AND y<50) would match only 2 rows.
+2 -3
View File
@@ -1,4 +1,4 @@
# 2005 July 22
# 2014-10-04
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
@@ -11,7 +11,6 @@
# This file implements regression tests for SQLite library.
# This file implements tests for the ANALYZE command.
#
# $Id: analyze.test,v 1.9 2008/08/11 18:44:58 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -75,7 +74,7 @@ do_test 1.3 {
} {}
# Without stat1, because 3001 is larger than all samples in the stat4
# table, SQLite things that a=3001 matches just 1 row. So it (incorrectly)
# table, SQLite thinks that a=3001 matches just 1 row. So it (incorrectly)
# chooses it over the c=150 index (5 rows). Even with stat1 data, things
# worked this way before commit [e6f7f97dbc].
#
+6 -3
View File
@@ -25,9 +25,12 @@ if {$tcl_platform(platform)=="windows"} {
set PROG "./sqlite3_analyzer"
}
if {![file exe $PROG]} {
puts "analyzer1 cannot run because $PROG is not available"
finish_test
return
set PROG [file normalize [file join $::cmdlinearg(TESTFIXTURE_HOME) $PROG]]
if {![file exe $PROG]} {
puts "analyzer1 cannot run because $PROG is not available"
finish_test
return
}
}
db close
forcedelete test.db test.db-journal test.db-wal
+47 -2
View File
@@ -2432,8 +2432,53 @@ do_test auth-6.3 {
execsql {SELECT rowid, * FROM t6}
} {101 1 2 3 4 5 6 7 8}
#-------------------------------------------------------------------------
# Test that view names are included as zArg4.
#
do_execsql_test auth-7.1 {
CREATE TABLE t7(a, b, c);
CREATE VIEW v7 AS SELECT * FROM t7;
} {}
set ::authargs [list]
proc auth {args} {
eval lappend ::authargs [lrange $args 0 4]
return SQLITE_OK
}
do_test auth-7.2 {
execsql {SELECT a, c FROM v7}
set ::authargs
} [list \
SQLITE_SELECT {} {} {} {} \
SQLITE_READ t7 a main v7 \
SQLITE_READ t7 b main v7 \
SQLITE_READ t7 c main v7 \
SQLITE_READ v7 a main {} \
SQLITE_READ v7 c main {} \
SQLITE_SELECT {} {} {} v7 \
]
set ::authargs [list]
do_test auth-7.3 {
execsql {SELECT a, c FROM t7}
set ::authargs
} [list \
SQLITE_SELECT {} {} {} {} \
SQLITE_READ t7 a main {} \
SQLITE_READ t7 c main {} \
]
set ::authargs [list]
do_test auth-7.4 {
execsql {SELECT a, c FROM t7 AS v7}
set ::authargs
} [list \
SQLITE_SELECT {} {} {} {} \
SQLITE_READ t7 a main {} \
SQLITE_READ t7 c main {} \
]
rename proc {}
rename proc_real proc
finish_test
-12
View File
@@ -98,12 +98,6 @@ SQLITE_UPDATE sqlite_master tbl_name main {}
SQLITE_UPDATE sqlite_master rootpage main {}
SQLITE_UPDATE sqlite_master sql main {}
SQLITE_READ sqlite_master ROWID main {}
SQLITE_READ sqlite_master name main {}
SQLITE_READ sqlite_master rootpage main {}
SQLITE_READ sqlite_master sql main {}
SQLITE_READ sqlite_master tbl_name main {}
SQLITE_READ sqlite_master type main {}
SQLITE_READ sqlite_master ROWID main {}
}
do_test auth2-2.2 {
set ::authargs {}
@@ -119,12 +113,6 @@ SQLITE_UPDATE sqlite_master tbl_name main {}
SQLITE_UPDATE sqlite_master rootpage main {}
SQLITE_UPDATE sqlite_master sql main {}
SQLITE_READ sqlite_master ROWID main {}
SQLITE_READ sqlite_master name main {}
SQLITE_READ sqlite_master rootpage main {}
SQLITE_READ sqlite_master sql main {}
SQLITE_READ sqlite_master tbl_name main {}
SQLITE_READ sqlite_master type main {}
SQLITE_READ sqlite_master ROWID main {}
}
do_test auth2-2.3 {
set ::authargs {}
+19 -2
View File
@@ -12,8 +12,7 @@
# Test that the truncate optimization is disabled if the SQLITE_DELETE
# authorization callback returns SQLITE_IGNORE.
#
# $Id: auth3.test,v 1.2 2009/05/04 01:58:31 drh Exp $
#
# Test that authorizer is disabled during schema parsing.
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -108,4 +107,22 @@ do_test auth3-2.2 {
set sqlite_search_count
} {1}
# 2016-07-28. A problem report from a private client complaining about
# an authorizer failure during an ALTER TABLE. The solution (I think) is
# to disable the authorizer during schema parsing.
#
proc auth {code args} {
if {$code=="SQLITE_READ" && [regexp {DoNotRead} $args]} {
return SQLITE_DENY
}
return SQLITE_OK
}
do_execsql_test auth3-3.0 {
CREATE TEMPORARY TABLE TempTable (
key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,
value TEXT NOT NULL ON CONFLICT FAIL);
ALTER TABLE TempTable RENAME TO DoNotRead;
SELECT name FROM sqlite_temp_master;
} {DoNotRead sqlite_autoindex_DoNotRead_1}
finish_test
+12
View File
@@ -663,6 +663,18 @@ ifcapable trigger {
} {1 124 2 10123}
}
# 2016-10-03 ticket https://www.sqlite.org/src/tktview/7b3328086a5c1
# Make sure autoincrement plays nicely with the xfer optimization
#
do_execsql_test autoinc-10.1 {
DELETE FROM sqlite_sequence;
CREATE TABLE t10a(a INTEGER PRIMARY KEY AUTOINCREMENT, b UNIQUE);
INSERT INTO t10a VALUES(888,9999);
CREATE TABLE t10b(x INTEGER PRIMARY KEY AUTOINCREMENT, y UNIQUE);
INSERT INTO t10b SELECT * FROM t10a;
SELECT * FROM sqlite_sequence;
} {t10a 888 t10b 888}
finish_test
+6 -1
View File
@@ -218,10 +218,15 @@ do_execsql_test autoindex2-120 {
AND t1.did = t2.did
AND t2.uid = t3.uid
ORDER BY t1.ptime desc LIMIT 500;
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1x1 (ptime>?)} 0 1 1 {SEARCH TABLE t2 USING INDEX t2x0 (did=?)} 0 2 2 {SEARCH TABLE t3 USING INDEX t3x0 (uid=?)}}
} {~/AUTO/}
#
# ^^^--- Before being fixed, the above was using an automatic covering
# on t3 and reordering the tables so that t3 was in the outer loop and
# implementing the ORDER BY clause using a B-Tree.
#
# This test is sanitized data received from a user. The original unsanitized
# data and STAT4 data is found in the th3private test repository. See one of
# the th3private check-ins on 2016-02-25. The test is much more accurate when
# STAT4 data is used.
finish_test
+14 -3
View File
@@ -269,7 +269,7 @@ do_test autovacuum-2.4.3 {
} {3 4 5 6 7 8 9 10}
# Right now there are 5 free pages in the database. Consume and then free
# a 520 pages. Then create 520 tables. This ensures that at least some of the
# all 520 pages. Then create 520 tables. This ensures that at least some of the
# desired root-pages reside on the second free-list trunk page, and that the
# trunk itself is required at some point.
do_test autovacuum-2.4.4 {
@@ -280,9 +280,20 @@ do_test autovacuum-2.4.4 {
} {}
set root_page_list [list]
set pending_byte_page [expr ($::sqlite_pending_byte / 1024) + 1]
# unusable_pages
# These are either the pending_byte page or the pointer map pages
#
unset -nocomplain unusable_page
if {[sqlite3 -has-codec]} {
array set unusable_page {205 1 408 1}
} else {
array set unusable_page {207 1 412 1}
}
set unusable_page($pending_byte_page) 1
for {set i 3} {$i<=532} {incr i} {
# 207 and 412 are pointer-map pages.
if { $i!=207 && $i!=412 && $i != $pending_byte_page} {
if {![info exists unusable_page($i)]} {
lappend root_page_list $i
}
}
+10 -3
View File
@@ -63,7 +63,7 @@ proc do_backcompat_test {rv bin1 bin2 script} {
set v [split [db version] .]
if {[llength $v]==3} {lappend v 0}
set ::sqlite_libversion [format \
"%d%.2d%.2d%2d" [lindex $v 0] [lindex $v 1] [lindex $v 2] [lindex $v 3]
"%d%.2d%.2d%.2d" [lindex $v 0] [lindex $v 1] [lindex $v 2] [lindex $v 3]
]
}
}
@@ -85,7 +85,8 @@ proc do_allbackcompat_test {script} {
set nErr [set_test_counter errors]
foreach dir {0 1} {
set bintag [string map {testfixture {}} $bin]
set bintag $bin
regsub {.*testfixture\.} $bintag {} bintag
set bintag [string map {\.exe {}} $bintag]
if {$bintag == ""} {set bintag self}
set ::bcname ".$bintag.$dir."
@@ -420,6 +421,12 @@ ifcapable fts3 {
if {[code1 { set ::sqlite_libversion }] >=3071200
&& [code2 { set ::sqlite_libversion }] >=3071200
} {
if {[code1 { set ::sqlite_libversion }]<3120000} {
set res {0 {0 1} 1 0}
} else {
set res {1 0}
}
do_test backcompat-3.9 {
sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
sql2 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
@@ -428,7 +435,7 @@ ifcapable fts3 {
sql2 {
SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level;
}
} {0 {0 1} 1 0}
} $res
do_test backcompat-3.10 {
sql1 { INSERT INTO t2(t2) VALUES('integrity-check') }
+10 -11
View File
@@ -164,7 +164,7 @@ foreach zOpenScript [list {
set file_dest temp
}] {
foreach rows_dest {0 3 10} {
foreach pgsz_dest {512 1024 2048} {
foreach pgsz_dest {512 1024 2048 4096} {
foreach nPagePerStep {1 200} {
# Open the databases.
@@ -176,17 +176,16 @@ foreach nPagePerStep {1 200} {
# in-memory destination is only possible if the initial destination
# page size is the same as the source page size (in this case 1024 bytes).
#
set isMemDest [expr {
$zDestFile eq ":memory:" || $file_dest eq "temp" && $TEMP_STORE>=2
}]
set isMemDest [expr { $zDestFile eq ":memory:" || $file_dest eq "temp" }]
if { $isMemDest==0 || $pgsz_dest == 1024 } {
if 0 {
puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
puts -nonewline " (as $db_dest.$file_dest)"
puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
puts ""
}
if 0 {
puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
puts -nonewline " (as $db_dest.$file_dest)"
puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
puts ""
}
if { $isMemDest==0 || $pgsz_dest==1024 || $rows_dest==0 } {
# Set up the content of the source database.
execsql {
+5
View File
@@ -23,6 +23,11 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix backup4
# The codec logic does not work for zero-length database files. A database
# file must contain at least one page in order to be recognized as an
# encrypted database.
do_not_use_codec
#-------------------------------------------------------------------------
# At one point this test was failing because [db] was using an out of
# date schema in test case 1.2.
+32
View File
@@ -84,4 +84,36 @@ do_malloc_test backup_malloc-2 -tclprep {
db2 close
}
reset_db
do_execsql_test 3.0 {
PRAGMA page_size = 16384;
BEGIN;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
COMMIT;
}
do_faultsim_test 3 -faults oom* -prep {
catch { db close }
catch { db2 close }
forcedelete test2.db
sqlite3 db2 test2.db
sqlite3 db test.db
sqlite3_backup B db2 main db main
} -body {
set rc [B step 50]
if {$rc == "SQLITE_NOMEM" || $rc == "SQLITE_IOERR_NOMEM"} {
error "out of memory"
}
} -test {
faultsim_test_result {0 {}}
faultsim_integrity_check
# Finalize the backup.
catch { B finish }
}
finish_test
+3 -2
View File
@@ -7,7 +7,7 @@ proc bc_find_binaries {zCaption} {
# against.
#
set binaries [list]
set self [file tail [info nameofexec]]
set self [info nameofexec]
set pattern "$self?*"
if {$::tcl_platform(platform)=="windows"} {
set pattern [string map {\.exe {}} $pattern]
@@ -52,7 +52,8 @@ proc do_bc_test {bin script} {
code1 { sqlite3 db test.db }
code2 { sqlite3 db test.db }
set bintag [string map {testfixture {}} $bin]
set bintag $bin
regsub {.*testfixture\.} $bintag {} bintag
set bintag [string map {\.exe {}} $bintag]
if {$bintag == ""} {set bintag self}
set saved_prefix $::testprefix
+275
View File
@@ -0,0 +1,275 @@
# 2016-03-01
#
# 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 bestindex1
ifcapable !vtab {
finish_test
return
}
register_tcl_module db
proc vtab_command {method args} {
switch -- $method {
xConnect {
return "CREATE TABLE t1(a, b, c)"
}
xBestIndex {
set clist [lindex $args 0]
if {[llength $clist]!=1} { error "unexpected constraint list" }
catch { array unset C }
array set C [lindex $clist 0]
if {$C(usable)} {
return "omit 0 cost 0 rows 1 idxnum 555 idxstr eq!"
} else {
return "cost 1000000 rows 0 idxnum 0 idxstr scan..."
}
}
}
return {}
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE x1 USING tcl(vtab_command);
} {}
do_eqp_test 1.1 {
SELECT * FROM x1 WHERE a = 'abc'
} {
0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
}
do_eqp_test 1.2 {
SELECT * FROM x1 WHERE a IN ('abc', 'def');
} {
0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
0 0 0 {EXECUTE LIST SUBQUERY 1}
}
#-------------------------------------------------------------------------
#
reset_db
register_tcl_module db
# Parameter $mode may be one of:
#
# "omit" - Implement filtering. Set the omit flag.
# "use" - Implement filtering. Use the constraint, but do not set omit.
# "use2" - Do not implement filtering. Use the constraint anyway.
#
#
proc t1_vtab {mode method args} {
switch -- $method {
xConnect {
return "CREATE TABLE t1(a, b)"
}
xBestIndex {
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
array set C [lindex $clist $idx]
if {$C(column)==0 && $C(op)=="eq" && $C(usable)} {
switch -- $mode {
"omit" {
return [list omit $idx rows 10 cost 10 idxstr $SQL_FILTER]
}
"use" {
return [list use $idx rows 10 cost 10 idxstr $SQL_FILTER]
}
"use2" {
return [list use $idx rows 10 cost 10 idxstr $SQL_SCAN]
}
default {
error "Bad mode - $mode"
}
}
}
}
return [list idxstr {SELECT * FROM t1x}]
}
xFilter {
set map [list %1% [lindex $args 2 0]]
set sql [string map $map [lindex $args 1]]
return [list sql $sql]
}
}
return {}
}
do_execsql_test 2.1 {
CREATE TABLE t1x(i INTEGER PRIMARY KEY, a, b);
INSERT INTO t1x VALUES(1, 'one', 1);
INSERT INTO t1x VALUES(2, 'two', 2);
INSERT INTO t1x VALUES(3, 'three', 3);
INSERT INTO t1x VALUES(4, 'four', 4);
}
foreach {tn mode} {
1 use 2 omit 3 use2
} {
do_execsql_test 2.2.$mode.1 "
DROP TABLE IF EXISTS t1;
CREATE VIRTUAL TABLE t1 USING tcl(t1_vtab $mode);
"
do_execsql_test 2.2.$mode.2 {SELECT * FROM t1} {one 1 two 2 three 3 four 4}
do_execsql_test 2.2.$mode.3 {SELECT rowid FROM t1} {1 2 3 4}
do_execsql_test 2.2.$mode.4 {SELECT rowid FROM t1 WHERE a='two'} {2}
do_execsql_test 2.2.$mode.5 {
SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
} {1 4}
set plan(use) {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'}
0 0 0 {EXECUTE LIST SUBQUERY 1}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
set plan(omit) {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'}
0 0 0 {EXECUTE LIST SUBQUERY 1}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
set plan(use2) {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x}
0 0 0 {EXECUTE LIST SUBQUERY 1}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
do_eqp_test 2.2.$mode.6 {
SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
} $plan($mode)
}
# 2016-04-09.
# Demonstrate a register overwrite problem when using two virtual
# tables where the outer loop uses the IN operator.
#
set G(collist) [list PrimaryKey flagA columnA]
set G(cols) [join $G(collist) ,]
set G(nulls) "NULL"
proc vtab_command {method args} {
global G
switch -- $method {
xConnect {
return "CREATE TABLE t1($G(cols))"
}
xBestIndex {
set clist [lindex $args 0]
#puts $clist
set W [list]
set U [list]
set i 0
for {set idx 0} {$idx < [llength $clist]} {incr idx} {
array set c [lindex $clist $idx]
if {$c(op)=="eq" && $c(usable)} {
lappend W "[lindex $G(collist) $c(column)] = %$i%"
lappend U use $idx
incr i
}
}
if {$W==""} {
set sql "SELECT rowid, * FROM t1"
} else {
set sql "SELECT rowid, * FROM t1 WHERE [join $W { AND }]"
}
return [concat [list idxstr $sql] $U]
}
xFilter {
foreach {idxnum idxstr vals} $args {}
set map [list]
for {set i 0} {$i < [llength $vals]} {incr i} {
lappend map "%$i%"
set v [lindex $vals $i]
if {[string is integer $v]} {
lappend map $v
} else {
lappend map "'$v'"
}
}
set sql [string map $map $idxstr]
#puts "SQL: $sql"
return [list sql $sql]
}
}
return {}
}
db close
forcedelete test.db
sqlite3 db test.db
register_tcl_module db
do_execsql_test 3.1 "
CREATE TABLE t1($G(cols));
INSERT INTO t1 VALUES(1, 0, 'ValueA');
INSERT INTO t1 VALUES(2, 0, 'ValueA');
INSERT INTO t1 VALUES(3, 0, 'ValueB');
INSERT INTO t1 VALUES(4, 0, 'ValueB');
"
do_execsql_test 3.2 {
CREATE VIRTUAL TABLE VirtualTableA USING tcl(vtab_command);
CREATE VIRTUAL TABLE VirtualTableB USING tcl(vtab_command);
}
do_execsql_test 3.3 { SELECT primarykey FROM VirtualTableA } {1 2 3 4}
do_execsql_test 3.4 {
SELECT * FROM
VirtualTableA a CROSS JOIN VirtualTableB b ON b.PrimaryKey=a.PrimaryKey
WHERE a.ColumnA IN ('ValueA', 'ValueB') AND a.FlagA=0
} {
1 0 ValueA 1 0 ValueA
2 0 ValueA 2 0 ValueA
3 0 ValueB 3 0 ValueB
4 0 ValueB 4 0 ValueB
}
do_execsql_test 3.5 {
SELECT * FROM
VirtualTableA a CROSS JOIN VirtualTableB b ON b.PrimaryKey=a.PrimaryKey
WHERE a.FlagA=0 AND a.ColumnA IN ('ValueA', 'ValueB')
} {
1 0 ValueA 1 0 ValueA
2 0 ValueA 2 0 ValueA
3 0 ValueB 3 0 ValueB
4 0 ValueB 4 0 ValueB
}
finish_test
+141
View File
@@ -0,0 +1,141 @@
# 2016 March 3
#
# 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 bestindex2
ifcapable !vtab {
finish_test
return
}
#-------------------------------------------------------------------------
# Virtual table callback for table named $tbl, with the columns specified
# by list argument $cols. e.g. if the function is invoked as:
#
# vtab_cmd t1 {a b c} ...
#
# The table created is:
#
# "CREATE TABLE t1 (a, b, c)"
#
# The tables xBestIndex method behaves as if all possible combinations of
# "=" constraints (but no others) may be optimized. The cost of a full table
# scan is:
#
# "WHERE 1" "cost 1000000 rows 1000000"
#
# If one or more "=" constraints are in use, the cost and estimated number
# of rows returned are both is (11 - nCons)*1000, where nCons is the number
# of constraints used. e.g.
#
# "WHERE a=? AND b=?" -> "cost 900 rows 900"
# "WHERE c=? AND b<?" -> "cost 1000 rows 1000"
#
proc vtab_cmd {tbl cols method args} {
switch -- $method {
xConnect {
return "CREATE TABLE $tbl ([join $cols ,])"
}
xBestIndex {
foreach {clist orderby mask} $args {}
set cons [list]
set used [list]
for {set i 0} {$i < [llength $clist]} {incr i} {
array unset C
array set C [lindex $clist $i]
if {$C(op)=="eq" && $C(usable) && [lsearch $cons $C(column)]<0} {
lappend used use $i
lappend cons $C(column)
}
}
set nCons [llength $cons]
if {$nCons==0} {
return "cost 1000000 rows 1000000"
} else {
set cost [expr (11-$nCons) * 1000]
set ret [concat $used "cost $cost rows $cost"]
set txt [list]
foreach c $cons { lappend txt "[lindex $cols $c]=?" }
lappend ret idxstr "indexed([join $txt { AND }])"
return $ret
}
}
}
return ""
}
register_tcl_module db
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING tcl("vtab_cmd t1 {a b}");
CREATE VIRTUAL TABLE t2 USING tcl("vtab_cmd t2 {c d}");
CREATE VIRTUAL TABLE t3 USING tcl("vtab_cmd t3 {e f}");
}
do_eqp_test 1.1 {
SELECT * FROM t1 WHERE a='abc'
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
}
do_eqp_test 1.2 {
SELECT * FROM t1 WHERE a='abc' AND b='def'
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
}
do_eqp_test 1.3 {
SELECT * FROM t1 WHERE a='abc' AND a='def'
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
}
do_eqp_test 1.4 {
SELECT * FROM t1,t2 WHERE c=a
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
}
do_eqp_test 1.5 {
SELECT * FROM t1, t2 CROSS JOIN t3 WHERE t2.c = +t1.b AND t3.e=t2.d
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
}
do_eqp_test 1.6 {
SELECT * FROM t1, t2, t3 WHERE t2.c = +t1.b AND t3.e = t2.d
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
}
do_execsql_test 1.7.1 {
CREATE TABLE x1(a, b);
}
do_eqp_test 1.7.2 {
SELECT * FROM x1 CROSS JOIN t1, t2, t3
WHERE t1.a = t2.c AND t1.b = t3.e
} {
0 0 0 {SCAN TABLE x1}
0 1 1 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
0 2 2 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
0 3 3 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
}
finish_test
+175
View File
@@ -0,0 +1,175 @@
# 2016 May 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 bestindex3
ifcapable !vtab {
finish_test
return
}
#-------------------------------------------------------------------------
# Virtual table callback for a virtual table named $tbl.
#
# The table created is:
#
# "CREATE TABLE t1 (a, b, c)"
#
# This virtual table supports both LIKE and = operators on all columns.
#
proc vtab_cmd {bOmit method args} {
switch -- $method {
xConnect {
return "CREATE TABLE t1(a, b, c)"
}
xBestIndex {
foreach {clist orderby mask} $args {}
set ret [list]
set use use
if {$bOmit} {set use omit}
for {set i 0} {$i < [llength $clist]} {incr i} {
array unset C
array set C [lindex $clist $i]
if {$C(usable) && ($C(op)=="like" || $C(op)=="eq")} {
lappend ret $use $i
lappend ret idxstr
lappend ret "[lindex {a b c} $C(column)] [string toupper $C(op)] ?"
break
}
}
if {$ret==""} {
lappend ret cost 1000000 rows 1000000
} else {
lappend ret cost 100 rows 10
}
return $ret
}
xFilter {
foreach {idxnum idxstr param} $args {}
set where ""
if {$bOmit && $idxstr != ""} {
set where " WHERE [string map [list ? '$param' EQ =] $idxstr]"
}
return [list sql "SELECT rowid, * FROM ttt$where"]
}
}
return ""
}
register_tcl_module db
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING tcl("vtab_cmd 0");
}
do_eqp_test 1.1 {
SELECT * FROM t1 WHERE a LIKE 'abc';
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
}
do_eqp_test 1.2 {
SELECT * FROM t1 WHERE a = 'abc';
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
}
do_eqp_test 1.3 {
SELECT * FROM t1 WHERE a = 'abc' OR b = 'def';
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?}
}
do_eqp_test 1.4 {
SELECT * FROM t1 WHERE a LIKE 'abc%' OR b = 'def';
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?}
}
do_execsql_test 1.5 {
CREATE TABLE ttt(a, b, c);
INSERT INTO ttt VALUES(1, 'two', 'three');
INSERT INTO ttt VALUES(2, 'one', 'two');
INSERT INTO ttt VALUES(3, 'three', 'one');
INSERT INTO ttt VALUES(4, 'y', 'one');
INSERT INTO ttt VALUES(5, 'x', 'two');
INSERT INTO ttt VALUES(6, 'y', 'three');
}
foreach omit {0 1} {
do_execsql_test 1.6.$omit.0 "
DROP TABLE t1;
CREATE VIRTUAL TABLE t1 USING tcl('vtab_cmd $omit');
"
do_execsql_test 1.6.$omit.1 {
SELECT rowid FROM t1 WHERE c LIKE 'o%'
} {3 4}
do_execsql_test 1.6.$omit.2 {
SELECT rowid FROM t1 WHERE c LIKE 'o%' OR b='y'
} {3 4 6}
do_execsql_test 1.6.$omit.3 {
SELECT rowid FROM t1 WHERE c = 'three' OR c LIKE 'o%'
} {1 6 3 4}
}
#-------------------------------------------------------------------------
# Test the same pattern works with ordinary tables.
#
# This test does not work if the ICU extension is enabled. ICU overrides
# LIKE - and this optimization only works with the built-in LIKE function.
#
ifcapable !icu {
do_execsql_test 2.1 {
CREATE TABLE t2(x TEXT COLLATE nocase, y TEXT);
CREATE INDEX t2x ON t2(x COLLATE nocase);
CREATE INDEX t2y ON t2(y);
}
do_eqp_test 2.2 {
SELECT * FROM t2 WHERE x LIKE 'abc%' OR y = 'def'
} {
0 0 0 {SEARCH TABLE t2 USING INDEX t2x (x>? AND x<?)}
0 0 0 {SEARCH TABLE t2 USING INDEX t2y (y=?)}
}
}
#-------------------------------------------------------------------------
# Test that any PRIMARY KEY within a sqlite3_decl_vtab() CREATE TABLE
# statement is currently ignored.
#
proc vvv_command {method args} {
switch -- $method {
xConnect { return "CREATE TABLE t1(a PRIMARY KEY, b, c)" }
}
}
proc yyy_command {method args} {
switch -- $method {
xConnect { return "CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b))" }
}
}
do_execsql_test 3.1 { CREATE VIRTUAL TABLE t3 USING tcl('vvv_command') }
do_execsql_test 3.2 { CREATE VIRTUAL TABLE t4 USING tcl('yyy_command') }
finish_test
+16 -14
View File
@@ -172,14 +172,15 @@ do_test capi3-3.3 {
catch {
set db2 [sqlite3_open /bogus/path/test.db {}]
}
sqlite3_extended_errcode $db2
} {SQLITE_CANTOPEN}
set ::capi3_errno [sqlite3_system_errno $db2]
list [sqlite3_extended_errcode $db2] [expr {$::capi3_errno!=0}]
} {SQLITE_CANTOPEN 1}
do_test capi3-3.4 {
sqlite3_errmsg $db2
} {unable to open database file}
do_test capi3-3.5 {
sqlite3_close $db2
} {SQLITE_OK}
list [sqlite3_system_errno $db2] [sqlite3_close $db2]
} [list $::capi3_errno SQLITE_OK]
if {[clang_sanitize_address]==0} {
do_test capi3-3.6.1-misuse {
sqlite3_close $db2
@@ -925,19 +926,20 @@ do_test capi3-11.9.3 {
do_test capi3-11.10 {
sqlite3_step $STMT
} {SQLITE_ROW}
ifcapable !autoreset {
# If SQLITE_OMIT_AUTORESET is defined, then the statement must be
# reset() before it can be passed to step() again.
do_test capi3-11.11a { sqlite3_step $STMT } {SQLITE_MISUSE}
do_test capi3-11.11b { sqlite3_reset $STMT } {SQLITE_ABORT}
}
do_test capi3-11.11 {
sqlite3_step $STMT
} {SQLITE_DONE}
do_test capi3-11.12 {
sqlite3_step $STMT
sqlite3_step $STMT
} {SQLITE_ROW}
ifcapable !autoreset {
do_test capi3-11.12armor {
sqlite3_step $STMT
sqlite3_step $STMT
} {SQLITE_MISUSE}
} else {
do_test capi3-11.12 {
sqlite3_step $STMT
sqlite3_step $STMT
} {SQLITE_ROW}
}
do_test capi3-11.13 {
sqlite3_finalize $STMT
} {SQLITE_OK}
+11 -10
View File
@@ -865,19 +865,20 @@ do_test capi3c-11.9.3 {
do_test capi3c-11.10 {
sqlite3_step $STMT
} {SQLITE_ROW}
ifcapable !autoreset {
# If SQLITE_OMIT_AUTORESET is defined, then the statement must be
# reset() before it can be passed to step() again.
do_test capi3-11.11a { sqlite3_step $STMT } {SQLITE_MISUSE}
do_test capi3-11.11b { sqlite3_reset $STMT } {SQLITE_ABORT}
}
do_test capi3c-11.11 {
sqlite3_step $STMT
} {SQLITE_DONE}
do_test capi3c-11.12 {
sqlite3_step $STMT
sqlite3_step $STMT
} {SQLITE_ROW}
ifcapable !autoreset {
do_test capi3c-11.12armor {
sqlite3_step $STMT
sqlite3_step $STMT
} {SQLITE_MISUSE}
} else {
do_test capi3c-11.12 {
sqlite3_step $STMT
sqlite3_step $STMT
} {SQLITE_ROW}
}
do_test capi3c-11.13 {
sqlite3_finalize $STMT
} {SQLITE_OK}
+1 -1
View File
@@ -15,7 +15,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix cacheflush
set testprefix cffault
source $testdir/malloc_common.tcl
# Run the supplied SQL on a copy of the database currently stored on
+4
View File
@@ -17,6 +17,10 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix close
# This module bypasses the "-key" logic in tester.tcl, so it cannot run
# with the codec enabled.
do_not_use_codec
do_execsql_test 1.0 {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES('one');
+63
View File
@@ -0,0 +1,63 @@
# 2016-07-01
#
# 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.
#
#***********************************************************************
# Test cases for a crash bug.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test collateB-1.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY);
CREATE TABLE t2(b INTEGER PRIMARY KEY, x1 INT COLLATE NOCASE);
CREATE TABLE t3(x2 INT);
SELECT * FROM t3, t2, t1 WHERE x2=b AND x1=a AND a=1;
} {}
do_execsql_test collateB-1.2 {
INSERT INTO t1(a) VALUES(1),(2),(3);
INSERT INTO t2(b,x1) VALUES(11,1),(22,2),(33,3);
INSERT INTO t3(x2) VALUES(11),(22),(33);
SELECT *,'|' FROM t3, t2, t1 WHERE x2=b AND x1=a AND a=1;
} {11 11 1 1 |}
do_execsql_test collateB-1.3 {
SELECT *,'|' FROM t3, t1, t2 WHERE x2=b AND x1=a AND a=1;
} {11 1 11 1 |}
do_execsql_test collateB-1.4 {
SELECT *,'|' FROM t2, t3, t1 WHERE x2=b AND x1=a AND a=1;
} {11 1 11 1 |}
do_execsql_test collateB-1.5 {
SELECT *,'|' FROM t2, t1, t3 WHERE x2=b AND x1=a AND a=1;
} {11 1 1 11 |}
do_execsql_test collateB-1.6 {
SELECT *,'|' FROM t1, t2, t3 WHERE x2=b AND x1=a AND a=1;
} {1 11 1 11 |}
do_execsql_test collateB-1.7 {
SELECT *,'|' FROM t1, t2, t3 WHERE x2=b AND x1=a AND a=1;
} {1 11 1 11 |}
do_execsql_test collateB-1.12 {
SELECT *,'|' FROM t3, t2, t1 WHERE b=x2 AND a=x1 AND 1=a;
} {11 11 1 1 |}
do_execsql_test collateB-1.13 {
SELECT *,'|' FROM t3, t1, t2 WHERE b=x2 AND a=x1 AND 1=a;
} {11 1 11 1 |}
do_execsql_test collateB-1.14 {
SELECT *,'|' FROM t2, t3, t1 WHERE b=x2 AND a=x1 AND 1=a;
} {11 1 11 1 |}
do_execsql_test collateB-1.15 {
SELECT *,'|' FROM t2, t1, t3 WHERE b=x2 AND a=x1 AND 1=a;
} {11 1 1 11 |}
do_execsql_test collateB-1.16 {
SELECT *,'|' FROM t1, t2, t3 WHERE b=x2 AND a=x1 AND 1=a;
} {1 11 1 11 |}
do_execsql_test collateB-1.17 {
SELECT *,'|' FROM t1, t2, t3 WHERE b=x2 AND a=x1 AND 1=a;
} {1 11 1 11 |}
finish_test
+7 -5
View File
@@ -285,15 +285,17 @@ do_test conflict-6.0 {
# t3 Number of temporary files for tables
# t4 Number of temporary files for statement journals
#
# Update: Since temporary table files are now opened lazily, and none
# of the following tests use large quantities of data, t3 is always 0.
# Update (2007-08-21): Since temporary table files are now opened lazily,
# and none of the following tests use large quantities of data, t3 is always 0.
#
# Update (2016-03-04): Subjournals now also open lazily, so t4 is also always 0.
#
foreach {i conf1 cmd t0 t1 t2 t3 t4} {
1 {} UPDATE 1 {6 7 8 9} 1 0 1
1 {} UPDATE 1 {6 7 8 9} 1 0 0
2 REPLACE UPDATE 0 {7 6 9} 1 0 0
3 IGNORE UPDATE 0 {6 7 3 9} 1 0 0
4 FAIL UPDATE 1 {6 7 3 4} 1 0 0
5 ABORT UPDATE 1 {1 2 3 4} 1 0 1
5 ABORT UPDATE 1 {1 2 3 4} 1 0 0
6 ROLLBACK UPDATE 1 {1 2 3 4} 0 0 0
7 REPLACE {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0
8 IGNORE {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0
@@ -303,7 +305,7 @@ foreach {i conf1 cmd t0 t1 t2 t3 t4} {
12 {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0
13 {} {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0
14 {} {UPDATE OR FAIL} 1 {6 7 3 4} 1 0 0
15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 1
15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 0
16 {} {UPDATE OR ROLLBACK} 1 {1 2 3 4} 0 0 0
} {
if {$t0} {set t1 {UNIQUE constraint failed: t1.a}}
+13 -10
View File
@@ -287,22 +287,25 @@ do_test conflict2-6.0 {
# Update: Since temporary table files are now opened lazily, and none
# of the following tests use large quantities of data, t3 is always 0.
#
# Update (2016-03-04): Subjournals now only open when their size
# exceeds 64KB.
#
foreach {i conf1 cmd t0 t1 t2 t3 t4} {
1 {} UPDATE 1 {6 7 8 9} 1 0 1
2 REPLACE UPDATE 0 {7 6 9} 1 0 1
3 IGNORE UPDATE 0 {6 7 3 9} 1 0 1
4 FAIL UPDATE 1 {6 7 3 4} 1 0 1
5 ABORT UPDATE 1 {1 2 3 4} 1 0 1
6 ROLLBACK UPDATE 1 {1 2 3 4} 0 0 1
1 {} UPDATE 1 {6 7 8 9} 1 0 0
2 REPLACE UPDATE 0 {7 6 9} 1 0 0
3 IGNORE UPDATE 0 {6 7 3 9} 1 0 0
4 FAIL UPDATE 1 {6 7 3 4} 1 0 0
5 ABORT UPDATE 1 {1 2 3 4} 1 0 0
6 ROLLBACK UPDATE 1 {1 2 3 4} 0 0 0
7 REPLACE {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0
8 IGNORE {UPDATE OR REPLACE} 0 {7 6 9} 1 0 1
8 IGNORE {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0
9 FAIL {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0
10 ABORT {UPDATE OR REPLACE} 0 {7 6 9} 1 0 1
10 ABORT {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0
11 ROLLBACK {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0
12 {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0
13 {} {UPDATE OR REPLACE} 0 {7 6 9} 1 0 1
13 {} {UPDATE OR REPLACE} 0 {7 6 9} 1 0 0
14 {} {UPDATE OR FAIL} 1 {6 7 3 4} 1 0 0
15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 1
15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 0
16 {} {UPDATE OR ROLLBACK} 1 {1 2 3 4} 0 0 0
} {
+23 -21
View File
@@ -346,27 +346,29 @@ ifcapable autovacuum {
} {1 {database disk image is malformed}}
}
corruption_test -sqlprep {
PRAGMA auto_vacuum = 1;
PRAGMA page_size = 1024;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, randomblob(2500));
DELETE FROM t1 WHERE a = 1;
} -corrupt {
set nAppend [expr 1024*207 - [file size corrupt.db]]
set fd [open corrupt.db r+]
seek $fd 0 end
puts -nonewline $fd [string repeat x $nAppend]
close $fd
hexio_write corrupt.db 28 00000000
} -test {
do_test corrupt2-6.4 {
catchsql "
$::presql
BEGIN EXCLUSIVE;
COMMIT;
"
} {1 {database disk image is malformed}}
if {![nonzero_reserved_bytes]} {
corruption_test -sqlprep {
PRAGMA auto_vacuum = 1;
PRAGMA page_size = 1024;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, randomblob(2500));
DELETE FROM t1 WHERE a = 1;
} -corrupt {
set nAppend [expr 1024*207 - [file size corrupt.db]]
set fd [open corrupt.db r+]
seek $fd 0 end
puts -nonewline $fd [string repeat x $nAppend]
close $fd
hexio_write corrupt.db 28 00000000
} -test {
do_test corrupt2-6.4 {
catchsql "
$::presql
BEGIN EXCLUSIVE;
COMMIT;
"
} {1 {database disk image is malformed}}
}
}
}
+3 -4
View File
@@ -18,10 +18,9 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
+3 -4
View File
@@ -18,10 +18,9 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
+3 -4
View File
@@ -19,10 +19,9 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
+3 -4
View File
@@ -19,10 +19,9 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
+3 -4
View File
@@ -18,10 +18,9 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
+3 -4
View File
@@ -14,10 +14,9 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptG
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
+4 -4
View File
@@ -14,10 +14,10 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptH
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
database_may_be_corrupt
# The corruption migrations tested by the code in this file are not detected
+4 -4
View File
@@ -19,10 +19,10 @@ if {[permutation]=="mmap"} {
return
}
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
database_may_be_corrupt
# Initialize the database.
+4 -4
View File
@@ -22,10 +22,10 @@ if {[permutation]=="mmap"} {
return
}
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
database_may_be_corrupt
# Initialize the database.
+31
View File
@@ -89,5 +89,36 @@ do_test 4.3 {
db eval {SELECT b FROM t1}
} {2 4 8}
#-------------------------------------------------------------------------
# Test that indexes with large numbers of columns can be correctly
# identified as covering indexes.
reset_db
set L [list]
for {set i 1} {$i<120} {incr i} {
lappend L "c$i"
}
set cols [join $L ,]
do_execsql_test 5.1.0 "
CREATE TABLE t1(a, b, c, $cols, PRIMARY KEY(a, b, c)) WITHOUT ROWID;
CREATE INDEX i1 ON t1($cols);
CREATE TABLE t2(i INTEGER PRIMARY KEY, $cols);
CREATE INDEX i2 ON t2($cols);
"
do_eqp_test 5.1.1 {
SELECT * FROM t1 ORDER BY c1, c2;
} {
0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
}
do_eqp_test 5.1.2 {
SELECT * FROM t2 ORDER BY c1, c2;
} {
0 0 0 {SCAN TABLE t2 USING COVERING INDEX i2}
}
finish_test
+1
View File
@@ -25,6 +25,7 @@ ifcapable !crashtest {
finish_test
return
}
do_not_use_codec
do_test crash8-1.1 {
execsql {
+112
View File
@@ -0,0 +1,112 @@
# 2016-06-02
#
# 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.
#
#***********************************************************************
#
# Test cases for CSV virtual table.
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix csv01
ifcapable !vtab||!cte { finish_test ; return }
load_static_extension db csv
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE temp.t1 USING csv(
data=
'1,2,3,4
5,6,7,8
9,10,11,12
13,14,15,16
',
columns=4
);
SELECT * FROM t1 WHERE c1=10;
} {9 10 11 12}
do_execsql_test 1.1 {
SELECT * FROM t1 WHERE c1='10';
} {9 10 11 12}
do_execsql_test 1.2 {
SELECT rowid FROM t1;
} {1 2 3 4}
do_execsql_test 2.0 {
DROP TABLE t1;
CREATE VIRTUAL TABLE temp.t2 USING csv(
data=
'1,2,3,4
5,6,7,8
9,10,11,12
13,14,15,16
',
columns=4,
schema='CREATE TABLE t2(a INT, b TEXT, c REAL, d BLOB)'
);
SELECT * FROM t2 WHERE a=9;
} {9 10 11 12}
do_execsql_test 2.1 {
SELECT * FROM t2 WHERE b=10;
} {9 10 11 12}
do_execsql_test 2.2 {
SELECT * FROM t2 WHERE c=11;
} {9 10 11 12}
do_execsql_test 2.3 {
SELECT * FROM t2 WHERE d=12;
} {}
do_execsql_test 2.4 {
SELECT * FROM t2 WHERE d='12';
} {9 10 11 12}
do_execsql_test 2.5 {
SELECT * FROM t2 WHERE a='9';
} {9 10 11 12}
do_execsql_test 3.0 {
DROP TABLE t2;
CREATE VIRTUAL TABLE temp.t3 USING csv(
data=
'1,2,3,4
5,6,7,8
9,10,11,12
13,14,15,16
',
columns=4,
schema=
'CREATE TABLE t3(a PRIMARY KEY,b TEXT,c TEXT,d TEXT) WITHOUT ROWID',
testflags=1
);
SELECT a FROM t3 WHERE b=6 OR c=7 OR d=12 ORDER BY +a;
} {5 9}
do_execsql_test 3.1 {
SELECT a FROM t3 WHERE +b=6 OR c=7 OR d=12 ORDER BY +a;
} {5 9}
# The rowid column is not visible on a WITHOUT ROWID virtual table
do_catchsql_test 3.2 {
SELECT rowid, a FROM t3;
} {1 {no such column: rowid}}
do_catchsql_test 4.0 {
DROP TABLE t3;
CREATE VIRTUAL TABLE temp.t4 USING csv_wr(
data=
'1,2,3,4
5,6,7,8
9,10,11,12
13,14,15,16
',
columns=4,
schema=
'CREATE TABLE t3(a PRIMARY KEY,b TEXT,c TEXT,d TEXT) WITHOUT ROWID',
testflags=1
);
} {1 {vtable constructor failed: t4}}
finish_test
+3 -2
View File
@@ -196,9 +196,10 @@ set tc 1
foreach opt $opts {
do_test ctime-2.5.$tc {
set N [ expr {$tc-1} ]
set ans1 [ catchsql {
set ans1 [catch {db one {
SELECT sqlite_compileoption_get($N);
} ]
}} msg]
lappend ans1 $msg
set ans2 [ catchsql {
SELECT sqlite_compileoption_used($opt);
} ]
+182
View File
@@ -0,0 +1,182 @@
# 2016 June 17
#
# 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 is on testing that cursor-hints are correct for queries
# involving LEFT JOIN.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix cursorhint2
ifcapable !cursorhints {
finish_test
return
}
proc extract_hints {sql} {
db eval "SELECT tbl_name, rootpage FROM sqlite_master where rootpage" {
set lookup($rootpage) $tbl_name
}
set ret [list]
db eval "EXPLAIN $sql" a {
switch -- $a(opcode) {
OpenRead {
set csr($a(p1)) $lookup($a(p2))
}
CursorHint {
lappend ret $csr($a(p1)) $a(p4)
}
}
}
set ret
}
proc do_extract_hints_test {tn sql ret} {
uplevel [list do_test $tn [list extract_hints $sql] [list {*}$ret]]
}
do_execsql_test 1.0 {
PRAGMA automatic_index = 0;
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
CREATE TABLE t3(e, f);
}
do_extract_hints_test 1.1 {
SELECT * FROM t1 WHERE a=1;
} {
t1 EQ(c0,1)
}
do_extract_hints_test 1.2 {
SELECT * FROM t1 CROSS JOIN t2 ON (a=c) WHERE d IS NULL;
} {
t2 {AND(ISNULL(c1),EQ(r[1],c0))}
}
do_extract_hints_test 1.3 {
SELECT * FROM t1 LEFT JOIN t2 ON (a=c) WHERE d IS NULL;
} {
t2 {EQ(r[2],c0)}
}
do_extract_hints_test 1.4 {
SELECT * FROM t1 LEFT JOIN t2 ON (a=c AND a=10) WHERE d IS NULL;
} {
t2 {AND(EQ(r[2],c0),EQ(r[3],10))}
}
do_extract_hints_test 1.5 {
SELECT * FROM t1 CROSS JOIN t2 ON (a=c AND a=10) WHERE d IS NULL;
} {
t1 EQ(c0,10) t2 {AND(ISNULL(c1),EQ(r[3],c0))}
}
do_extract_hints_test 1.6 {
SELECT * FROM t1 LEFT JOIN t2 ON (a=c) LEFT JOIN t3 ON (d=f);
} {
t2 {EQ(r[2],c0)} t3 {EQ(r[6],c1)}
}
do_extract_hints_test 1.7 {
SELECT * FROM t1 LEFT JOIN t2 ON (a=c AND d=e) LEFT JOIN t3 ON (d=f);
} {
t2 {EQ(r[2],c0)} t3 {AND(EQ(r[6],c0),EQ(r[7],c1))}
}
#-------------------------------------------------------------------------
#
do_execsql_test 2.0 {
CREATE TABLE x1(x, y);
CREATE TABLE x2(a, b);
}
do_extract_hints_test 2.1 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE b IS NULL;
} {
x2 {EQ(c0,r[2])}
}
do_extract_hints_test 2.2 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE b IS +NULL;
} {
x2 {EQ(c0,r[2])}
}
do_extract_hints_test 2.3 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE 1 = (b IS NULL)
} {
x2 {EQ(c0,r[2])}
}
do_extract_hints_test 2.4 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE 1 = coalesce(b, 1)
} {
x2 {EQ(c0,r[2])}
}
do_extract_hints_test 2.5 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE 1 = coalesce(b, 1)
} {
x2 {EQ(c0,r[2])}
}
do_extract_hints_test 2.6 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE 0 = (b IS NOT NULL)
} {
x2 {EQ(c0,r[2])}
}
do_extract_hints_test 2.7 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE 0 = (b IS NOT +NULL)
} {
x2 {EQ(c0,r[2])}
}
do_extract_hints_test 2.8 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE b IS NOT +NULL
} {
x2 {EQ(c0,r[2])}
}
do_extract_hints_test 2.9 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE CASE b WHEN 0 THEN 0 ELSE 1 END;
} {
x2 {EQ(c0,r[2])}
}
do_extract_hints_test 2.10 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE x2.b = 32+32
} {
x2 {AND(EQ(c1,ADD(32,32)),EQ(c0,r[2]))}
}
ifcapable !icu {
# This test only works using the built-in LIKE, not the ICU LIKE extension.
do_extract_hints_test 2.11 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE x2.b LIKE 'abc%'
} {
x2 {AND(expr,EQ(c0,r[2]))}
}
}
do_extract_hints_test 2.12 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE coalesce(x2.b, 1)
} {
x2 {EQ(c0,r[2])}
}
finish_test
+43 -5
View File
@@ -14,6 +14,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix dbstatus
ifcapable !compound {
finish_test
@@ -24,6 +25,7 @@ ifcapable !compound {
db close
sqlite3_shutdown
sqlite3_config_memstatus 1
sqlite3_config_uri 1
sqlite3_initialize
sqlite3 db test.db
@@ -67,16 +69,12 @@ ifcapable stat4||stat3 {
set STAT3 0
}
ifcapable malloc_usable_size {
finish_test
return
}
#---------------------------------------------------------------------------
# Run the dbstatus-2 and dbstatus-3 tests with several of different
# lookaside buffer sizes.
#
foreach ::lookaside_buffer_size {0 64 120} {
ifcapable malloc_usable_size break
# Do not run any of these tests if there is SQL configured to run
# as part of the [sqlite3] command. This prevents the script from
@@ -377,4 +375,44 @@ foreach ::lookaside_buffer_size {0 64 120} {
}
}
#-------------------------------------------------------------------------
# The following tests focus on DBSTATUS_CACHE_USED_SHARED
#
ifcapable shared_cache {
if {[permutation]=="memsys3"
|| [permutation]=="memsys5"
|| $::tcl_platform(os)=="Linux"} {
proc do_cacheused_test {tn db res} {
set cu [sqlite3_db_status $db SQLITE_DBSTATUS_CACHE_USED 0]
set pcu [sqlite3_db_status $db SQLITE_DBSTATUS_CACHE_USED_SHARED 0]
set cu [lindex $cu 1]
set pcu [lindex $pcu 1]
uplevel [list do_test $tn [list list $cu $pcu] "#/$res/"]
}
reset_db
sqlite3 db file:test.db?cache=shared
do_execsql_test 4.0 {
PRAGMA auto_vacuum=NONE;
CREATE TABLE t1(a, b, c);
INSERT INTO t1 VALUES(1, 2, 3);
}
do_cacheused_test 4.0.1 db { 4568 4568 }
do_execsql_test 4.1 {
CREATE TEMP TABLE tt(a, b, c);
INSERT INTO tt VALUES(1, 2, 3);
}
do_cacheused_test 4.1.1 db { 9000 9000 }
sqlite3 db2 file:test.db?cache=shared
do_cacheused_test 4.2.1 db2 { 4568 2284 }
do_cacheused_test 4.2.2 db { 9000 6716 }
db close
do_cacheused_test 4.2.3 db2 { 4568 4568 }
sqlite3 db file:test.db?cache=shared
do_cacheused_test 4.2.4 db2 { 4568 2284 }
db2 close
}
}
finish_test
+1 -1
View File
@@ -86,7 +86,7 @@ do_test 2.3 { db_write db 1 } {0 4 0}
do_test 2.4 { db_write db 0 } {0 0 0}
do_test 2.5 { db_write db 1 } {0 0 0}
ifcapable wal {
if {[wal_is_capable]} {
do_test 2.6 {
execsql { PRAGMA journal_mode = WAL }
db_write db 1
+14
View File
@@ -389,5 +389,19 @@ do_test delete-9.5 {
set res
} {1 a b 1 c d 2 a b 2 c d}
do_execsql_test delete-10.0 {
CREATE TABLE t1(a INT UNIQUE, b INT);
INSERT INTO t1(a,b) VALUES('1','2');
SELECT * FROM t1 WHERE a='1' AND b='2';
} {1 2}
do_execsql_test delete-10.1 {
DELETE FROM t1 WHERE a='1' AND b='2';
}
do_execsql_test delete-10.2 {
SELECT * FROM t1 WHERE a='1' AND b='2';
}
finish_test
+42
View File
@@ -139,7 +139,49 @@ do_execsql_test 4.12 {
PRAGMA integrity_check;
} {ok}
# 2016-04-09
# Ticket https://sqlite.org/src/info/a306e56ff68b8fa5
# Failure to completely delete when reverse_unordered_selects is
# engaged.
#
db close
forcedelete test.db
sqlite3 db test.db
do_execsql_test 5.0 {
PRAGMA page_size=1024;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX x1 ON t1(b, c);
INSERT INTO t1(a,b,c) VALUES(1, 1, zeroblob(80));
INSERT INTO t1(a,b,c) SELECT a+1, 1, c FROM t1;
INSERT INTO t1(a,b,c) SELECT a+2, 1, c FROM t1;
INSERT INTO t1(a,b,c) SELECT a+10, 2, c FROM t1 WHERE b=1;
INSERT INTO t1(a,b,c) SELECT a+20, 3, c FROM t1 WHERE b=1;
PRAGMA reverse_unordered_selects = ON;
DELETE FROM t1 WHERE b=2;
SELECT a FROM t1 WHERE b=2;
} {}
# 2016-05-02
# Ticket https://www.sqlite.org/src/tktview/dc6ebeda93960877
# A subquery in the WHERE clause of a one-pass DELETE can cause an
# incorrect answer.
#
db close
forcedelete test.db
sqlite3 db test.db
do_execsql_test 6.0 {
CREATE TABLE t2(x INT);
INSERT INTO t2(x) VALUES(1),(2),(3),(4),(5);
DELETE FROM t2 WHERE EXISTS(SELECT 1 FROM t2 AS v WHERE v.x=t2.x-1);
SELECT x FROM t2;
} {1}
do_execsql_test 6.1 {
DROP TABLE IF EXISTS t2;
CREATE TABLE t2(x INT);
INSERT INTO t2(x) VALUES(1),(2),(3),(4),(5);
DELETE FROM t2 WHERE EXISTS(SELECT 1 FROM t2 AS v WHERE v.x=t2.x+1);
SELECT x FROM t2;
} {5}
finish_test
+217
View File
@@ -0,0 +1,217 @@
# 2016 September 10
#
# 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 the code in test_delete.c (the
# sqlite3_delete_database() API).
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix delete_db
proc delete_all {} {
foreach f [glob -nocomplain test2*] { file delete $f }
foreach f [glob -nocomplain test3*] { file delete $f }
}
proc copydb {} {
foreach f [glob -nocomplain test3*] { file delete $f }
foreach f [glob -nocomplain test2*] {
set p [string range $f 5 end]
file copy "test2$p" "test3$p"
}
}
proc files {} {
lsort [glob -nocomplain test3*]
}
db close
delete_all
sqlite3 db test2.database
#-------------------------------------------------------------------------
#
# 1.1: Journal files.
# 1.2: Wal files.
# 1.3: Multiplexor with journal file.
# 1.4: Multiplexor with wal file.
#
# 2.* are a copy of 1.* with the multiplexor enabled.
#
# 3.* tests errors.
#
do_test 1.1.0 {
execsql {
CREATE TABLE t1(x, y);
BEGIN;
INSERT INTO t1 VALUES(1, 2);
}
copydb
files
} {test3.database test3.database-journal}
do_test 1.1.1 {
sqlite3_delete_database test3.database
files
} {}
do_test 1.2.0 {
execsql {
COMMIT;
PRAGMA journal_mode = wal;
INSERT INTO t1 VALUES(3, 4);
}
copydb
files
} {test3.database test3.database-shm test3.database-wal}
do_test 1.2.1 {
sqlite3_delete_database test3.database
files
} {}
db close
delete_all
sqlite3_multiplex_initialize "" 0
sqlite3 db test2.database -vfs multiplex
sqlite3_multiplex_control db "main" chunk_size 32768
do_test 1.3.0 {
execsql { PRAGMA auto_vacuum = 0; }
execsql {
CREATE TABLE x1(a, b);
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1000 )
INSERT INTO x1 SELECT randomblob(100), randomblob(100) FROM s;
BEGIN;
UPDATE x1 SET a=randomblob(101)
}
copydb
files
} [list {*}{
test3.database test3.database-journal test3.database001
test3.database002 test3.database003
}]
do_test 1.3.1 {
sqlite3_delete_database test3.database
files
} {}
do_test 1.4.0 {
execsql {
COMMIT;
PRAGMA journal_mode = wal;
UPDATE x1 SET a=randomblob(102)
}
copydb
files
} [list {*}{
test3.database test3.database-shm test3.database-wal test3.database001
test3.database002 test3.database003
}]
do_test 1.4.1 {
sqlite3_delete_database test3.database
files
} {}
ifcapable 8_3_names {
db close
delete_all
sqlite3 db file:test2.db?8_3_names=1 -uri 1
do_test 2.1.0 {
execsql {
CREATE TABLE t1(x, y);
BEGIN;
INSERT INTO t1 VALUES(1, 2);
}
copydb
files
} {test3.db test3.nal}
do_test 2.1.1 {
sqlite3_delete_database test3.db
files
} {}
do_test 2.2.0 {
execsql {
COMMIT;
PRAGMA journal_mode = wal;
INSERT INTO t1 VALUES(3, 4);
}
copydb
files
} {test3.db test3.shm test3.wal}
do_test 2.2.1 {
sqlite3_delete_database test3.db
files
} {}
db close
delete_all
sqlite3_multiplex_initialize "" 0
sqlite3 db file:test2.db?8_3_names=1 -uri 1 -vfs multiplex
sqlite3_multiplex_control db "main" chunk_size 32768
do_test 2.3.0 {
execsql { PRAGMA auto_vacuum = 0; }
execsql {
CREATE TABLE x1(a, b);
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1000 )
INSERT INTO x1 SELECT randomblob(100), randomblob(100) FROM s;
BEGIN;
UPDATE x1 SET a=randomblob(101)
}
copydb
files
} [list {*}{
test3.001 test3.002 test3.003 test3.db test3.nal
}]
do_test 2.3.1 {
sqlite3_delete_database test3.db
files
} {}
do_test 2.4.0 {
execsql {
COMMIT;
PRAGMA journal_mode = wal;
UPDATE x1 SET a=randomblob(102)
}
copydb
files
} [list {*}{
test3.001 test3.002 test3.003 test3.db test3.db-shm test3.wal
}]
do_test 2.4.1 {
sqlite3_delete_database test3.db
files
} {}
}
db close
delete_all
sqlite3_multiplex_shutdown
do_test 3.0 {
file mkdir dir2.db
sqlite3_delete_database dir2.db
} {SQLITE_ERROR}
do_test 3.1 {
sqlite3_delete_database dir2.db/test.db
} {SQLITE_OK}
finish_test
+5 -2
View File
@@ -847,6 +847,9 @@ foreach {tn x expr res nEval} {
3 5 "x() >= 5 AND x() <= 5" 1 2
4 5 "x() BETWEEN 5 AND 5" 1 1
5 9 "(x(),8) >= (9,7) AND (x(),8)<=(9,10)" 1 2
6 9 "(x(),8) BETWEEN (9,7) AND (9,10)" 1 1
} {
do_test e_expr-13.1.$tn {
set ::xcount 0
@@ -1809,7 +1812,7 @@ do_expr_test e_expr-35.1.6 {
# The following block tests that errors are returned in a bunch of cases
# where a subquery returns more than one column.
#
set M {only a single result allowed for a SELECT that is part of an expression}
set M {/1 {sub-select returns [23] columns - expected 1}/}
foreach {tn sql} {
1 { SELECT (SELECT * FROM t2 UNION SELECT a+1, b+1 FROM t2) }
2 { SELECT (SELECT * FROM t2 UNION SELECT a+1, b+1 FROM t2 ORDER BY 1) }
@@ -1818,7 +1821,7 @@ foreach {tn sql} {
5 { SELECT (SELECT * FROM t2) }
6 { SELECT (SELECT * FROM (SELECT 1, 2, 3)) }
} {
do_catchsql_test e_expr-35.2.$tn $sql [list 1 $M]
do_catchsql_test e_expr-35.2.$tn $sql $M
}
# EVIDENCE-OF: R-35764-28041 The result of the expression is the value
+4 -4
View File
@@ -52,11 +52,11 @@ ifcapable trigger&&foreignkey {
#-------------------------------------------------------------------------
# Test the effects of defining OMIT_TRIGGER but not OMIT_FOREIGN_KEY.
#
# EVIDENCE-OF: R-44697-61543 If SQLITE_OMIT_TRIGGER is defined but
# EVIDENCE-OF: R-10109-20452 If SQLITE_OMIT_TRIGGER is defined but
# SQLITE_OMIT_FOREIGN_KEY is not, then SQLite behaves as it did prior to
# version 3.6.19 - foreign key definitions are parsed and may be queried
# using PRAGMA foreign_key_list, but foreign key constraints are not
# enforced.
# version 3.6.19 (2009-10-14) - foreign key definitions are parsed and
# may be queried using PRAGMA foreign_key_list, but foreign key
# constraints are not enforced.
#
# Specifically, test that "PRAGMA foreign_keys" is a no-op in this case.
# When using the pragma to query the current setting, 0 rows are returned.
+1 -1
View File
@@ -13,7 +13,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix e_uri
do_not_use_codec
db close
proc parse_uri {uri} {
+41 -38
View File
@@ -159,37 +159,39 @@ do_test e_vacuum-1.3.1.2 {
execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
} {1024 1}
# EVIDENCE-OF: R-08570-19916 However, when not in write-ahead log mode,
# the page_size and/or auto_vacuum properties of an existing database
# may be changed by using the page_size and/or pragma auto_vacuum
# pragmas and then immediately VACUUMing the database.
#
do_test e_vacuum-1.3.2.1 {
execsql { PRAGMA journal_mode = delete }
execsql { PRAGMA page_size = 2048 }
execsql { PRAGMA auto_vacuum = NONE }
execsql VACUUM
execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
} {2048 0}
# EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the
# auto_vacuum support property can be changed using VACUUM.
#
ifcapable wal {
do_test e_vacuum-1.3.3.1 {
execsql { PRAGMA journal_mode = wal }
execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
} {2048 0}
do_test e_vacuum-1.3.3.2 {
execsql { PRAGMA page_size = 1024 }
execsql { PRAGMA auto_vacuum = FULL }
execsql VACUUM
execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
} {2048 1}
if {![nonzero_reserved_bytes]} {
# EVIDENCE-OF: R-08570-19916 However, when not in write-ahead log mode,
# the page_size and/or auto_vacuum properties of an existing database
# may be changed by using the page_size and/or pragma auto_vacuum
# pragmas and then immediately VACUUMing the database.
#
do_test e_vacuum-1.3.2.1 {
execsql { PRAGMA journal_mode = delete }
execsql { PRAGMA page_size = 2048 }
execsql { PRAGMA auto_vacuum = NONE }
execsql VACUUM
execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
} {2048 0}
# EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the
# auto_vacuum support property can be changed using VACUUM.
#
if {[wal_is_capable]} {
do_test e_vacuum-1.3.3.1 {
execsql { PRAGMA journal_mode = wal }
execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
} {2048 0}
do_test e_vacuum-1.3.3.2 {
execsql { PRAGMA page_size = 1024 }
execsql { PRAGMA auto_vacuum = FULL }
execsql VACUUM
execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
} {2048 1}
}
}
# EVIDENCE-OF: R-38001-03952 VACUUM only works on the main database. It
# is not possible to VACUUM an attached database file.
# EVIDENCE-OF: R-55119-57913 By default, VACUUM only works only on the
# main database.
forcedelete test.db2
create_db { PRAGMA auto_vacuum = NONE }
do_execsql_test e_vacuum-2.1.1 {
@@ -200,14 +202,15 @@ do_execsql_test e_vacuum-2.1.1 {
} {}
set original_size [file size test.db2]
# Try everything we can think of to get the aux database vacuumed:
# Vacuuming the main database does not affect aux
do_execsql_test e_vacuum-2.1.3 { VACUUM } {}
do_execsql_test e_vacuum-2.1.4 { VACUUM aux } {}
do_execsql_test e_vacuum-2.1.5 { VACUUM 'test.db2' } {}
# Despite our efforts, space in the aux database has not been reclaimed:
do_test e_vacuum-2.1.6 { expr {[file size test.db2]==$::original_size} } 1
# EVIDENCE-OF: R-36598-60500 Attached databases can be vacuumed by
# appending the appropriate schema-name to the VACUUM statement.
do_execsql_test e_vacuum-2.1.7 { VACUUM aux; } {}
do_test e_vacuum-2.1.8 { expr {[file size test.db2]<$::original_size} } 1
# EVIDENCE-OF: R-17495-17419 The VACUUM command may change the ROWIDs of
# entries in any tables that do not have an explicit INTEGER PRIMARY
# KEY.
@@ -269,9 +272,9 @@ do_test e_vacuum-3.2.2.1 {
} {1 {cannot VACUUM - SQL statements in progress}}
# EVIDENCE-OF: R-38735-12540 As of SQLite version 3.1, an alternative to
# using the VACUUM command to reclaim space after data has been deleted
# is auto-vacuum mode, enabled using the auto_vacuum pragma.
# EVIDENCE-OF: R-55138-13241 An alternative to using the VACUUM command
# to reclaim space after data has been deleted is auto-vacuum mode,
# enabled using the auto_vacuum pragma.
#
do_test e_vacuum-3.3.1 {
create_db { PRAGMA auto_vacuum = FULL }
+5
View File
@@ -24,6 +24,11 @@ if {$tcl_platform(os) == "OpenBSD"} {
return
}
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
proc read_nbackfill {} {
seek $::shmfd 96
binary scan [read $::shmfd 4] n nBackfill
+3 -3
View File
@@ -161,10 +161,10 @@ do_test 5.2 {
# EVIDENCE-OF: R-42842-27162 Note that the sqlite3_wal_autocheckpoint()
# EVIDENCE-OF: R-57445-43425 Note that the sqlite3_wal_autocheckpoint()
# interface and the wal_autocheckpoint pragma both invoke
# sqlite3_wal_hook() and will those overwrite any prior
# sqlite3_wal_hook() settings.
# sqlite3_wal_hook() and will overwrite any prior sqlite3_wal_hook()
# settings.
#
set ::old_wal_hook 0
proc my_old_wal_hook {args} { incr ::old_wal_hook ; return 0 }
+34 -32
View File
@@ -516,45 +516,47 @@ det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {
}
#-------------------------------------------------------------------------
# The following tests - eqp-6.* - test that the example C code on
# documentation page eqp.html works. The C code is duplicated in test1.c
# and wrapped in Tcl command [print_explain_query_plan]
#
set boilerplate {
proc explain_query_plan {db sql} {
set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY]
print_explain_query_plan $stmt
sqlite3_finalize $stmt
if {![nonzero_reserved_bytes]} {
#-------------------------------------------------------------------------
# The following tests - eqp-6.* - test that the example C code on
# documentation page eqp.html works. The C code is duplicated in test1.c
# and wrapped in Tcl command [print_explain_query_plan]
#
set boilerplate {
proc explain_query_plan {db sql} {
set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY]
print_explain_query_plan $stmt
sqlite3_finalize $stmt
}
sqlite3 db test.db
explain_query_plan db {%SQL%}
db close
exit
}
sqlite3 db test.db
explain_query_plan db {%SQL%}
db close
exit
}
# Do a "Print Explain Query Plan" test.
proc do_peqp_test {tn sql res} {
set fd [open script.tcl w]
puts $fd [string map [list %SQL% $sql] $::boilerplate]
close $fd
uplevel do_test $tn [list {
set fd [open "|[info nameofexec] script.tcl"]
set data [read $fd]
# Do a "Print Explain Query Plan" test.
proc do_peqp_test {tn sql res} {
set fd [open script.tcl w]
puts $fd [string map [list %SQL% $sql] $::boilerplate]
close $fd
set data
}] [list $res]
}
do_peqp_test 6.1 {
SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
} [string trimleft {
uplevel do_test $tn [list {
set fd [open "|[info nameofexec] script.tcl"]
set data [read $fd]
close $fd
set data
}] [list $res]
}
do_peqp_test 6.1 {
SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
} [string trimleft {
1 0 0 SCAN TABLE t1 USING COVERING INDEX i2
2 0 0 SCAN TABLE t2
2 0 0 USE TEMP B-TREE FOR ORDER BY
0 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
}]
}
#-------------------------------------------------------------------------
# The following tests - eqp-7.* - test that queries that use the OP_Count
+6 -3
View File
@@ -420,9 +420,10 @@ do_test exclusive-5.0 {
} {}
do_test exclusive-5.1 {
# Three files are open: The db, journal and statement-journal.
# (2016-03-04) The statement-journal is now opened lazily
set sqlite_open_file_count
expr $sqlite_open_file_count-$extrafds
} [expr 3 - ($TEMP_STORE>=2)]
} {2}
do_test exclusive-5.2 {
execsql {
COMMIT;
@@ -446,17 +447,19 @@ do_test exclusive-5.4 {
INSERT INTO abc SELECT a+10, b+10, c+10 FROM abc;
}
# Three files are open: The db, journal and statement-journal.
# 2016-03-04: The statement-journal open is deferred
set sqlite_open_file_count
expr $sqlite_open_file_count-$extrafds
} [expr 3 - ($TEMP_STORE>=2)]
} {2}
do_test exclusive-5.5 {
execsql {
COMMIT;
}
# Three files are still open: The db, journal and statement-journal.
# 2016-03-04: The statement-journal open is deferred
set sqlite_open_file_count
expr $sqlite_open_file_count-$extrafds
} [expr 3 - ($TEMP_STORE>=2)]
} {2}
do_test exclusive-5.6 {
execsql {
PRAGMA locking_mode = normal;
+1
View File
@@ -19,6 +19,7 @@ source $testdir/lock_common.tcl
foreach jm {rollback wal} {
if {![wal_is_capable] && $jm=="wal"} continue
set testprefix exists-$jm
+27
View File
@@ -308,6 +308,33 @@ ifcapable floatingpoint {if {[working_64bit_int]} {
test_realnum_expr expr-1.257\
{i1=-4294967296, i2=-2147483647} {i1*i2} 9223372032559808512
test_realnum_expr expr-1.260\
{i1=3037000500, i2=3037000500} {i1*i2} 9.22337203700025e+18
test_realnum_expr expr-1.261\
{i1=3037000500, i2=-3037000500} {i1*i2} -9.22337203700025e+18
test_realnum_expr expr-1.262\
{i1=-3037000500, i2=3037000500} {i1*i2} -9.22337203700025e+18
test_realnum_expr expr-1.263\
{i1=-3037000500, i2=-3037000500} {i1*i2} 9.22337203700025e+18
test_realnum_expr expr-1.264\
{i1=3037000500, i2=3037000499} {i1*i2} 9223372033963249500
test_realnum_expr expr-1.265\
{i1=3037000500, i2=-3037000499} {i1*i2} -9223372033963249500
test_realnum_expr expr-1.266\
{i1=-3037000500, i2=3037000499} {i1*i2} -9223372033963249500
test_realnum_expr expr-1.267\
{i1=-3037000500, i2=-3037000499} {i1*i2} 9223372033963249500
test_realnum_expr expr-1.268\
{i1=3037000499, i2=3037000500} {i1*i2} 9223372033963249500
test_realnum_expr expr-1.269\
{i1=3037000499, i2=-3037000500} {i1*i2} -9223372033963249500
test_realnum_expr expr-1.270\
{i1=-3037000499, i2=3037000500} {i1*i2} -9223372033963249500
test_realnum_expr expr-1.271\
{i1=-3037000499, i2=-3037000500} {i1*i2} 9223372033963249500
}}
ifcapable floatingpoint {
+26
View File
@@ -43,4 +43,30 @@ do_test filectrl-1.6 {
} {/etilqs_/}
db close
forcedelete .test_control_lockproxy.db-conch test.proxy
forcedelete test.db test2.db
if {$tcl_platform(platform)=="windows"} {
do_test filectrl-2.1 {
sqlite3 db test2.db
set size [file size test2.db]
set handle [file_control_win32_get_handle db]
db close
forcedelete test2.db
list $size $handle [expr {$handle != 0}]
} {/^0 \{0 \d+\} 1$/}
do_test filectrl-2.2 {
sqlite3 db test2.db
execsql {
CREATE TABLE t1(x);
INSERT INTO t1 (x) VALUES(RANDOMBLOB(1048576));
}
set size [file size test2.db]
set handle [file_control_win32_get_handle db]
db close
forcedelete test2.db
list $size $handle [expr {$handle != 0}]
} {/^1\d+ \{0 \d+\} 1$/}
}
finish_test
+10 -6
View File
@@ -144,9 +144,11 @@ do_execsql_test filefmt-2.1.1 {
CREATE TABLE t2(a);
INSERT INTO t2 VALUES(1);
} {}
do_test filefmt-2.1.2 {
hexio_read test.db 28 4
} {00000009}
if {![nonzero_reserved_bytes]} {
do_test filefmt-2.1.2 {
hexio_read test.db 28 4
} {00000009}
}
do_test filefmt-2.1.3 {
sql36231 { INSERT INTO t1 VALUES(a_string(3000)) }
@@ -170,9 +172,11 @@ do_execsql_test filefmt-2.2.1 {
CREATE TABLE t2(a);
INSERT INTO t2 VALUES(1);
} {}
do_test filefmt-2.2.2 {
hexio_read test.db 28 4
} {00000009}
if {![nonzero_reserved_bytes]} {
do_test filefmt-2.2.2 {
hexio_read test.db 28 4
} {00000009}
}
do_test filefmt-2.2.3 {
sql36231 { INSERT INTO t1 VALUES(a_string(3000)) }
+55 -1
View File
@@ -1,4 +1,4 @@
# 2013-07-11
# 2012 December 17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
@@ -23,6 +23,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fkey6
ifcapable {!foreignkey} {
finish_test
@@ -171,5 +172,58 @@ do_execsql_test fkey6-2.6 {
PRAGMA defer_foreign_keys;
} {0}
#--------------------------------------------------------------------------
# Test that defer_foreign_keys disables RESTRICT.
#
do_execsql_test 3.1 {
CREATE TABLE p2(a PRIMARY KEY, b);
CREATE TABLE c2(x, y REFERENCES p2 ON DELETE RESTRICT ON UPDATE RESTRICT);
INSERT INTO p2 VALUES(1, 'one');
INSERT INTO p2 VALUES(2, 'two');
INSERT INTO c2 VALUES('i', 1);
}
do_catchsql_test 3.2.1 {
BEGIN;
UPDATE p2 SET a=a-1;
} {1 {FOREIGN KEY constraint failed}}
do_execsql_test 3.2.2 { COMMIT }
do_execsql_test 3.2.3 {
BEGIN;
PRAGMA defer_foreign_keys = 1;
UPDATE p2 SET a=a-1;
COMMIT;
}
do_execsql_test 3.2.4 {
BEGIN;
PRAGMA defer_foreign_keys = 1;
UPDATE p2 SET a=a-1;
}
do_catchsql_test 3.2.5 {
COMMIT;
} {1 {FOREIGN KEY constraint failed}}
do_execsql_test 3.2.6 { ROLLBACK }
do_execsql_test 3.3.1 {
CREATE TRIGGER p2t AFTER DELETE ON p2 BEGIN
INSERT INTO p2 VALUES(old.a, 'deleted!');
END;
}
do_catchsql_test 3.3.2 {
BEGIN;
DELETE FROM p2 WHERE a=1;
} {1 {FOREIGN KEY constraint failed}}
do_execsql_test 3.3.3 { COMMIT }
do_execsql_test 3.3.4 {
BEGIN;
PRAGMA defer_foreign_keys = 1;
DELETE FROM p2 WHERE a=1;
COMMIT;
SELECT * FROM p2;
} {0 one 1 deleted!}
finish_test
+42 -41
View File
@@ -56,40 +56,41 @@ proc escape_string {str} {
#
# 5: Test that the table created to use tokenizer 'blah' is usable.
#
ifcapable fts3_tokenizer {
do_test fts3atoken-1.1 {
catchsql {
CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah);
}
} {1 {unknown tokenizer: blah}}
do_test fts3atoken-1.2 {
execsql {
SELECT fts3_tokenizer('blah', fts3_tokenizer('simple')) IS NULL;
}
} {0}
do_test fts3atoken-1.3 {
execsql {
SELECT fts3_tokenizer('blah') == fts3_tokenizer('simple');
}
} {1}
do_test fts3atoken-1.4 {
catchsql {
CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah);
}
} {0 {}}
do_test fts3atoken-1.5 {
execsql {
INSERT INTO t1(content) VALUES('There was movement at the station');
INSERT INTO t1(content) VALUES('For the word has passed around');
INSERT INTO t1(content) VALUES('That the colt from ol regret had got');
SELECT content FROM t1 WHERE content MATCH 'movement'
}
} {{There was movement at the station}}
} else {
do_catchsql_test 1.6 {
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1
do_test fts3atoken-1.1 {
catchsql {
CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah);
}
} {1 {unknown tokenizer: blah}}
do_test fts3atoken-1.2 {
execsql {
SELECT fts3_tokenizer('blah', fts3_tokenizer('simple')) IS NULL;
} {1 {fts3tokenize: disabled - rebuild with -DSQLITE_ENABLE_FTS3_TOKENIZER}}
}
}
} {0}
do_test fts3atoken-1.3 {
execsql {
SELECT fts3_tokenizer('blah') == fts3_tokenizer('simple');
}
} {1}
do_test fts3atoken-1.4 {
catchsql {
CREATE VIRTUAL TABLE t1 USING fts3(content, tokenize blah);
}
} {0 {}}
do_test fts3atoken-1.5 {
execsql {
INSERT INTO t1(content) VALUES('There was movement at the station');
INSERT INTO t1(content) VALUES('For the word has passed around');
INSERT INTO t1(content) VALUES('That the colt from ol regret had got');
SELECT content FROM t1 WHERE content MATCH 'movement'
}
} {{There was movement at the station}}
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 0
do_catchsql_test 1.6 {
SELECT fts3_tokenizer('blah', fts3_tokenizer('simple')) IS NULL;
} {1 {fts3tokenize disabled}}
#--------------------------------------------------------------------------
# Test cases fts3atoken-2.* test error cases in the scalar function based
@@ -212,14 +213,14 @@ do_catchsql_test 6.1.3 {
do_catchsql_test 6.2.1 {
SELECT fts3_tokenizer(NULL);
} {1 {unknown tokenizer: }}
ifcapable fts3_tokenizer {
do_catchsql_test 6.2.2 {
SELECT fts3_tokenizer(NULL, X'1234567812345678');
} {1 {argument type mismatch}}
do_catchsql_test 6.2.3 {
SELECT fts3_tokenizer(NULL, X'12345678');
} {1 {argument type mismatch}}
}
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1
do_catchsql_test 6.2.2 {
SELECT fts3_tokenizer(NULL, X'1234567812345678');
} {1 {argument type mismatch}}
do_catchsql_test 6.2.3 {
SELECT fts3_tokenizer(NULL, X'12345678');
} {1 {argument type mismatch}}
finish_test
+3 -3
View File
@@ -117,12 +117,12 @@ do_test 2.1.2.1 {
set cnt 0
execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND term='braid' }
set cnt
} {2}
} {1}
do_test 2.1.2.2 {
set cnt 0
execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND +term='braid' }
set cnt
} {38}
} {19}
# Similar to the test immediately above, but using a term ("breakfast") that
# is not featured in the dataset.
@@ -136,7 +136,7 @@ do_test 2.1.3.2 {
set cnt 0
execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND +term='breakfast' }
set cnt
} {38}
} {19}
do_execsql_test 2.1.4.1 { SELECT * FROM terms_v WHERE term='braid' } {braid 1 1}
do_execsql_test 2.1.4.2 { SELECT * FROM terms_v WHERE +term='braid'} {braid 1 1}
+38
View File
@@ -211,4 +211,42 @@ do_execsql_test 4.2.2 {
INSERT INTO t01(t01) VALUES('integrity-check');
} {}
do_execsql_test 4.3.1 {
CREATE VIRTUAL TABLE t02 USING fts4;
INSERT INTO t01 VALUES('1 1 1');
INSERT INTO t02 VALUES('2 2 2');
BEGIN;
SAVEPOINT abc;
INSERT INTO t01 VALUES('a b c');
INSERT INTO t02 VALUES('a b c');
ROLLBACK TO abc;
COMMIT;
}
do_execsql_test 4.3.2 {
SELECT * FROM t01 WHERE t01 MATCH 'b';
INSERT INTO t01(t01) VALUES('integrity-check');
} {}
do_execsql_test 4.4.1 {
CREATE TABLE A(ID INTEGER PRIMARY KEY, AnotherID INTEGER, Notes TEXT);
CREATE VIRTUAL TABLE AFTS USING FTS4 (Notes);
CREATE TRIGGER A_DeleteTrigger AFTER DELETE ON A FOR EACH ROW BEGIN
DELETE FROM AFTS WHERE rowid=OLD.ID;
END;
CREATE TABLE B(ID INTEGER PRIMARY KEY,Notes TEXT);
CREATE VIRTUAL TABLE BFTS USING FTS3 (Notes);
CREATE TRIGGER B_DeleteTrigger AFTER DELETE ON B FOR EACH ROW BEGIN
DELETE FROM BFTS WHERE rowid=OLD.ID;
END;
}
do_execsql_test 4.4.2 {
BEGIN TRANSACTION;
DELETE FROM A WHERE AnotherID=1;
DELETE FROM B WHERE ID=1;
COMMIT;
}
finish_test
+4
View File
@@ -514,4 +514,8 @@ do_test fts3expr-9.1 {
test_fts3expr "f (e NEAR/2 a)"
} {AND {PHRASE 3 0 f} {NEAR/2 {PHRASE 3 0 e} {PHRASE 3 0 a}}}
do_test fts3expr-10.1 { test_fts3expr "abc *" } {PHRASE 3 0 abc}
do_test fts3expr-10.2 { test_fts3expr "*" } {}
do_test fts3expr-10.3 { test_fts3expr "abc*" } {PHRASE 3 0 abc+}
finish_test
+22 -18
View File
@@ -59,11 +59,11 @@ do_test 1.4 {
INSERT INTO x1(x1) VALUES('merge=4,4');
SELECT level, end_block, length(root) FROM x1_segdir;
}
} {0 {0 110} 110 0 {0 132} 132 0 {0 129} 129 1 {128 658} 2}
} {1 {224 921} 2}
do_execsql_test 1.5 {
SELECT length(block) FROM x1_segments;
} {658 {}}
} {921 {}}
do_test 1.6 {
foreach L {
@@ -71,27 +71,33 @@ do_test 1.6 {
{That perched above Dead Man's Creek, beside the mountain road.}
{He turned the cycle down the hill and mounted for the fray,}
{But 'ere he'd gone a dozen yards it bolted clean away.}
{It left the track, and through the trees, just like a silver steak,}
{It whistled down the awful slope towards the Dead Man's Creek.}
{It shaved a stump by half an inch, it dodged a big white-box:}
{The very wallaroos in fright went scrambling up the rocks,}
{The wombats hiding in their caves dug deeper underground,}
{As Mulga Bill, as white as chalk, sat tight to every bound.}
{It struck a stone and gave a spring that cleared a fallen tree,}
{It raced beside a precipice as close as close could be;}
{And then as Mulga Bill let out one last despairing shriek}
{It made a leap of twenty feet into the Dead Man's Creek.}
{It shaved a stump by half an inch, it dodged a big white-box:}
{The very wallaroos in fright went scrambling up the rocks,}
{The wombats hiding in their caves dug deeper underground,}
} {
execsql { INSERT INTO x1 VALUES($L) }
}
execsql {
SELECT level, end_block, length(root) FROM x1_segdir;
}
} {1 {128 658} 2 1 {130 1377} 6 0 {0 117} 117}
} {1 {224 921} 2 1 {226 1230} 7 0 {0 98} 98}
do_execsql_test 1.7 {
SELECT sum(length(block)) FROM x1_segments WHERE blockid IN (129, 130);
} {1377}
SELECT sum(length(block)) FROM x1_segments WHERE blockid IN (224,225,226)
} {1230}
#-------------------------------------------------------------------------
#
@@ -131,24 +137,24 @@ do_execsql_test 2.5 {
SELECT end_block FROM x2_segdir WHERE level=3;
INSERT INTO x2(x2) VALUES('merge=4,4');
SELECT end_block FROM x2_segdir WHERE level=3;
} {{3828 -3430} {3828 -10191} {3828 -14109}}
} {{5588 -3950} {5588 -11766} {5588 -15541}}
do_execsql_test 2.6 {
SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE
blockid BETWEEN start_block AND leaves_end_block
AND level=3
} {14109}
} {15541}
do_execsql_test 2.7 {
INSERT INTO x2(x2) VALUES('merge=1000,4');
SELECT end_block FROM x2_segdir WHERE level=3;
} {{3828 86120}}
} {{5588 127563}}
do_execsql_test 2.8 {
SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE
blockid BETWEEN start_block AND leaves_end_block
AND level=3
} {86120}
} {127563}
#--------------------------------------------------------------------------
# Test that delete markers are removed from FTS segments when possible.
@@ -391,7 +397,7 @@ do_execsql_test 7.2 {
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
1 0 {16014 -51226}
1 0 {23694 -69477}
}
do_execsql_test 7.3 {
@@ -400,7 +406,7 @@ do_execsql_test 7.3 {
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
1 0 16014
1 0 23694
}
do_execsql_test 7.4 {
@@ -409,28 +415,26 @@ do_execsql_test 7.4 {
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
1 0 16014
1 0 23694
}
do_execsql_test 7.5 {
INSERT INTO x6(x6) VALUES('merge=2500,4');
SELECT level, idx, end_block FROM x6_segdir;
SELECT level, idx, start_block, leaves_end_block, end_block FROM x6_segdir;
} {
0 0 {598 118006} 0 1 {718 118006} 1 0 16014
1 0 719 1171 23694
}
do_execsql_test 7.6 {
INSERT INTO x6(x6) VALUES('merge=2500,2');
SELECT level, idx, start_block, leaves_end_block, end_block FROM x6_segdir;
} {
2 0 23695 24147 {41262 633507}
1 0 719 1171 23694
}
do_execsql_test 7.7 {
SELECT sum(length(block)) FROM x6_segments
WHERE blockid BETWEEN 23695 AND 24147
} {633507}
} {635247}
finish_test
+24 -25
View File
@@ -358,31 +358,30 @@ proc build_multilingual_db_2 {db} {
}
}
ifcapable fts3_tokenizer {
do_test 4.1.0 {
reset_db
set ptr [fts3_test_tokenizer]
execsql { SELECT fts3_tokenizer('testtokenizer', $ptr) }
build_multilingual_db_2 db
} {}
do_execsql_test 4.1.1 {
SELECT docid FROM t4 WHERE t4 MATCH 'quick';
} {0}
do_execsql_test 4.1.2 {
SELECT docid FROM t4 WHERE t4 MATCH 'quick' AND lid=1;
} {}
do_execsql_test 4.1.3 {
SELECT docid FROM t4 WHERE t4 MATCH 'Quick' AND lid=1;
} {1}
for {set i 0} {$i < 50} {incr i} {
do_execsql_test 4.1.4.$i {
SELECT count(*) FROM t4 WHERE t4 MATCH 'fox' AND lid=$i;
} [expr 0==($i%2)]
}
do_catchsql_test 4.1.5 {
INSERT INTO t4(content, lid) VALUES('hello world', 101)
} {1 {SQL logic error or missing database}}
do_test 4.1.0 {
reset_db
set ptr [fts3_test_tokenizer]
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1
execsql { SELECT fts3_tokenizer('testtokenizer', $ptr) }
build_multilingual_db_2 db
} {}
do_execsql_test 4.1.1 {
SELECT docid FROM t4 WHERE t4 MATCH 'quick';
} {0}
do_execsql_test 4.1.2 {
SELECT docid FROM t4 WHERE t4 MATCH 'quick' AND lid=1;
} {}
do_execsql_test 4.1.3 {
SELECT docid FROM t4 WHERE t4 MATCH 'Quick' AND lid=1;
} {1}
for {set i 0} {$i < 50} {incr i} {
do_execsql_test 4.1.4.$i {
SELECT count(*) FROM t4 WHERE t4 MATCH 'fox' AND lid=$i;
} [expr 0==($i%2)]
}
do_catchsql_test 4.1.5 {
INSERT INTO t4(content, lid) VALUES('hello world', 101)
} {1 {SQL logic error or missing database}}
#-------------------------------------------------------------------------
# Test cases 5.*
@@ -482,6 +481,6 @@ foreach lid [list 4 [expr 1<<30]] {
do_execsql_test 5.4.$lid.5 {
SELECT count(*) FROM t6_segdir;
SELECT count(*) FROM t6_segments;
} {4 4}
} {1 2}
}
finish_test
+8 -18
View File
@@ -55,8 +55,6 @@ foreach mod {fts3 fts4} {
do_execsql_test 1.3 {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
} {
0 {0 1 2 3}
1 {0 1 2 3 4 5 6}
2 {0 1 2 3}
}
@@ -71,7 +69,6 @@ foreach mod {fts3 fts4} {
do_execsql_test 1.5 {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
} {
2 {0 1}
3 0
}
@@ -89,7 +86,6 @@ foreach mod {fts3 fts4} {
5 {merge=6,%}
6 {merge=6,six}
7 {merge=6,1}
8 {merge=6,0}
} {
do_catchsql_test 2.$tn {
INSERT INTO t2(t2) VALUES($arg);
@@ -119,11 +115,7 @@ foreach mod {fts3 fts4} {
INSERT INTO t2(t2) VALUES('merge=1000000,2');
SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level
} {
0 0
2 0
3 0
4 0
6 0
}
#-------------------------------------------------------------------------
@@ -203,28 +195,27 @@ foreach mod {fts3 fts4} {
INSERT INTO t1(t1) VALUES('merge=1,5');
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
} {
0 {0 1 2}
1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14}
2 {0 1 2 3}
}
do_execsql_test 5.4 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'0105'}
do_execsql_test 5.4 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'010F'}
do_test 5.5 {
foreach docid [execsql {SELECT docid FROM t1}] {
execsql {INSERT INTO t1 SELECT * FROM t1 WHERE docid=$docid}
}
} {}
do_execsql_test 5.6 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'0105'}
do_execsql_test 5.6 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'010F'}
do_execsql_test 5.7 {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
SELECT quote(value) from t1_stat WHERE rowid=1;
} {
0 {0 1 2 3 4 5 6 7 8 9 10}
0 {0 1 2 3 4 5 6 7}
1 {0 1 2 3 4 5 6 7 8 9 10 11 12}
2 {0 1 2 3 4 5 6 7}
X'0105'
2 {0 1 2 3 4 5 6 7}
X'010F'
}
do_execsql_test 5.8 {
@@ -233,9 +224,8 @@ foreach mod {fts3 fts4} {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
SELECT quote(value) from t1_stat WHERE rowid=1;
} {
0 {0 1 2 3 4}
1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13}
2 {0 1 2 3 4 5 6 7 8} X'0106'
2 {0 1 2 3 4 5 6 7 8} X'010E'
}
do_test 5.8.1 { fts3_integrity_check t1 } ok
@@ -253,7 +243,7 @@ foreach mod {fts3 fts4} {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
SELECT quote(value) from t1_stat WHERE rowid=1;
} {
0 0 1 {0 1} 2 0 3 0 X'0106'
0 {0 1 2 3 4 5 6 7 8 9 10 11} 1 0 2 0 3 0 X'010E'
}
do_execsql_test 5.11 {
@@ -261,7 +251,7 @@ foreach mod {fts3 fts4} {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
SELECT quote(value) from t1_stat WHERE rowid=1;
} {
0 0 1 {0 1} 2 0 3 0 X''
1 {0 1} 2 0 3 0 X'010E'
}
#-------------------------------------------------------------------------
+3 -3
View File
@@ -62,7 +62,7 @@ do_all_bc_test {
do_test 1.7 { sql2 {
SELECT level, count(*) FROM t2_segdir GROUP BY level ORDER BY 1
} } [list 0 1 2 18 3 5]
} } {2 15 3 5}
# Using the old connection, insert many rows.
do_test 1.8 {
@@ -73,7 +73,7 @@ do_all_bc_test {
do_test 1.9 { sql2 {
SELECT level, count(*) FROM t2_segdir GROUP BY level ORDER BY 1
} } [list 0 13 1 13 2 5 3 6]
} } [list 0 12 1 13 2 4 3 6]
# Run a big incr-merge operation on the db.
do_test 1.10 { sql1 { INSERT INTO t2(t2) VALUES('merge=2000,2') } } {}
@@ -97,7 +97,7 @@ do_all_bc_test {
do_test 1.15 { sql2 {
SELECT level, count(*) FROM t2_segdir GROUP BY level ORDER BY 1
} } {6 1}
} } {4 1}
}
}
+213
View File
@@ -0,0 +1,213 @@
# 2016 March 8
#
# 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
source $testdir/fts3_common.tcl
set ::testprefix fts4opt
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
finish_test
return
}
# Create the fts_kjv_genesis procedure which fills and FTS3/4 table
# with the complete text of the Book of Genesis.
#
source $testdir/genesis.tcl
do_execsql_test 1.0 { CREATE TABLE t1(docid, words) }
fts_kjv_genesis
#-------------------------------------------------------------------------
# Argument $db is an open database handle. $tbl is the name of an FTS3/4
# table with the database. This command rearranges the contents of the
# %_segdir table so that all segments within each index are on the same
# level. This means that the 'merge' command can then be used for an
# incremental optimize routine.
#
proc prepare_for_optimize {db tbl} {
$db eval [string map [list % $tbl] {
BEGIN;
CREATE TEMP TABLE tmp_segdir(
level, idx, start_block, leaves_end_block, end_block, root
);
INSERT INTO temp.tmp_segdir
SELECT
1024*(o.level / 1024) + 32, -- level
sum(o.level<i.level OR (o.level=i.level AND o.idx>i.idx)), -- idx
o.start_block, o.leaves_end_block, o.end_block, o.root -- other
FROM %_segdir o, %_segdir i
WHERE (o.level / 1024) = (i.level / 1024)
GROUP BY o.level, o.idx;
DELETE FROM %_segdir;
INSERT INTO %_segdir SELECT * FROM temp.tmp_segdir;
DROP TABLE temp.tmp_segdir;
COMMIT;
}]
}
do_test 1.1 {
execsql { CREATE VIRTUAL TABLE t2 USING fts4(words, prefix="1,2,3") }
foreach {docid words} [db eval { SELECT * FROM t1 }] {
execsql { INSERT INTO t2(docid, words) VALUES($docid, $words) }
}
} {}
do_execsql_test 1.2 {
SELECT level, count(*) FROM t2_segdir GROUP BY level
} {
0 13 1 15 2 5
1024 13 1025 15 1026 5
2048 13 2049 15 2050 5
3072 13 3073 15 3074 5
}
do_execsql_test 1.3 { INSERT INTO t2(t2) VALUES('integrity-check') }
prepare_for_optimize db t2
do_execsql_test 1.4 { INSERT INTO t2(t2) VALUES('integrity-check') }
do_execsql_test 1.5 {
SELECT level, count(*) FROM t2_segdir GROUP BY level
} {
32 33
1056 33
2080 33
3104 33
}
do_test 1.6 {
while 1 {
set tc1 [db total_changes]
execsql { INSERT INTO t2(t2) VALUES('merge=5,2') }
set tc2 [db total_changes]
if {($tc2 - $tc1) < 2} break
}
execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level }
} {33 1 1057 1 2081 1 3105 1}
do_execsql_test 1.7 { INSERT INTO t2(t2) VALUES('integrity-check') }
do_execsql_test 1.8 {
INSERT INTO t2(words) SELECT words FROM t1;
SELECT level, count(*) FROM t2_segdir GROUP BY level;
} {0 2 1024 2 2048 2 3072 2}
#-------------------------------------------------------------------------
do_execsql_test 2.0 {
DELETE FROM t2;
}
do_test 2.1 {
foreach {docid words} [db eval { SELECT * FROM t1 }] {
execsql { INSERT INTO t2(docid, words) VALUES($docid, $words) }
}
set i 0
foreach {docid words} [db eval { SELECT * FROM t1 }] {
if {[incr i] % 2} { execsql { DELETE FROM t2 WHERE docid = $docid } }
}
set i 0
foreach {docid words} [db eval { SELECT * FROM t1 }] {
if {[incr i] % 3} {
execsql { INSERT OR REPLACE INTO t2(docid, words) VALUES($docid, $words) }
}
}
} {}
do_execsql_test 2.2 {
SELECT level, count(*) FROM t2_segdir GROUP BY level
} {
0 10 1 15 2 12
1024 10 1025 15 1026 12
2048 10 2049 15 2050 12
3072 10 3073 15 3074 12
}
do_execsql_test 2.3 { INSERT INTO t2(t2) VALUES('integrity-check') }
prepare_for_optimize db t2
do_execsql_test 2.4 { INSERT INTO t2(t2) VALUES('integrity-check') }
do_execsql_test 2.5 {
SELECT level, count(*) FROM t2_segdir GROUP BY level
} {
32 37
1056 37
2080 37
3104 37
}
do_test 2.6 {
while 1 {
set tc1 [db total_changes]
execsql { INSERT INTO t2(t2) VALUES('merge=5,2') }
set tc2 [db total_changes]
if {($tc2 - $tc1) < 2} break
}
execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level }
} {33 1 1057 1 2081 1 3105 1}
do_execsql_test 2.7 { INSERT INTO t2(t2) VALUES('integrity-check') }
do_execsql_test 2.8 {
INSERT INTO t2(words) SELECT words FROM t1;
SELECT level, count(*) FROM t2_segdir GROUP BY level;
} {0 2 1024 2 2048 2 3072 2}
#-------------------------------------------------------------------------
# Check that 'optimize' works when there is data in the in-memory hash
# table, but no segments at all on disk.
#
do_execsql_test 3.1 {
CREATE VIRTUAL TABLE fts USING fts4 (t);
INSERT INTO fts (fts) VALUES ('optimize');
}
do_execsql_test 3.2 {
INSERT INTO fts(fts) VALUES('integrity-check');
SELECT count(*) FROM fts_segdir;
} {0}
do_execsql_test 3.3 {
BEGIN;
INSERT INTO fts (rowid, t) VALUES (2, 'test');
INSERT INTO fts (fts) VALUES ('optimize');
COMMIT;
SELECT level, idx FROM fts_segdir;
} {0 0}
do_execsql_test 3.4 {
INSERT INTO fts(fts) VALUES('integrity-check');
SELECT rowid FROM fts WHERE fts MATCH 'test';
} {2}
do_execsql_test 3.5 {
INSERT INTO fts (fts) VALUES ('optimize');
INSERT INTO fts(fts) VALUES('integrity-check');
}
do_test 3.6 {
set c1 [db total_changes]
execsql { INSERT INTO fts (fts) VALUES ('optimize') }
expr {[db total_changes] - $c1}
} {1}
do_test 3.7 {
execsql { INSERT INTO fts (rowid, t) VALUES (3, 'xyz') }
set c1 [db total_changes]
execsql { INSERT INTO fts (fts) VALUES ('optimize') }
expr {([db total_changes] - $c1) > 1}
} {1}
do_test 3.8 {
set c1 [db total_changes]
execsql { INSERT INTO fts (fts) VALUES ('optimize') }
expr {[db total_changes] - $c1}
} {1}
finish_test
+4
View File
@@ -1997,5 +1997,9 @@ NULL AND ("9_u" COLLATE NOCASE = ? COLLATE NOCASE))) FROM (SELECT
}
} {/.* Goto .*/}
# Crash reported by OSS-FUZZ on 2016-11-10
do_catchsql_test fuzz-oss1-detach {
DETACH x IS #1;
} {1 {near "#1": syntax error}}
finish_test
+27 -25
View File
@@ -70,6 +70,7 @@
#include <stdarg.h>
#include <ctype.h>
#include "sqlite3.h"
#include <assert.h>
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))
@@ -188,7 +189,7 @@ static int progressHandler(void *pVdbeLimitFlag){
** Reallocate memory. Show and error and quit if unable.
*/
static void *safe_realloc(void *pOld, int szNew){
void *pNew = realloc(pOld, szNew);
void *pNew = realloc(pOld, szNew<=0 ? 1 : szNew);
if( pNew==0 ) fatalError("unable to realloc for %d bytes", szNew);
return pNew;
}
@@ -255,8 +256,9 @@ static VFile *createVFile(const char *zName, int sz, unsigned char *pData){
if( i>=MX_FILE ) return 0;
pNew = &g.aFile[i];
if( zName ){
pNew->zFilename = safe_realloc(0, strlen(zName)+1);
memcpy(pNew->zFilename, zName, strlen(zName)+1);
int nName = (int)strlen(zName)+1;
pNew->zFilename = safe_realloc(0, nName);
memcpy(pNew->zFilename, zName, nName);
}else{
pNew->zFilename = 0;
}
@@ -620,12 +622,14 @@ static void inmemVfsRegister(void){
*/
static void runSql(sqlite3 *db, const char *zSql, unsigned runFlags){
const char *zMore;
const char *zEnd = &zSql[strlen(zSql)];
sqlite3_stmt *pStmt;
while( zSql && zSql[0] ){
zMore = 0;
pStmt = 0;
sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zMore);
assert( zMore<=zEnd );
if( zMore==zSql ) break;
if( runFlags & SQL_TRACE ){
const char *z = zSql;
@@ -778,25 +782,23 @@ static void showHelp(void){
"Read databases and SQL scripts from SOURCE-DB and execute each script against\n"
"each database, checking for crashes and memory leaks.\n"
"Options:\n"
" --cell-size-check Set the PRAGMA cell_size_check=ON\n"
" --dbid N Use only the database where dbid=N\n"
" --export-db DIR Write databases to files(s) in DIR. Works with --dbid\n"
" --export-sql DIR Write SQL to file(s) in DIR. Also works with --sqlid\n"
" --help Show this help text\n"
" -q Reduced output\n"
" --quiet Reduced output\n"
" --limit-mem N Limit memory used by test SQLite instance to N bytes\n"
" --limit-vdbe Panic if an sync SQL runs for more than 100,000 cycles\n"
" --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n"
" --load-db ARGS... Load template databases from files into SOURCE_DB\n"
" -m TEXT Add a description to the database\n"
" --native-vfs Use the native VFS for initially empty database files\n"
" --rebuild Rebuild and vacuum the database file\n"
" --result-trace Show the results of each SQL command\n"
" --sqlid N Use only SQL where sqlid=N\n"
" --timeout N Abort if any single test case needs more than N seconds\n"
" -v Increased output\n"
" --verbose Increased output\n"
" --cell-size-check Set the PRAGMA cell_size_check=ON\n"
" --dbid N Use only the database where dbid=N\n"
" --export-db DIR Write databases to files(s) in DIR. Works with --dbid\n"
" --export-sql DIR Write SQL to file(s) in DIR. Also works with --sqlid\n"
" --help Show this help text\n"
" -q|--quiet Reduced output\n"
" --limit-mem N Limit memory used by test SQLite instance to N bytes\n"
" --limit-vdbe Panic if any test runs for more than 100,000 cycles\n"
" --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n"
" --load-db ARGS... Load template databases from files into SOURCE_DB\n"
" -m TEXT Add a description to the database\n"
" --native-vfs Use the native VFS for initially empty database files\n"
" --rebuild Rebuild and vacuum the database file\n"
" --result-trace Show the results of each SQL command\n"
" --sqlid N Use only SQL where sqlid=N\n"
" --timeout N Abort if any single test needs more than N seconds\n"
" -v|--verbose Increased output. Repeat for more output.\n"
);
}
@@ -919,8 +921,8 @@ int main(int argc, char **argv){
}else
if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
quietFlag = 0;
verboseFlag = 1;
runFlags |= SQL_TRACE;
verboseFlag++;
if( verboseFlag>1 ) runFlags |= SQL_TRACE;
}else
{
fatalError("unknown option: %s", argv[i]);
@@ -1055,7 +1057,7 @@ int main(int argc, char **argv){
/* Print the description, if there is one */
if( !quietFlag ){
zDbName = azSrcDb[iSrcDb];
i = strlen(zDbName) - 1;
i = (int)strlen(zDbName) - 1;
while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; }
zDbName += i;
sqlite3_prepare_v2(db, "SELECT msg FROM readme", -1, &pStmt, 0);
+410
View File
@@ -21,6 +21,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix hook
do_test hook-1.2 {
db commit_hook
@@ -438,4 +439,413 @@ do_test hook-6.2 {
} {COMMIT ROLLBACK}
unset ::hooks
#----------------------------------------------------------------------------
# The following tests - hook-7.* - test the pre-update hook.
#
ifcapable !preupdate {
finish_test
return
}
#
# 7.1.1 - INSERT statement.
# 7.1.2 - INSERT INTO ... SELECT statement.
# 7.1.3 - REPLACE INTO ... (rowid conflict)
# 7.1.4 - REPLACE INTO ... (other index conflicts)
# 7.1.5 - REPLACE INTO ... (both rowid and other index conflicts)
#
# 7.2.1 - DELETE statement.
# 7.2.2 - DELETE statement that uses the truncate optimization.
#
# 7.3.1 - UPDATE statement.
# 7.3.2 - UPDATE statement that modifies the rowid.
# 7.3.3 - UPDATE OR REPLACE ... (rowid conflict).
# 7.3.4 - UPDATE OR REPLACE ... (other index conflicts)
# 7.3.4 - UPDATE OR REPLACE ... (both rowid and other index conflicts)
#
# 7.4.1 - Test that the pre-update-hook is invoked only once if a row being
# deleted is removed by a BEFORE trigger.
#
# 7.4.2 - Test that the pre-update-hook is invoked if a BEFORE trigger
# removes a row being updated. In this case the update hook should
# be invoked with SQLITE_INSERT as the opcode when inserting the
# new version of the row.
#
# TODO: Short records (those created before a column is added to a table
# using ALTER TABLE)
#
proc do_preupdate_test {tn sql x} {
set X [list]
foreach elem $x {lappend X $elem}
uplevel do_test $tn [list "
set ::preupdate \[list\]
execsql { $sql }
set ::preupdate
"] [list $X]
}
proc preupdate_hook {args} {
set type [lindex $args 0]
eval lappend ::preupdate $args
if {$type != "INSERT"} {
for {set i 0} {$i < [db preupdate count]} {incr i} {
lappend ::preupdate [db preupdate old $i]
}
}
if {$type != "DELETE"} {
for {set i 0} {$i < [db preupdate count]} {incr i} {
set rc [catch { db preupdate new $i } v]
lappend ::preupdate $v
}
}
}
db close
forcedelete test.db
sqlite3 db test.db
db preupdate hook preupdate_hook
# Set up a schema to use for tests 7.1.* to 7.3.*.
do_execsql_test 7.0 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(x, y);
CREATE TABLE t3(i, j, UNIQUE(i));
INSERT INTO t2 VALUES('a', 'b');
INSERT INTO t2 VALUES('c', 'd');
INSERT INTO t3 VALUES(4, 16);
INSERT INTO t3 VALUES(5, 25);
INSERT INTO t3 VALUES(6, 36);
}
do_preupdate_test 7.1.1 {
INSERT INTO t1 VALUES('x', 'y')
} {INSERT main t1 1 1 x y}
# 7.1.2.1 does not use the xfer optimization. 7.1.2.2 does.
do_preupdate_test 7.1.2.1 {
INSERT INTO t1 SELECT y, x FROM t2;
} {INSERT main t1 2 2 b a INSERT main t1 3 3 d c}
do_preupdate_test 7.1.2.2 {
INSERT INTO t1 SELECT * FROM t2;
} {INSERT main t1 4 4 a b INSERT main t1 5 5 c d}
do_preupdate_test 7.1.3 {
REPLACE INTO t1(rowid, a, b) VALUES(1, 1, 1);
} {
DELETE main t1 1 1 x y
INSERT main t1 1 1 1 1
}
do_preupdate_test 7.1.4 {
REPLACE INTO t3 VALUES(4, NULL);
} {
DELETE main t3 1 1 4 16
INSERT main t3 4 4 4 {}
}
do_preupdate_test 7.1.5 {
REPLACE INTO t3(rowid, i, j) VALUES(2, 6, NULL);
} {
DELETE main t3 2 2 5 25
DELETE main t3 3 3 6 36
INSERT main t3 2 2 6 {}
}
do_execsql_test 7.2.0 { SELECT rowid FROM t1 } {1 2 3 4 5}
do_preupdate_test 7.2.1 {
DELETE FROM t1 WHERE rowid = 3
} {
DELETE main t1 3 3 d c
}
do_preupdate_test 7.2.2 {
DELETE FROM t1
} {
DELETE main t1 1 1 1 1
DELETE main t1 2 2 b a
DELETE main t1 4 4 a b
DELETE main t1 5 5 c d
}
do_execsql_test 7.3.0 {
DELETE FROM t1;
DELETE FROM t2;
DELETE FROM t3;
INSERT INTO t2 VALUES('a', 'b');
INSERT INTO t2 VALUES('c', 'd');
INSERT INTO t3 VALUES(4, 16);
INSERT INTO t3 VALUES(5, 25);
INSERT INTO t3 VALUES(6, 36);
}
do_preupdate_test 7.3.1 {
UPDATE t2 SET y = y||y;
} {
UPDATE main t2 1 1 a b a bb
UPDATE main t2 2 2 c d c dd
}
do_preupdate_test 7.3.2 {
UPDATE t2 SET rowid = rowid-1;
} {
UPDATE main t2 1 0 a bb a bb
UPDATE main t2 2 1 c dd c dd
}
do_preupdate_test 7.3.3 {
UPDATE OR REPLACE t2 SET rowid = 1 WHERE x = 'a'
} {
DELETE main t2 1 1 c dd
UPDATE main t2 0 1 a bb a bb
}
do_preupdate_test 7.3.4.1 {
UPDATE OR REPLACE t3 SET i = 5 WHERE i = 6
} {
DELETE main t3 2 2 5 25
UPDATE main t3 3 3 6 36 5 36
}
do_execsql_test 7.3.4.2 {
INSERT INTO t3 VALUES(10, 100);
SELECT rowid, * FROM t3;
} {1 4 16 3 5 36 4 10 100}
do_preupdate_test 7.3.5 {
UPDATE OR REPLACE t3 SET rowid = 1, i = 5 WHERE j = 100;
} {
DELETE main t3 1 1 4 16
DELETE main t3 3 3 5 36
UPDATE main t3 4 1 10 100 5 100
}
do_execsql_test 7.4.1.0 {
CREATE TABLE t4(a, b);
INSERT INTO t4 VALUES('a', 1);
INSERT INTO t4 VALUES('b', 2);
INSERT INTO t4 VALUES('c', 3);
CREATE TRIGGER t4t BEFORE DELETE ON t4 BEGIN
DELETE FROM t4 WHERE b = 1;
END;
}
do_preupdate_test 7.4.1.1 {
DELETE FROM t4 WHERE b = 3
} {
DELETE main t4 1 1 a 1
DELETE main t4 3 3 c 3
}
do_execsql_test 7.4.1.2 {
INSERT INTO t4(rowid, a, b) VALUES(1, 'a', 1);
INSERT INTO t4(rowid, a, b) VALUES(3, 'c', 3);
}
do_preupdate_test 7.4.1.3 {
DELETE FROM t4 WHERE b = 1
} {
DELETE main t4 1 1 a 1
}
do_execsql_test 7.4.2.0 {
CREATE TABLE t5(a, b);
INSERT INTO t5 VALUES('a', 1);
INSERT INTO t5 VALUES('b', 2);
INSERT INTO t5 VALUES('c', 3);
CREATE TRIGGER t5t BEFORE UPDATE ON t5 BEGIN
DELETE FROM t5 WHERE b = 1;
END;
}
do_preupdate_test 7.4.2.1 {
UPDATE t5 SET b = 4 WHERE a = 'c'
} {
DELETE main t5 1 1 a 1
UPDATE main t5 3 3 c 3 c 4
}
do_execsql_test 7.4.2.2 {
INSERT INTO t5(rowid, a, b) VALUES(1, 'a', 1);
}
do_preupdate_test 7.4.2.3 {
UPDATE t5 SET b = 5 WHERE a = 'a'
} {
DELETE main t5 1 1 a 1
}
do_execsql_test 7.5.1.0 {
CREATE TABLE t7(a, b);
INSERT INTO t7 VALUES('one', 'two');
INSERT INTO t7 VALUES('three', 'four');
ALTER TABLE t7 ADD COLUMN c DEFAULT NULL;
}
do_preupdate_test 7.5.1.1 {
DELETE FROM t7 WHERE a = 'one'
} {
DELETE main t7 1 1 one two {}
}
do_preupdate_test 7.5.1.2 {
UPDATE t7 SET b = 'five'
} {
UPDATE main t7 2 2 three four {} three five {}
}
do_execsql_test 7.5.2.0 {
CREATE TABLE t8(a, b);
INSERT INTO t8 VALUES('one', 'two');
INSERT INTO t8 VALUES('three', 'four');
ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx';
}
if 0 {
# At time of writing, these two are broken. They demonstrate that the
# sqlite3_preupdate_old() method does not handle the case where ALTER TABLE
# has been used to add a column with a default value other than NULL.
#
do_preupdate_test 7.5.2.1 {
DELETE FROM t8 WHERE a = 'one'
} {
DELETE main t8 1 1 one two xxx
}
do_preupdate_test 7.5.2.2 {
UPDATE t8 SET b = 'five'
} {
UPDATE main t8 2 2 three four xxx three five xxx
}
}
# This block of tests verifies that IPK values are correctly reported
# by the sqlite3_preupdate_old() and sqlite3_preupdate_new() functions.
#
do_execsql_test 7.6.1 { CREATE TABLE t9(a, b INTEGER PRIMARY KEY, c) }
do_preupdate_test 7.6.2 {
INSERT INTO t9 VALUES(1, 2, 3);
UPDATE t9 SET b = b+1, c = c+1;
DELETE FROM t9 WHERE a = 1;
} {
INSERT main t9 2 2 1 2 3
UPDATE main t9 2 3 1 2 3 1 3 4
DELETE main t9 3 3 1 3 4
}
#--------------------------------------------------------------------------
# Test that the sqlite3_preupdate_depth() API seems to work.
#
proc preupdate_hook {args} {
set type [lindex $args 0]
eval lappend ::preupdate $args
eval lappend ::preupdate [db preupdate depth]
if {$type != "INSERT"} {
for {set i 0} {$i < [db preupdate count]} {incr i} {
lappend ::preupdate [db preupdate old $i]
}
}
if {$type != "DELETE"} {
for {set i 0} {$i < [db preupdate count]} {incr i} {
set rc [catch { db preupdate new $i } v]
lappend ::preupdate $v
}
}
}
db close
forcedelete test.db
sqlite3 db test.db
db preupdate hook preupdate_hook
do_execsql_test 7.6.1 {
CREATE TABLE t1(x PRIMARY KEY);
CREATE TABLE t2(x PRIMARY KEY);
CREATE TABLE t3(x PRIMARY KEY);
CREATE TABLE t4(x PRIMARY KEY);
CREATE TRIGGER a AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(new.x); END;
CREATE TRIGGER b AFTER INSERT ON t2 BEGIN INSERT INTO t3 VALUES(new.x); END;
CREATE TRIGGER c AFTER INSERT ON t3 BEGIN INSERT INTO t4 VALUES(new.x); END;
CREATE TRIGGER d AFTER UPDATE ON t1 BEGIN UPDATE t2 SET x = new.x; END;
CREATE TRIGGER e AFTER UPDATE ON t2 BEGIN UPDATE t3 SET x = new.x; END;
CREATE TRIGGER f AFTER UPDATE ON t3 BEGIN UPDATE t4 SET x = new.x; END;
CREATE TRIGGER g AFTER DELETE ON t1 BEGIN DELETE FROM t2 WHERE 1; END;
CREATE TRIGGER h AFTER DELETE ON t2 BEGIN DELETE FROM t3 WHERE 1; END;
CREATE TRIGGER i AFTER DELETE ON t3 BEGIN DELETE FROM t4 WHERE 1; END;
}
do_preupdate_test 7.6.2 {
INSERT INTO t1 VALUES('xyz');
} {
INSERT main t1 1 1 0 xyz
INSERT main t2 1 1 1 xyz
INSERT main t3 1 1 2 xyz
INSERT main t4 1 1 3 xyz
}
do_preupdate_test 7.6.3 {
UPDATE t1 SET x = 'abc';
} {
UPDATE main t1 1 1 0 xyz abc
UPDATE main t2 1 1 1 xyz abc
UPDATE main t3 1 1 2 xyz abc
UPDATE main t4 1 1 3 xyz abc
}
do_preupdate_test 7.6.4 {
DELETE FROM t1 WHERE 1;
} {
DELETE main t1 1 1 0 abc
DELETE main t2 1 1 1 abc
DELETE main t3 1 1 2 abc
DELETE main t4 1 1 3 abc
}
do_execsql_test 7.6.5 {
DROP TRIGGER a; DROP TRIGGER b; DROP TRIGGER c;
DROP TRIGGER d; DROP TRIGGER e; DROP TRIGGER f;
DROP TRIGGER g; DROP TRIGGER h; DROP TRIGGER i;
CREATE TRIGGER a BEFORE INSERT ON t1 BEGIN INSERT INTO t2 VALUES(new.x); END;
CREATE TRIGGER b BEFORE INSERT ON t2 BEGIN INSERT INTO t3 VALUES(new.x); END;
CREATE TRIGGER c BEFORE INSERT ON t3 BEGIN INSERT INTO t4 VALUES(new.x); END;
CREATE TRIGGER d BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET x = new.x; END;
CREATE TRIGGER e BEFORE UPDATE ON t2 BEGIN UPDATE t3 SET x = new.x; END;
CREATE TRIGGER f BEFORE UPDATE ON t3 BEGIN UPDATE t4 SET x = new.x; END;
CREATE TRIGGER g BEFORE DELETE ON t1 BEGIN DELETE FROM t2 WHERE 1; END;
CREATE TRIGGER h BEFORE DELETE ON t2 BEGIN DELETE FROM t3 WHERE 1; END;
CREATE TRIGGER i BEFORE DELETE ON t3 BEGIN DELETE FROM t4 WHERE 1; END;
}
do_preupdate_test 7.6.6 {
INSERT INTO t1 VALUES('xyz');
} {
INSERT main t4 1 1 3 xyz
INSERT main t3 1 1 2 xyz
INSERT main t2 1 1 1 xyz
INSERT main t1 1 1 0 xyz
}
do_preupdate_test 7.6.3 {
UPDATE t1 SET x = 'abc';
} {
UPDATE main t4 1 1 3 xyz abc
UPDATE main t3 1 1 2 xyz abc
UPDATE main t2 1 1 1 xyz abc
UPDATE main t1 1 1 0 xyz abc
}
do_preupdate_test 7.6.4 {
DELETE FROM t1 WHERE 1;
} {
DELETE main t4 1 1 3 abc
DELETE main t3 1 1 2 abc
DELETE main t2 1 1 1 abc
DELETE main t1 1 1 0 abc
}
finish_test
+9
View File
@@ -72,6 +72,10 @@ test_expr icu-2.6 {i1=$::OGRAVE} {upper(i1)} $::OGRAVE
test_expr icu-2.7 {i1=$::szlig} {upper(i1)} "SS"
test_expr icu-2.8 {i1='SS'} {lower(i1)} "ss"
do_execsql_test icu-2.9 {
SELECT upper(char(0xfb04,0xfb04,0xfb04,0xfb04));
} {FFLFFLFFLFFL}
# In turkish (locale="tr_TR"), the lower case version of I
# is "small dotless i" (code point 0x131 (decimal 305)).
#
@@ -133,4 +137,9 @@ do_catchsql_test icu-5.4 {
do_catchsql_test icu-5.4 { SELECT 'abc' REGEXP } {1 {near " ": syntax error}}
do_catchsql_test icu-5.5 { SELECT 'abc' REGEXP, 1 } {1 {near ",": syntax error}}
do_malloc_test icu-6.10 -sqlbody {
SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04));
}
finish_test
+19 -7
View File
@@ -314,7 +314,7 @@ do_test in-9.4 {
catchsql {
SELECT b FROM t1 WHERE a NOT IN tb;
}
} {1 {only a single result allowed for a SELECT that is part of an expression}}
} {1 {sub-select returns 2 columns - expected 1}}
# IN clauses in CHECK constraints. Ticket #1645
#
@@ -391,28 +391,28 @@ do_test in-12.2 {
SELECT a, b FROM t3 UNION ALL SELECT a, b FROM t2
);
}
} {1 {only a single result allowed for a SELECT that is part of an expression}}
} {1 {sub-select returns 2 columns - expected 1}}
do_test in-12.3 {
catchsql {
SELECT * FROM t2 WHERE a IN (
SELECT a, b FROM t3 UNION SELECT a, b FROM t2
);
}
} {1 {only a single result allowed for a SELECT that is part of an expression}}
} {1 {sub-select returns 2 columns - expected 1}}
do_test in-12.4 {
catchsql {
SELECT * FROM t2 WHERE a IN (
SELECT a, b FROM t3 EXCEPT SELECT a, b FROM t2
);
}
} {1 {only a single result allowed for a SELECT that is part of an expression}}
} {1 {sub-select returns 2 columns - expected 1}}
do_test in-12.5 {
catchsql {
SELECT * FROM t2 WHERE a IN (
SELECT a, b FROM t3 INTERSECT SELECT a, b FROM t2
);
}
} {1 {only a single result allowed for a SELECT that is part of an expression}}
} {1 {sub-select returns 2 columns - expected 1}}
do_test in-12.6 {
catchsql {
SELECT * FROM t2 WHERE a IN (
@@ -478,7 +478,7 @@ do_test in-12.14 {
SELECT a, b FROM t3 UNION ALL SELECT a, b FROM t2
);
}
} {1 {only a single result allowed for a SELECT that is part of an expression}}
} {1 {sub-select returns 2 columns - expected 1}}
do_test in-12.15 {
catchsql {
SELECT * FROM t2 WHERE a IN (
@@ -629,15 +629,27 @@ do_test in-13.14 {
}
} {}
breakpoint
do_test in-13.15 {
catchsql {
SELECT 0 WHERE (SELECT 0,0) OR (0 IN (1,2));
}
} {1 {only a single result allowed for a SELECT that is part of an expression}}
} {1 {sub-select returns 2 columns - expected 1}}
do_test in-13.X {
db nullvalue ""
} {}
# At one point the following was causing valgrind to report a "jump
# depends on unitialized location" problem.
#
do_execsql_test in-14.0 {
CREATE TABLE c1(a);
INSERT INTO c1 VALUES(1), (2), (4), (3);
}
do_execsql_test in-14.1 {
SELECT * FROM c1 WHERE a IN (SELECT a FROM c1) ORDER BY 1
} {1 2 3 4}
finish_test
+54
View File
@@ -183,4 +183,58 @@ do_execsql_test 6.3.1 {
SELECT count(*) FROM x2 WHERE b IN (SELECT DISTINCT a FROM x1 LIMIT 2);
} {2}
#-------------------------------------------------------------------------
# Test to confirm that bug [5e3c886796e5] is fixed.
#
do_execsql_test 7.1 {
CREATE TABLE y1(a, b);
CREATE TABLE y2(c);
INSERT INTO y1 VALUES(1, 'one');
INSERT INTO y1 VALUES('two', 'two');
INSERT INTO y1 VALUES(3, 'three');
INSERT INTO y2 VALUES('one');
INSERT INTO y2 VALUES('two');
INSERT INTO y2 VALUES('three');
} {}
do_execsql_test 7.2.1 {
SELECT a FROM y1 WHERE b NOT IN (SELECT a FROM y2);
} {1 3}
do_execsql_test 7.2.2 {
SELECT a FROM y1 WHERE b IN (SELECT a FROM y2);
} {two}
do_execsql_test 7.3.1 {
CREATE INDEX y2c ON y2(c);
SELECT a FROM y1 WHERE b NOT IN (SELECT a FROM y2);
} {1 3}
do_execsql_test 7.3.2 {
SELECT a FROM y1 WHERE b IN (SELECT a FROM y2);
} {two}
#-------------------------------------------------------------------------
# Tests to confirm that indexes on the rowid column do not confuse
# the query planner. See ticket [0eab1ac7591f511d].
#
do_execsql_test 8.0 {
CREATE TABLE n1(a INTEGER PRIMARY KEY, b VARCHAR(500));
CREATE UNIQUE INDEX n1a ON n1(a);
}
do_execsql_test 8.1 {
SELECT count(*) FROM n1 WHERE a IN (1, 2, 3)
} 0
do_execsql_test 8.2 {
SELECT count(*) FROM n1 WHERE a IN (SELECT +a FROM n1)
} 0
do_execsql_test 8.3 {
INSERT INTO n1 VALUES(1, NULL), (2, NULL), (3, NULL);
SELECT count(*) FROM n1 WHERE a IN (1, 2, 3)
} 3
do_execsql_test 8.4 {
SELECT count(*) FROM n1 WHERE a IN (SELECT +a FROM n1)
} 3
finish_test
+14 -9
View File
@@ -126,6 +126,11 @@ foreach AutoVacuumMode [list 0 1] {
execsql "PRAGMA mmap_size = 0"
execsql "PRAGMA auto_vacuum = $AutoVacuumMode"
# Extra value added to size answers
set ib2_extra 0
if {$AutoVacuumMode} {incr ib2_extra}
if {[nonzero_reserved_bytes]} {incr ib2_extra}
do_test incrblob-2.$AutoVacuumMode.1 {
set ::str [string repeat abcdefghij 2900]
execsql {
@@ -136,7 +141,7 @@ foreach AutoVacuumMode [list 0 1] {
COMMIT;
}
expr [file size test.db]/1024
} [expr 31 + $AutoVacuumMode]
} [expr 31 + $ib2_extra]
ifcapable autovacuum {
do_test incrblob-2.$AutoVacuumMode.2 {
@@ -163,7 +168,7 @@ foreach AutoVacuumMode [list 0 1] {
# sqlite uses the ptrmap pages to avoid reading the other pages.
#
nRead db
} [expr $AutoVacuumMode ? 4 : 30]
} [expr $AutoVacuumMode ? 4 : 30+$ib2_extra]
do_test incrblob-2.$AutoVacuumMode.4 {
string range [db one {SELECT v FROM blobs}] end-19 end
@@ -187,7 +192,7 @@ foreach AutoVacuumMode [list 0 1] {
# sqlite uses the ptrmap pages to avoid reading the other pages.
#
nRead db
} [expr $AutoVacuumMode ? 4 : 30]
} [expr $AutoVacuumMode ? 4 : 30 + $ib2_extra]
# Pages 1 (the write-counter) and 32 (the blob data) were written.
do_test incrblob-2.$AutoVacuumMode.6 {
@@ -210,7 +215,7 @@ foreach AutoVacuumMode [list 0 1] {
do_test incrblob-2.$AutoVacuumMode.9 {
nRead db
} [expr $AutoVacuumMode ? 4 : 30]
} [expr $AutoVacuumMode ? 4 : 30 + $ib2_extra]
}
sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
@@ -384,7 +389,7 @@ ifcapable vtab {
ifcapable attach {
do_test incrblob-5.1 {
forcedelete test2.db test2.db-journal
set ::size [expr [file size [info script]]]
set ::size [expr [file size $::cmdlinearg(INFO_SCRIPT)]]
execsql {
ATTACH 'test2.db' AS aux;
CREATE TABLE aux.files(name, text);
@@ -392,16 +397,16 @@ ifcapable attach {
}
set fd [db incrblob aux files text 1]
fconfigure $fd -translation binary
set fd2 [open [info script]]
set fd2 [open $::cmdlinearg(INFO_SCRIPT)]
fconfigure $fd2 -translation binary
puts -nonewline $fd [read $fd2]
close $fd
close $fd2
set ::text [db one {select text from aux.files}]
string length $::text
} [file size [info script]]
} [file size $::cmdlinearg(INFO_SCRIPT)]
do_test incrblob-5.2 {
set fd2 [open [info script]]
set fd2 [open $::cmdlinearg(INFO_SCRIPT)]
fconfigure $fd2 -translation binary
set ::data [read $fd2]
close $fd2
@@ -576,7 +581,7 @@ foreach {tn arg} {1 "" 2 -readonly} {
}
set fd [open [info script]]
set fd [open $::cmdlinearg(INFO_SCRIPT)]
fconfigure $fd -translation binary
set ::data [read $fd 14000]
close $fd
+2 -2
View File
@@ -24,12 +24,12 @@ ifcapable {!incrblob || !memdebug || !tclvar} {
source $testdir/malloc_common.tcl
unset -nocomplain ::fd ::data
set ::fd [open [info script]]
set ::fd [open $::cmdlinearg(INFO_SCRIPT)]
set ::data [read $::fd]
close $::fd
do_malloc_test 1 -tclprep {
set bytes [file size [info script]]
set bytes [file size $::cmdlinearg(INFO_SCRIPT)]
execsql {
CREATE TABLE blobs(k, v BLOB);
INSERT INTO blobs VALUES(1, zeroblob($::bytes));
+1 -1
View File
@@ -134,7 +134,7 @@ do_test incrvacuum2-3.2 {
integrity_check incrvacuum2-3.3
ifcapable wal {
if {[wal_is_capable]} {
# At one point, when a specific page was being extracted from the b-tree
# free-list (e.g. during an incremental-vacuum), all trunk pages that
# occurred before the specific page in the free-list trunk were being
+16 -2
View File
@@ -65,12 +65,15 @@ do_test index6-1.5 {
catchsql {
CREATE INDEX bad1 ON t1(a,b) WHERE a!=random();
}
} {1 {functions prohibited in partial index WHERE clauses}}
} {1 {non-deterministic functions prohibited in partial index WHERE clauses}}
do_test index6-1.6 {
catchsql {
CREATE INDEX bad1 ON t1(a,b) WHERE a NOT LIKE 'abc%';
}
} {1 {functions prohibited in partial index WHERE clauses}}
} {0 {}}
do_execsql_test index6-1.7 {
DROP INDEX IF EXISTS bad1;
}
do_test index6-1.10 {
execsql {
@@ -376,4 +379,15 @@ do_execsql_test index6-10.3eqp {
SELECT e FROM t10 WHERE a=1 AND b=2 ORDER BY d DESC;
} {~/USING INDEX t10x/}
# A partial index will be used for a full table scan, where possible
do_execsql_test index6-11.1 {
CREATE TABLE t11(a,b,c);
CREATE INDEX t11x ON t11(a) WHERE b<>99;
EXPLAIN QUERY PLAN SELECT a FROM t11 WHERE b<>99;
} {/USING INDEX t11x/}
do_execsql_test index6-11.2 {
EXPLAIN QUERY PLAN SELECT a FROM t11 WHERE b<>99 AND c<>98;
} {/USING INDEX t11x/}
finish_test
+15 -2
View File
@@ -99,12 +99,25 @@ do_test index7-1.5 {
catchsql {
CREATE INDEX bad1 ON t1(a,b) WHERE a!=random();
}
} {1 {functions prohibited in partial index WHERE clauses}}
} {1 {non-deterministic functions prohibited in partial index WHERE clauses}}
do_test index7-1.6 {
catchsql {
CREATE INDEX bad1 ON t1(a,b) WHERE a NOT LIKE 'abc%';
}
} {1 {functions prohibited in partial index WHERE clauses}}
} {0 {}}
do_execsql_test index7-1.7 {
INSERT INTO t1(a,b,c)
VALUES('abcde',1,101),('abdef',2,102),('xyz',3,103),('abcz',4,104);
SELECT c FROM t1 WHERE a NOT LIKE 'abc%' AND a=7 ORDER BY +b;
} {7}
do_execsql_test index7-1.7eqp {
EXPLAIN QUERY PLAN
SELECT b FROM t1 WHERE a NOT LIKE 'abc%' AND a=7 ORDER BY +b;
} {/SEARCH TABLE t1 USING COVERING INDEX bad1 /}
do_execsql_test index7-1.8 {
DELETE FROM t1 WHERE c>=101;
DROP INDEX IF EXISTS bad1;
} {}
do_test index7-1.10 {
execsql {
+60
View File
@@ -0,0 +1,60 @@
# 2016-07-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.
#
#***********************************************************************
#
# Test cases for ORDER BY and LIMIT on an index scan.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Performance regression reported at
# http://www.mail-archive.com/sqlite-users@mailinglists.sqlite.org/msg98615.html
#
# Caused by the ORDER BY LIMIT optionation for check-in
# https://sqlite.org/src/info/bf46179d44843769
#
# Fixed on approximately 2016-07-27 by changes that compute a better score
# for index scans by taking into account WHERE clause constraints that can
# be handled by the index and do not require a table lookup.
#
do_execsql_test 1.0 {
CREATE TABLE t1(a,b,c,d);
WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b,c,d)
SELECT x/10, x%10, x%19, x FROM c;
CREATE INDEX t1abc ON t1(a,b,c);
SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
} {0 4 4 4 2 3 4 23}
# Prior to the fix, the following EQP would show a table scan and a sort
# rather than an index scan.
#
do_execsql_test 1.0eqp {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
} {/SCAN TABLE t1 USING INDEX t1abc/}
# If we change the index so that it no longer covers the WHERE clause,
# then we should (correctly) revert to using a table scan.
#
do_execsql_test 1.1 {
DROP INDEX t1abc;
CREATE INDEX t1abd ON t1(a,b,d);
SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
} {0 4 4 4 2 3 4 23}
do_execsql_test 1.1eqp {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
} {~/USING INDEX/}
finish_test
+46
View File
@@ -323,5 +323,51 @@ do_execsql_test indexexpr1-1010 {
SELECT *, '|' FROM t0 ORDER BY +a;
} {0 88 2 | 2 99 4 | 5 99 7 |}
# 2016-10-10
# Make sure indexes on expressions skip over initial NULL values in the
# index as they are suppose to do.
# Ticket https://www.sqlite.org/src/tktview/4baa46491212947
#
do_execsql_test indexexpr1-1100 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(NULL),(1);
SELECT '1:', typeof(a), a FROM t1 WHERE a<10;
SELECT '2:', typeof(a), a FROM t1 WHERE a+0<10;
CREATE INDEX t1x1 ON t1(a);
CREATE INDEX t1x2 ON t1(a+0);
SELECT '3:', typeof(a), a FROM t1 WHERE a<10;
SELECT '4:', typeof(a), a FROM t1 WHERE a+0<10;
} {1: integer 1 2: integer 1 3: integer 1 4: integer 1}
do_execsql_test indexexpr1-1200 {
CREATE TABLE t10(a int, b int, c int, d int);
INSERT INTO t10(a, b, c, d) VALUES(0, 0, 2, 2);
INSERT INTO t10(a, b, c, d) VALUES(0, 0, 0, 0);
INSERT INTO t10(a, b, c, d) VALUES(0, 0, 1, 1);
INSERT INTO t10(a, b, c, d) VALUES(1, 1, 1, 1);
INSERT INTO t10(a, b, c, d) VALUES(1, 1, 0, 0);
INSERT INTO t10(a, b, c, d) VALUES(2, 2, 0, 0);
SELECT a+b, c+d FROM t10 ORDER BY a+b, c+d;
} {
0 0 0 2 0 4 2 0 2 2 4 0
}
do_execsql_test indexexpr1-1200.1 {
CREATE INDEX t10_ab ON t10(a+b);
}
do_execsql_test indexexpr1-1200.2 {
SELECT a+b, c+d FROM t10 ORDER BY a+b, c+d;
} {
0 0 0 2 0 4 2 0 2 2 4 0
}
do_execsql_test indexexpr1-1200.3 {
CREATE INDEX t10_abcd ON t10(a+b,c+d);
}
do_execsql_test indexexpr1-1200.4 {
SELECT a+b, c+d FROM t10 ORDER BY a+b, c+d;
} {
0 0 0 2 0 4 2 0 2 2 4 0
}
finish_test
+68
View File
@@ -0,0 +1,68 @@
# 2016 November 4
#
# 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 OOM error handling within the built-in
# INSTR() function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix instrfault
# Use big NEEDLE and HAYSTACK strings. Strings so large they cannot
# use lookaside buffers.
#
set ::NEEDLE [string repeat "abcdefghijklmnopqrstuvwxyz" 10]
set ::HAYSTACK "[string repeat 123 10]$NEEDLE[string repeat 456 10]"
foreach {enc} {
utf8
utf16
} {
reset_db
execsql "PRAGMA encoding = $enc"
do_execsql_test 1.$enc.1 {
CREATE TABLE t1(n, h);
INSERT INTO t1 VALUES($::NEEDLE, $::HAYSTACK);
} {}
do_faultsim_test 1.$enc.1 -faults oom-t* -prep {
execsql { SELECT instr(h, n) FROM t1 }
} -body {
execsql { SELECT instr(h, n) FROM t1 }
} -test {
faultsim_test_result {0 31}
}
do_faultsim_test 1.$enc.2 -faults oom-t* -prep {
execsql { SELECT instr($::HAYSTACK, $::NEEDLE) FROM t1 }
} -body {
execsql { SELECT instr($::HAYSTACK, $::NEEDLE) FROM t1 }
} -test {
faultsim_test_result {0 31}
}
do_faultsim_test 1.$enc.3 -faults oom-t* -prep {
set ::stmt [sqlite3_prepare_v2 db "SELECT instr(?, ?)" -1 dummy]
sqlite3_bind_text $::stmt 1 $::HAYSTACK [string length $::HAYSTACK]
sqlite3_bind_text $::stmt 2 $::NEEDLE [string length $::NEEDLE]
} -body {
set rc [sqlite3_step $::stmt]
if {$rc=="SQLITE_NOMEM"} { error "out of memory" }
sqlite3_column_int $::stmt 0
} -test {
faultsim_test_result {0 31}
sqlite3_finalize $::stmt
}
}
finish_test
+38 -1
View File
@@ -296,7 +296,7 @@ do_test intpkey-3.8 {
count {
SELECT * FROM t1 WHERE c=='world' AND a>7;
}
} {11 hello world 4}
} {11 hello world 3}
do_test intpkey-3.9 {
count {
SELECT * FROM t1 WHERE 7<a;
@@ -604,5 +604,42 @@ do_test intpkey-15.7 {
}
} {}
# 2016-04-18 ticket https://www.sqlite.org/src/tktview/7d7525cb01b68712495d3a
# Be sure to escape quoted typenames.
#
do_execsql_test intpkey-16.0 {
CREATE TABLE t16a(id "INTEGER" PRIMARY KEY AUTOINCREMENT, b [TEXT], c `INT`);
} {}
do_execsql_test intpkey-16.1 {
PRAGMA table_info=t16a;
} {0 id INTEGER 0 {} 1 1 b TEXT 0 {} 0 2 c INT 0 {} 0}
# 2016-05-06 ticket https://www.sqlite.org/src/tktview/16c9801ceba4923939085
# When the schema contains an index on the IPK and no other index
# and a WHERE clause on a delete uses an OR where both sides referencing
# the IPK, then it is possible that the OP_Delete will fail because there
# deferred seek of the OP_Seek is not resolved prior to reaching the OP_Delete.
#
do_execsql_test intpkey-17.0 {
CREATE TABLE t17(x INTEGER PRIMARY KEY, y TEXT);
INSERT INTO t17(x,y) VALUES(123,'elephant'),(248,'giraffe');
CREATE INDEX t17x ON t17(x);
DELETE FROM t17 WHERE x=99 OR x<130;
SELECT * FROM t17;
} {248 giraffe}
do_execsql_test intpkey-17.1 {
DROP INDEX t17x;
DELETE FROM t17;
INSERT INTO t17(x,y) VALUES(123,'elephant'),(248,'giraffe');
CREATE UNIQUE INDEX t17x ON t17(abs(x));
DELETE FROM t17 WHERE abs(x) IS NULL OR abs(x)<130;
SELECT * FROM t17;
} {248 giraffe}
do_execsql_test intpkey-17.2 {
DELETE FROM t17;
INSERT INTO t17(x,y) VALUES(123,'elephant'),(248,'giraffe');
UPDATE t17 SET y='ostrich' WHERE abs(x)=248;
SELECT * FROM t17 ORDER BY +x;
} {123 elephant 248 ostrich}
finish_test
+1 -1
View File
@@ -424,7 +424,7 @@ ifcapable pager_pragmas {
# The COMMIT requires a single fsync() - to the database file.
execsql { COMMIT }
list [file size test.db] [nSync]
} {39936 1}
} "[expr {[nonzero_reserved_bytes]?40960:39936}] 1"
}
#----------------------------------------------------------------------
+1 -1
View File
@@ -204,7 +204,7 @@ db close
# delete the journal file when committing the transaction that switches
# the system to WAL mode.
#
ifcapable wal {
if {[wal_is_capable]} {
do_test journal2-2.1 {
faultsim_delete_and_reopen
set ::oplog [list]
+332
View File
@@ -356,5 +356,337 @@ do_execsql_test json-8.2 {
SELECT a=json_extract(b,'$[0]') FROM t8;
} {1}
# The json_quote() function transforms an SQL value into a JSON value.
# String values are quoted and interior quotes are escaped. NULL values
# are rendered as the unquoted string "null".
#
do_execsql_test json-9.1 {
SELECT json_quote('abc"xyz');
} {{"abc\"xyz"}}
do_execsql_test json-9.2 {
SELECT json_quote(3.14159);
} {3.14159}
do_execsql_test json-9.3 {
SELECT json_quote(12345);
} {12345}
do_execsql_test json-9.4 {
SELECT json_quote(null);
} {"null"}
do_catchsql_test json-9.5 {
SELECT json_quote(x'30313233');
} {1 {JSON cannot hold BLOB values}}
do_catchsql_test json-9.6 {
SELECT json_quote(123,456)
} {1 {wrong number of arguments to function json_quote()}}
do_catchsql_test json-9.7 {
SELECT json_quote()
} {1 {wrong number of arguments to function json_quote()}}
# Make sure only valid backslash-escapes are accepted.
#
do_execsql_test json-10.1 {
SELECT json_valid('" \ "');
} {0}
do_execsql_test json-10.2 {
SELECT json_valid('" \! "');
} {0}
do_execsql_test json-10.3 {
SELECT json_valid('" \" "');
} {1}
do_execsql_test json-10.4 {
SELECT json_valid('" \# "');
} {0}
do_execsql_test json-10.5 {
SELECT json_valid('" \$ "');
} {0}
do_execsql_test json-10.6 {
SELECT json_valid('" \% "');
} {0}
do_execsql_test json-10.7 {
SELECT json_valid('" \& "');
} {0}
do_execsql_test json-10.8 {
SELECT json_valid('" \'' "');
} {0}
do_execsql_test json-10.9 {
SELECT json_valid('" \( "');
} {0}
do_execsql_test json-10.10 {
SELECT json_valid('" \) "');
} {0}
do_execsql_test json-10.11 {
SELECT json_valid('" \* "');
} {0}
do_execsql_test json-10.12 {
SELECT json_valid('" \+ "');
} {0}
do_execsql_test json-10.13 {
SELECT json_valid('" \, "');
} {0}
do_execsql_test json-10.14 {
SELECT json_valid('" \- "');
} {0}
do_execsql_test json-10.15 {
SELECT json_valid('" \. "');
} {0}
do_execsql_test json-10.16 {
SELECT json_valid('" \/ "');
} {1}
do_execsql_test json-10.17 {
SELECT json_valid('" \0 "');
} {0}
do_execsql_test json-10.18 {
SELECT json_valid('" \1 "');
} {0}
do_execsql_test json-10.19 {
SELECT json_valid('" \2 "');
} {0}
do_execsql_test json-10.20 {
SELECT json_valid('" \3 "');
} {0}
do_execsql_test json-10.21 {
SELECT json_valid('" \4 "');
} {0}
do_execsql_test json-10.22 {
SELECT json_valid('" \5 "');
} {0}
do_execsql_test json-10.23 {
SELECT json_valid('" \6 "');
} {0}
do_execsql_test json-10.24 {
SELECT json_valid('" \7 "');
} {0}
do_execsql_test json-10.25 {
SELECT json_valid('" \8 "');
} {0}
do_execsql_test json-10.26 {
SELECT json_valid('" \9 "');
} {0}
do_execsql_test json-10.27 {
SELECT json_valid('" \: "');
} {0}
do_execsql_test json-10.28 {
SELECT json_valid('" \; "');
} {0}
do_execsql_test json-10.29 {
SELECT json_valid('" \< "');
} {0}
do_execsql_test json-10.30 {
SELECT json_valid('" \= "');
} {0}
do_execsql_test json-10.31 {
SELECT json_valid('" \> "');
} {0}
do_execsql_test json-10.32 {
SELECT json_valid('" \? "');
} {0}
do_execsql_test json-10.33 {
SELECT json_valid('" \@ "');
} {0}
do_execsql_test json-10.34 {
SELECT json_valid('" \A "');
} {0}
do_execsql_test json-10.35 {
SELECT json_valid('" \B "');
} {0}
do_execsql_test json-10.36 {
SELECT json_valid('" \C "');
} {0}
do_execsql_test json-10.37 {
SELECT json_valid('" \D "');
} {0}
do_execsql_test json-10.38 {
SELECT json_valid('" \E "');
} {0}
do_execsql_test json-10.39 {
SELECT json_valid('" \F "');
} {0}
do_execsql_test json-10.40 {
SELECT json_valid('" \G "');
} {0}
do_execsql_test json-10.41 {
SELECT json_valid('" \H "');
} {0}
do_execsql_test json-10.42 {
SELECT json_valid('" \I "');
} {0}
do_execsql_test json-10.43 {
SELECT json_valid('" \J "');
} {0}
do_execsql_test json-10.44 {
SELECT json_valid('" \K "');
} {0}
do_execsql_test json-10.45 {
SELECT json_valid('" \L "');
} {0}
do_execsql_test json-10.46 {
SELECT json_valid('" \M "');
} {0}
do_execsql_test json-10.47 {
SELECT json_valid('" \N "');
} {0}
do_execsql_test json-10.48 {
SELECT json_valid('" \O "');
} {0}
do_execsql_test json-10.49 {
SELECT json_valid('" \P "');
} {0}
do_execsql_test json-10.50 {
SELECT json_valid('" \Q "');
} {0}
do_execsql_test json-10.51 {
SELECT json_valid('" \R "');
} {0}
do_execsql_test json-10.52 {
SELECT json_valid('" \S "');
} {0}
do_execsql_test json-10.53 {
SELECT json_valid('" \T "');
} {0}
do_execsql_test json-10.54 {
SELECT json_valid('" \U "');
} {0}
do_execsql_test json-10.55 {
SELECT json_valid('" \V "');
} {0}
do_execsql_test json-10.56 {
SELECT json_valid('" \W "');
} {0}
do_execsql_test json-10.57 {
SELECT json_valid('" \X "');
} {0}
do_execsql_test json-10.58 {
SELECT json_valid('" \Y "');
} {0}
do_execsql_test json-10.59 {
SELECT json_valid('" \Z "');
} {0}
do_execsql_test json-10.60 {
SELECT json_valid('" \[ "');
} {0}
do_execsql_test json-10.61 {
SELECT json_valid('" \\ "');
} {1}
do_execsql_test json-10.62 {
SELECT json_valid('" \] "');
} {0}
do_execsql_test json-10.63 {
SELECT json_valid('" \^ "');
} {0}
do_execsql_test json-10.64 {
SELECT json_valid('" \_ "');
} {0}
do_execsql_test json-10.65 {
SELECT json_valid('" \` "');
} {0}
do_execsql_test json-10.66 {
SELECT json_valid('" \a "');
} {0}
do_execsql_test json-10.67 {
SELECT json_valid('" \b "');
} {1}
do_execsql_test json-10.68 {
SELECT json_valid('" \c "');
} {0}
do_execsql_test json-10.69 {
SELECT json_valid('" \d "');
} {0}
do_execsql_test json-10.70 {
SELECT json_valid('" \e "');
} {0}
do_execsql_test json-10.71 {
SELECT json_valid('" \f "');
} {1}
do_execsql_test json-10.72 {
SELECT json_valid('" \g "');
} {0}
do_execsql_test json-10.73 {
SELECT json_valid('" \h "');
} {0}
do_execsql_test json-10.74 {
SELECT json_valid('" \i "');
} {0}
do_execsql_test json-10.75 {
SELECT json_valid('" \j "');
} {0}
do_execsql_test json-10.76 {
SELECT json_valid('" \k "');
} {0}
do_execsql_test json-10.77 {
SELECT json_valid('" \l "');
} {0}
do_execsql_test json-10.78 {
SELECT json_valid('" \m "');
} {0}
do_execsql_test json-10.79 {
SELECT json_valid('" \n "');
} {1}
do_execsql_test json-10.80 {
SELECT json_valid('" \o "');
} {0}
do_execsql_test json-10.81 {
SELECT json_valid('" \p "');
} {0}
do_execsql_test json-10.82 {
SELECT json_valid('" \q "');
} {0}
do_execsql_test json-10.83 {
SELECT json_valid('" \r "');
} {1}
do_execsql_test json-10.84 {
SELECT json_valid('" \s "');
} {0}
do_execsql_test json-10.85 {
SELECT json_valid('" \t "');
} {1}
do_execsql_test json-10.86.0 {
SELECT json_valid('" \u "');
} {0}
do_execsql_test json-10.86.1 {
SELECT json_valid('" \ua "');
} {0}
do_execsql_test json-10.86.2 {
SELECT json_valid('" \uab "');
} {0}
do_execsql_test json-10.86.3 {
SELECT json_valid('" \uabc "');
} {0}
do_execsql_test json-10.86.4 {
SELECT json_valid('" \uabcd "');
} {1}
do_execsql_test json-10.86.5 {
SELECT json_valid('" \uFEDC "');
} {1}
do_execsql_test json-10.86.6 {
SELECT json_valid('" \u1234 "');
} {1}
do_execsql_test json-10.87 {
SELECT json_valid('" \v "');
} {0}
do_execsql_test json-10.88 {
SELECT json_valid('" \w "');
} {0}
do_execsql_test json-10.89 {
SELECT json_valid('" \x "');
} {0}
do_execsql_test json-10.90 {
SELECT json_valid('" \y "');
} {0}
do_execsql_test json-10.91 {
SELECT json_valid('" \z "');
} {0}
do_execsql_test json-10.92 {
SELECT json_valid('" \{ "');
} {0}
do_execsql_test json-10.93 {
SELECT json_valid('" \| "');
} {0}
do_execsql_test json-10.94 {
SELECT json_valid('" \} "');
} {0}
do_execsql_test json-10.95 {
SELECT json_valid('" \~ "');
} {0}
finish_test
+153
View File
@@ -0,0 +1,153 @@
# 2016-05-20
#
# 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 the LIMIT in combination with ORDER BY
# and in particular, the optimizations in the inner loop that cause an
# early exit of the inner loop when the LIMIT is reached and the inner
# loop is emitting rows in ORDER BY order.
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix limit2
do_execsql_test limit2-100 {
CREATE TABLE t1(a,b);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
INSERT INTO t1(a,b) SELECT 1, (x*17)%1000 + 1000 FROM c;
INSERT INTO t1(a,b) VALUES(2,2),(3,1006),(4,4),(5,9999);
CREATE INDEX t1ab ON t1(a,b);
}
set sqlite_search_count 0
do_execsql_test limit2-100.1 {
SELECT a, b, '|' FROM t1 WHERE a IN (2,4,5,3,1) ORDER BY b LIMIT 5;
} {2 2 | 4 4 | 1 1000 | 1 1001 | 1 1002 |}
set fast_count $sqlite_search_count
set sqlite_search_count 0
do_execsql_test limit2-100.2 {
SELECT a, b, '|' FROM t1 WHERE a IN (2,4,5,3,1) ORDER BY +b LIMIT 5;
} {2 2 | 4 4 | 1 1000 | 1 1001 | 1 1002 |}
do_test limit2-100.3 {
set slow_count $sqlite_search_count
expr {$fast_count < 0.02*$slow_count}
} {1}
do_execsql_test limit2-110 {
CREATE TABLE t2(x,y);
INSERT INTO t2(x,y) VALUES('a',1),('a',2),('a',3),('a',4);
INSERT INTO t2(x,y) VALUES('b',1),('c',2),('d',3),('e',4);
CREATE INDEX t2xy ON t2(x,y);
}
set sqlite_search_count 0
do_execsql_test limit2-110.1 {
SELECT a, b, '|' FROM t2, t1 WHERE t2.x='a' AND t1.a=t2.y ORDER BY t1.b LIMIT 5;
} {2 2 | 4 4 | 1 1000 | 1 1001 | 1 1002 |}
set fast_count $sqlite_search_count
set sqlite_search_count 0
do_execsql_test limit2-110.2 {
SELECT a, b, '|' FROM t2, t1 WHERE t2.x='a' AND t1.a=t2.y ORDER BY +t1.b LIMIT 5;
} {2 2 | 4 4 | 1 1000 | 1 1001 | 1 1002 |}
set slow_count $sqlite_search_count
do_test limit2-110.3 {
expr {$fast_count < 0.02*$slow_count}
} {1}
do_execsql_test limit2-120 {
DROP INDEX t1ab;
CREATE INDEX t1ab ON t1(a,b DESC);
}
set sqlite_search_count 0
do_execsql_test limit2-120.1 {
SELECT a, b, '|' FROM t1 WHERE a IN (2,4,5,3,1) ORDER BY b DESC LIMIT 5;
} {5 9999 | 1 1999 | 1 1998 | 1 1997 | 1 1996 |}
set fast_count $sqlite_search_count
set sqlite_search_count 0
do_execsql_test limit2-120.2 {
SELECT a, b, '|' FROM t1 WHERE a IN (2,4,5,3,1) ORDER BY +b DESC LIMIT 5;
} {5 9999 | 1 1999 | 1 1998 | 1 1997 | 1 1996 |}
do_test limit2-120.3 {
set slow_count $sqlite_search_count
expr {$fast_count < 0.02*$slow_count}
} {1}
# Bug report against the new ORDER BY LIMIT optimization just prior to
# release. (Unreleased so there is no ticket).
#
# Make sure the optimization is not applied if the inner loop can only
# provide a single row of output.
#
do_execsql_test limit2-200 {
CREATE TABLE t200(a, b);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
INSERT INTO t200(a,b) SELECT x, x FROM c;
CREATE TABLE t201(x INTEGER PRIMARY KEY, y);
INSERT INTO t201(x,y) VALUES(2,12345);
SELECT *, '|' FROM t200, t201 WHERE x=b ORDER BY y LIMIT 3;
} {2 2 2 12345 |}
do_execsql_test limit2-210 {
SELECT *, '|' FROM t200 LEFT JOIN t201 ON x=b ORDER BY y LIMIT 3;
} {1 1 {} {} | 3 3 {} {} | 4 4 {} {} |}
# Bug in the ORDER BY LIMIT optimization reported on 2016-09-06.
# Ticket https://www.sqlite.org/src/info/559733b09e96
#
do_execsql_test limit2-300 {
CREATE TABLE t300(a,b,c);
CREATE INDEX t300x ON t300(a,b,c);
INSERT INTO t300 VALUES(0,1,99),(0,1,0),(0,0,0);
SELECT *,'.' FROM t300 WHERE a=0 AND (c=0 OR c=99) ORDER BY c DESC;
} {0 1 99 . 0 0 0 . 0 1 0 .}
do_execsql_test limit2-310 {
SELECT *,'.' FROM t300 WHERE a=0 AND (c=0 OR c=99) ORDER BY c DESC LIMIT 1;
} {0 1 99 .}
# Make sure the SELECT loop is ordered correctly for the direction of
# the ORDER BY
#
do_execsql_test limit2-400 {
CREATE TABLE t400(a,b);
CREATE INDEX t400_ab ON t400(a,b);
INSERT INTO t400(a,b) VALUES(1,90),(1,40),(2,80),(2,30),(3,70),(3,20);
SELECT *,'x' FROM t400 WHERE a IN (1,2,3) ORDER BY b DESC LIMIT 3;
SELECT *,'y' FROM t400 WHERE a IN (1,2,3) ORDER BY +b DESC LIMIT 3;
} {1 90 x 2 80 x 3 70 x 1 90 y 2 80 y 3 70 y}
do_execsql_test 500 {
CREATE TABLE t500(i INTEGER PRIMARY KEY, j);
INSERT INTO t500 VALUES(1, 1);
INSERT INTO t500 VALUES(2, 2);
INSERT INTO t500 VALUES(3, 3);
INSERT INTO t500 VALUES(4, 0);
INSERT INTO t500 VALUES(5, 5);
SELECT j FROM t500 WHERE i IN (1,2,3,4,5) ORDER BY j DESC LIMIT 3;
} {5 3 2}
do_execsql_test 501 {
CREATE TABLE t501(i INTEGER PRIMARY KEY, j);
INSERT INTO t501 VALUES(1, 5);
INSERT INTO t501 VALUES(2, 4);
INSERT INTO t501 VALUES(3, 3);
INSERT INTO t501 VALUES(4, 6);
INSERT INTO t501 VALUES(5, 1);
SELECT j FROM t501 WHERE i IN (1,2,3,4,5) ORDER BY j LIMIT 3;
} {1 3 4}
do_execsql_test 502 {
CREATE TABLE t502(i INT PRIMARY KEY, j);
INSERT INTO t502 VALUES(1, 5);
INSERT INTO t502 VALUES(2, 4);
INSERT INTO t502 VALUES(3, 3);
INSERT INTO t502 VALUES(4, 6);
INSERT INTO t502 VALUES(5, 1);
SELECT j FROM t502 WHERE i IN (1,2,3,4,5) ORDER BY j LIMIT 3;
} {1 3 4}
finish_test
+12 -2
View File
@@ -81,7 +81,7 @@ if {![file exists $testextension]} {
set testextsrc $srcdir/test_loadext.c
set cmdline [concat exec gcc $gcc_shared]
lappend cmdline -Wall -I$srcdir -I. -g $testextsrc -o $testextension
lappend cmdline -Wall -I$srcdir -I. -I.. -g $testextsrc -o $testextension
if {[catch $cmdline msg]} {
puts "Skipping loadext tests: Test extension not built..."
@@ -111,7 +111,7 @@ do_test loadext-1.2 {
#
do_test loadext-1.3 {
sqlite3 db2 test.db
sqlite3_enable_load_extension db2 1
sqlite3_db_config db2 SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1
catchsql {
SELECT half(1.0);
} db2
@@ -256,6 +256,7 @@ do_test loadext-4.2 {
}
} {0 {{}}}
# disable all extension loading
do_test loadext-4.3 {
sqlite3_enable_load_extension db 0
catchsql {
@@ -263,6 +264,15 @@ do_test loadext-4.3 {
}
} {1 {not authorized}}
# enable C-api extension loading only. Show that the SQL function
# still does not work.
do_test loadext-4.4 {
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1
catchsql {
SELECT load_extension($::testextension,'testloadext_init')
}
} {1 {not authorized}}
source $testdir/malloc_common.tcl
+3 -2
View File
@@ -423,8 +423,9 @@ do_test lock-6.5 {
# * there exists one or more active read-only statements, and
# * a transaction that modified zero database pages is committed.
#
set temp_status unlocked
if {$TEMP_STORE>=2} {set temp_status unknown}
#set temp_status unlocked
#if {$TEMP_STORE>=2} {set temp_status unknown}
set temp_status unknown
do_test lock-7.1 {
set STMT [sqlite3_prepare $DB "SELECT * FROM sqlite_master" -1 TAIL]
sqlite3_step $STMT
+1 -1
View File
@@ -319,7 +319,7 @@ do_test main-3.1 {
sqlite3 db testdb
set v [catch {execsql {SELECT * from T1 where x!!5}} msg]
lappend v $msg
} {1 {unrecognized token: "!!"}}
} {1 {unrecognized token: "!"}}
do_test main-3.2 {
catch {db close}
foreach f [glob -nocomplain testdb/*] {forcedelete $f}
+11
View File
@@ -61,4 +61,15 @@ do_malloc_test mallocI-4 -tclprep {
}
catch { db2 close }
do_faultsim_test mallocI-5 -faults oom* -prep {
catch { db close }
sqlite3 db test.db
sqlite3_db_config_lookaside db 0 0 0
} -body {
db eval { Select CAST(1 AS blob) }
} -test {
faultsim_test_result {0 1}
}
finish_test
+7 -5
View File
@@ -100,10 +100,12 @@ reset_highwater_marks
build_test_db memsubsys1-2 {PRAGMA page_size=1024; PRAGMA mmap_size=0}
#show_memstats
set MEMORY_MANAGEMENT $sqlite_options(memorymanage)
ifcapable !malloc_usable_size {
do_test memsubsys1-2.3 {
set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
} [expr ($TEMP_STORE>1 || $MEMORY_MANAGEMENT==0)*1024]
ifcapable pagecache_overflow_stats {
ifcapable !malloc_usable_size {
do_test memsubsys1-2.3 {
set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
} [expr ($TEMP_STORE>1 || $MEMORY_MANAGEMENT==0)*1024]
}
}
do_test memsubsys1-2.4 {
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
@@ -255,7 +257,7 @@ do_test memsubsys1-7.4 {
} 0
do_test memsubsys1-7.5 {
set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
expr {$maxreq<4100}
expr {$maxreq<(4100 + 8200*[nonzero_reserved_bytes])}
} 1
do_test memsubsys1-7.6 {
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
+14
View File
@@ -628,5 +628,19 @@ do_test_13_noopt 13.7 {
SELECT min(c), count(c) FROM t1 WHERE a='a';
} {1 5}
# 2016-07-26. https://www.sqlite.org/src/info/a0bac8b3c3d1bb75
# Incorrect result on a min() query after a CREATE INDEX.
#
do_execsql_test 14.1 {
CREATE TABLE t14(a INTEGER, b INTEGER);
INSERT INTO t14(a,b) VALUES(100,2),(200,2),(300,2),(400,1),(500,2);
SELECT min(a) FROM t14 WHERE b='2' AND a>'50';
} {100}
do_execsql_test 14.2 {
CREATE INDEX t14ba ON t14(b,a);
SELECT min(a) FROM t14 WHERE b='2' AND a>'50';
} {100}
finish_test
+1 -1
View File
@@ -699,7 +699,7 @@ do_catchsql_test misc1-23.3 {
#
do_test misc1-24.0 {
list [catch { sqlite3_prepare_v2 db ! -1 dummy } msg] $msg
} {1 {(1) unrecognized token: "!}}
} {1 {(1) unrecognized token: "!"}}
# The following query (provided by Kostya Serebryany) used to take 25
# minutes to prepare. This has been speeded up to about 250 milliseconds.
+2
View File
@@ -571,6 +571,8 @@ ifcapable subquery&&compound {
# Overflow the lemon parser stack by providing an overly complex
# expression. Make sure that the overflow is detected and reported.
#
# This test fails when building with -DYYSTACKDEPTH=0
#
do_test misc5-7.1 {
execsql {CREATE TABLE t1(x)}
set sql "INSERT INTO t1 VALUES("
+39
View File
@@ -94,5 +94,44 @@ do_execsql_test misc8-2.1 {
0 10 {} 10 {} {}
}
# 2016-02-26: An assertion fault found by the libFuzzer project
#
do_execsql_test misc8-3.0 {
SELECT *
FROM
(
(SELECT 0 AS i) AS x1,
(SELECT 1) AS x2
) AS x3,
(SELECT 6 AS j UNION ALL SELECT 7) AS x4
WHERE i<rowid
ORDER BY 1;
} {0 1 6 0 1 7}
# The SQLITE_DBCONFIG_MAINDBNAME interface
#
db close
forcedelete test.db test2.db
sqlite3 db test.db
do_execsql_test misc8-4.0 {
CREATE TABLE t1(a,b,c);
INSERT INTO t1 VALUES(1,2,3);
ATTACH 'test2.db' AS aux2;
CREATE TABLE aux2.t2(c,d,e);
INSERT INTO t2 VALUES(4,5,6);
SELECT * FROM t1, t2;
} {1 2 3 4 5 6}
do_execsql_test misc8-4.1 {
PRAGMA database_list;
} {/0 main .* 2 aux2/}
dbconfig_maindbname_icecube db
do_execsql_test misc8-4.2 {
SELECT name FROM icecube.sqlite_master;
} {t1}
do_execsql_test misc8-4.3 {
PRAGMA database_list;
} {/0 icecube .* 2 aux2/}
finish_test
+4 -2
View File
@@ -88,7 +88,7 @@ foreach {t mmap_size nRead c2init} {
sql2 { DELETE FROM t1 WHERE rowid%2; }
do_test $t.$tn.2 {
sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
} {16 ok 42}
} "16 ok [expr {42+[nonzero_reserved_bytes]}]"
# Have connection 2 grow the file. Check connection 1 can still read it.
sql2 { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1 }
@@ -104,7 +104,9 @@ foreach {t mmap_size nRead c2init} {
# Check that the number of pages read by connection 1 indicates that the
# "PRAGMA mmap_size" command worked.
do_test $t.$tn.5 { nRead db } $nRead
if {[nonzero_reserved_bytes]==0} {
do_test $t.$tn.5 { nRead db } $nRead
}
}
}
+3
View File
@@ -19,6 +19,9 @@ ifcapable !mmap||!vtab {
source $testdir/lock_common.tcl
set testprefix mmap3
# A codec shuts down memory-mapped I/O
if {[nonzero_reserved_bytes]} {finish_test; return;}
do_test mmap3-1.0 {
load_static_extension db wholenumber
db eval {
+1 -1
View File
@@ -97,7 +97,7 @@ do_test mutex1-1.9 {
# * Multi-threaded mode,
# * Single-threaded mode.
#
ifcapable threadsafe&&shared_cache {
ifcapable threadsafe1&&shared_cache {
set enable_shared_cache [sqlite3_enable_shared_cache 1]
foreach {mode mutexes} {
singlethread {}
+41 -39
View File
@@ -151,45 +151,47 @@ sqlite3_finalize $::STMT
# Then it reads the value of the database to verify it is converted into
# NULL.
#
do_test nan-3.1 {
db eval {
DELETE FROM t1;
INSERT INTO t1 VALUES(0.5);
PRAGMA auto_vacuum=OFF;
PRAGMA page_size=1024;
VACUUM;
}
hexio_read test.db 2040 8
} {3FE0000000000000}
do_test nan-3.2 {
db eval {
SELECT x, typeof(x) FROM t1
}
} {0.5 real}
do_test nan-3.3 {
db close
hexio_write test.db 2040 FFF8000000000000
sqlite3 db test.db
db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
do_test nan-3.4 {
db close
hexio_write test.db 2040 7FF8000000000000
sqlite3 db test.db
db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
do_test nan-3.5 {
db close
hexio_write test.db 2040 FFFFFFFFFFFFFFFF
sqlite3 db test.db
db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
do_test nan-3.6 {
db close
hexio_write test.db 2040 7FFFFFFFFFFFFFFF
sqlite3 db test.db
db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
if {![nonzero_reserved_bytes]} {
do_test nan-3.1 {
db eval {
DELETE FROM t1;
INSERT INTO t1 VALUES(0.5);
PRAGMA auto_vacuum=OFF;
PRAGMA page_size=1024;
VACUUM;
}
hexio_read test.db 2040 8
} {3FE0000000000000}
do_test nan-3.2 {
db eval {
SELECT x, typeof(x) FROM t1
}
} {0.5 real}
do_test nan-3.3 {
db close
hexio_write test.db 2040 FFF8000000000000
sqlite3 db test.db
db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
do_test nan-3.4 {
db close
hexio_write test.db 2040 7FF8000000000000
sqlite3 db test.db
db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
do_test nan-3.5 {
db close
hexio_write test.db 2040 FFFFFFFFFFFFFFFF
sqlite3 db test.db
db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
do_test nan-3.6 {
db close
hexio_write test.db 2040 7FFFFFFFFFFFFFFF
sqlite3 db test.db
db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
}
# Verify that the sqlite3AtoF routine is able to handle extreme
# numbers.

Some files were not shown because too many files have changed in this diff Show More