mirror of
https://github.com/status-im/sqlcipher.git
synced 2026-08-31 06:21:07 +00:00
Merge sqlite-release(3.15.2) into prerelease-integration
This commit is contained in:
+6
-6
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -25,6 +25,7 @@ ifcapable !crashtest {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
do_not_use_codec
|
||||
|
||||
do_test crash8-1.1 {
|
||||
execsql {
|
||||
|
||||
+112
@@ -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
@@ -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);
|
||||
} ]
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 }
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -19,6 +19,7 @@ source $testdir/lock_common.tcl
|
||||
|
||||
|
||||
foreach jm {rollback wal} {
|
||||
if {![wal_is_capable] && $jm=="wal"} continue
|
||||
|
||||
set testprefix exists-$jm
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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'
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -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}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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("
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user