mirror of
https://github.com/status-im/sqlcipher.git
synced 2026-08-31 06:21:07 +00:00
Merge sqlite-release(3.8.10.2) into prerelease-integration
This commit is contained in:
@@ -912,5 +912,14 @@ do_execsql_test alter-17.9 {
|
||||
do_execsql_test alter-17.10 {
|
||||
SELECT sqlite_rename_parent(NULL,'abc','xyz');
|
||||
} {{}}
|
||||
do_execsql_test alter-17.11 {
|
||||
SELECT sqlite_rename_parent('create references ''','abc','xyz');
|
||||
} {{create references '}}
|
||||
do_execsql_test alter-17.12 {
|
||||
SELECT sqlite_rename_parent('create references "abc"123" ','abc','xyz');
|
||||
} {{create references "xyz"123" }}
|
||||
do_execsql_test alter-17.13 {
|
||||
SELECT sqlite_rename_parent("references '''",'abc','xyz');
|
||||
} {{references '''}}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -359,6 +359,6 @@ do_test analyze-99.1 {
|
||||
catchsql {
|
||||
ANALYZE
|
||||
}
|
||||
} {1 {malformed database schema (sqlite_stat1) - near "nonsense": syntax error}}
|
||||
} {1 {malformed database schema (sqlite_stat1)}}
|
||||
|
||||
finish_test
|
||||
|
||||
+42
-12
@@ -16,6 +16,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix analyze3
|
||||
|
||||
ifcapable !stat4&&!stat3 {
|
||||
finish_test
|
||||
@@ -46,6 +47,9 @@ ifcapable !stat4&&!stat3 {
|
||||
#
|
||||
# analyze3-6.*: Test that the problem fixed by commit [127a5b776d] is fixed.
|
||||
#
|
||||
# analyze3-7.*: Test that some memory leaks discovered by fuzz testing
|
||||
# have been fixed.
|
||||
#
|
||||
|
||||
proc getvar {varname} { uplevel #0 set $varname }
|
||||
db function var getvar
|
||||
@@ -281,35 +285,35 @@ do_eqp_test analyze3-2.3 {
|
||||
|
||||
do_test analyze3-2.4 {
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE 'a%' }
|
||||
} {101 0 100}
|
||||
} {102 0 100}
|
||||
do_test analyze3-2.5 {
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE '%a' }
|
||||
} {999 999 100}
|
||||
|
||||
do_test analyze3-2.4 {
|
||||
do_test analyze3-2.6 {
|
||||
set like "a%"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {101 0 100}
|
||||
do_test analyze3-2.5 {
|
||||
} {102 0 100}
|
||||
do_test analyze3-2.7 {
|
||||
set like "%a"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {999 999 100}
|
||||
do_test analyze3-2.6 {
|
||||
do_test analyze3-2.8 {
|
||||
set like "a"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {101 0 0}
|
||||
do_test analyze3-2.7 {
|
||||
} {102 0 0}
|
||||
do_test analyze3-2.9 {
|
||||
set like "ab"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {11 0 0}
|
||||
do_test analyze3-2.8 {
|
||||
} {12 0 0}
|
||||
do_test analyze3-2.10 {
|
||||
set like "abc"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {2 0 1}
|
||||
do_test analyze3-2.9 {
|
||||
} {3 0 1}
|
||||
do_test analyze3-2.11 {
|
||||
set like "a_c"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {101 0 10}
|
||||
} {102 0 10}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -662,4 +666,30 @@ do_eqp_test analyze3-6-2 {
|
||||
SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# 2015-04-20.
|
||||
# Memory leak in sqlite3Stat4ProbeFree(). (Discovered while fuzzing.)
|
||||
#
|
||||
do_execsql_test analyze-7.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
INSERT INTO t1 VALUES(1,1,'0000');
|
||||
CREATE INDEX t0b ON t1(b);
|
||||
ANALYZE;
|
||||
SELECT c FROM t1 WHERE b=3 AND a BETWEEN 30 AND hex(1);
|
||||
} {}
|
||||
|
||||
# At one point duplicate stat1 entries were causing a memory leak.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.2 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
ANALYZE;
|
||||
SELECT * FROM sqlite_stat1;
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000');
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000');
|
||||
ANALYZE sqlite_master;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1134,4 +1134,116 @@ ifcapable stat4&&cte {
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that a problem in they way stat4 data is used has been
|
||||
# resolved (see below).
|
||||
#
|
||||
reset_db
|
||||
do_test 26.1.1 {
|
||||
db transaction {
|
||||
execsql {
|
||||
CREATE TABLE t1(x, y, z);
|
||||
CREATE INDEX t1xy ON t1(x, y);
|
||||
CREATE INDEX t1z ON t1(z);
|
||||
}
|
||||
for {set i 0} {$i < 10000} {incr i} {
|
||||
execsql { INSERT INTO t1(x, y) VALUES($i, $i) }
|
||||
}
|
||||
for {set i 0} {$i < 10} {incr i} {
|
||||
execsql {
|
||||
WITH cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt WHERE x<100)
|
||||
INSERT INTO t1(x, y) SELECT 10000+$i, x FROM cnt;
|
||||
INSERT INTO t1(x, y) SELECT 10000+$i, 100;
|
||||
}
|
||||
}
|
||||
execsql {
|
||||
UPDATE t1 SET z = rowid / 20;
|
||||
ANALYZE;
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 26.1.2 {
|
||||
SELECT count(*) FROM t1 WHERE x = 10000 AND y < 50;
|
||||
} {49}
|
||||
do_execsql_test 26.1.3 {
|
||||
SELECT count(*) FROM t1 WHERE z = 444;
|
||||
} {20}
|
||||
|
||||
# The analyzer knows that any (z=?) expression matches 20 rows. So it
|
||||
# will use index "t1z" if the estimate of hits for (x=10000 AND y<50)
|
||||
# is greater than 20 rows.
|
||||
#
|
||||
# And it should be. The analyzer has a stat4 sample as follows:
|
||||
#
|
||||
# sample=(x=10000, y=100) nLt=(10000 10099)
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
do_eqp_test 26.1.4 {
|
||||
SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1z (z=?)}
|
||||
}
|
||||
|
||||
|
||||
# This test - 26.2.* - tests that another manifestation of the same problem
|
||||
# is no longer present in the library. Assuming:
|
||||
#
|
||||
# CREATE INDEX t1xy ON t1(x, y)
|
||||
#
|
||||
# and that have samples for index t1xy as follows:
|
||||
#
|
||||
#
|
||||
# sample=('A', 70) nEq=(100, 2) nLt=(900, 970)
|
||||
# sample=('B', 70) nEq=(100, 2) nLt=(1000, 1070)
|
||||
#
|
||||
# the planner should estimate that (x = 'B' AND y > 25) matches 76 rows
|
||||
# (70 * 2/3 + 30). Before, due to the problem, the planner was estimating
|
||||
# that this matched 100 rows.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 26.2.1 {
|
||||
BEGIN;
|
||||
CREATE TABLE t1(x, y, z);
|
||||
CREATE INDEX i1 ON t1(x, y);
|
||||
CREATE INDEX i2 ON t1(z);
|
||||
|
||||
WITH
|
||||
cnt(y) AS (SELECT 0 UNION ALL SELECT y+1 FROM cnt WHERE y<99),
|
||||
letters(x) AS (
|
||||
SELECT 'A' UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D'
|
||||
)
|
||||
INSERT INTO t1(x, y) SELECT x, y FROM letters, cnt;
|
||||
|
||||
WITH
|
||||
letters(x) AS (
|
||||
SELECT 'A' UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D'
|
||||
)
|
||||
INSERT INTO t1(x, y) SELECT x, 70 FROM letters;
|
||||
|
||||
WITH
|
||||
cnt(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM cnt WHERE i<9999)
|
||||
INSERT INTO t1(x, y) SELECT i, i FROM cnt;
|
||||
|
||||
UPDATE t1 SET z = (rowid / 95);
|
||||
ANALYZE;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_eqp_test 26.2.2 {
|
||||
SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
# 2015-03-12
|
||||
#
|
||||
# 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 that deterministic scalar functions passed constant arguments
|
||||
# are used with stat4 data.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix analyzeF
|
||||
|
||||
ifcapable {!stat4} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc isqrt {i} { expr { int(sqrt($i)) } }
|
||||
db func isqrt isqrt
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x INTEGER, y INTEGER);
|
||||
WITH data(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM data
|
||||
)
|
||||
INSERT INTO t1 SELECT isqrt(i), isqrt(i) FROM data LIMIT 400;
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
ANALYZE;
|
||||
}
|
||||
|
||||
proc str {a} { return $a }
|
||||
db func str str
|
||||
|
||||
# Note: tests 7 to 12 might be unstable - as they assume SQLite will
|
||||
# prefer the expression to the right of the AND clause. Which of
|
||||
# course could change.
|
||||
#
|
||||
# Note 2: tests 9 and 10 depend on the tcl interface creating functions
|
||||
# without the SQLITE_DETERMINISTIC flag set.
|
||||
#
|
||||
foreach {tn where idx} {
|
||||
1 "x = 4 AND y = 19" {t1x (x=?)}
|
||||
2 "x = 19 AND y = 4" {t1y (y=?)}
|
||||
3 "x = '4' AND y = '19'" {t1x (x=?)}
|
||||
4 "x = '19' AND y = '4'" {t1y (y=?)}
|
||||
5 "x = substr('5195', 2, 2) AND y = substr('145', 2, 1)" {t1y (y=?)}
|
||||
6 "x = substr('145', 2, 1) AND y = substr('5195', 2, 2)" {t1x (x=?)}
|
||||
|
||||
7 "x = substr('5195', 2, 2+0) AND y = substr('145', 2, 1+0)" {t1y (y=?)}
|
||||
8 "x = substr('145', 2, 1+0) AND y = substr('5195', 2, 2+0)" {t1y (y=?)}
|
||||
|
||||
9 "x = str('19') AND y = str('4')" {t1y (y=?)}
|
||||
10 "x = str('4') AND y = str('19')" {t1y (y=?)}
|
||||
|
||||
11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)}
|
||||
12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)}
|
||||
} {
|
||||
set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
|
||||
do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res
|
||||
}
|
||||
|
||||
# Test that functions that do not exist - "func()" - do not cause an error.
|
||||
#
|
||||
do_catchsql_test 2.1 {
|
||||
SELECT * FROM t1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
|
||||
} {1 {no such function: func}}
|
||||
do_catchsql_test 2.2 {
|
||||
UPDATE t1 SET y=y+1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
|
||||
} {1 {no such function: func}}
|
||||
|
||||
|
||||
# Check that functions that accept zero arguments do not cause problems.
|
||||
#
|
||||
proc ret {x} { return $x }
|
||||
|
||||
db func det4 -deterministic [list ret 4]
|
||||
db func nondet4 [list ret 4]
|
||||
db func det19 -deterministic [list ret 19]
|
||||
db func nondet19 [list ret 19]
|
||||
|
||||
foreach {tn where idx} {
|
||||
1 "x = det4() AND y = det19()" {t1x (x=?)}
|
||||
2 "x = det19() AND y = det4()" {t1y (y=?)}
|
||||
|
||||
3 "x = nondet4() AND y = nondet19()" {t1y (y=?)}
|
||||
4 "x = nondet19() AND y = nondet4()" {t1y (y=?)}
|
||||
} {
|
||||
set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
|
||||
do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
|
||||
}
|
||||
|
||||
|
||||
execsql { DELETE FROM t1 }
|
||||
|
||||
proc throw_error {err} { error $err }
|
||||
db func error -deterministic throw_error
|
||||
do_catchsql_test 4.1 {
|
||||
SELECT * FROM t1 WHERE x = error('error one') AND y = 4;
|
||||
} {1 {error one}}
|
||||
|
||||
do_catchsql_test 4.2 {
|
||||
SELECT * FROM t1 WHERE x = zeroblob(2000000000) AND y = 4;
|
||||
} {1 {string or blob too big}}
|
||||
|
||||
sqlite3_limit db SQLITE_LIMIT_LENGTH 1000000
|
||||
proc dstr {} { return [string repeat x 1100000] }
|
||||
db func dstr -deterministic dstr
|
||||
do_catchsql_test 4.3 {
|
||||
SELECT * FROM t1 WHERE x = dstr() AND y = 11;
|
||||
} {1 {string or blob too big}}
|
||||
|
||||
do_catchsql_test 4.4 {
|
||||
SELECT * FROM t1 WHERE x = test_zeroblob(1100000) AND y = 4;
|
||||
} {1 {string or blob too big}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -859,4 +859,16 @@ do_test attach-10.2 {
|
||||
}] 9 end
|
||||
} {4 noname {} 5 inmem {}}
|
||||
|
||||
# Attach with a very long URI filename.
|
||||
#
|
||||
db close
|
||||
sqlite3 db test.db -uri 1
|
||||
do_execsql_test attach-11.1 {
|
||||
ATTACH printf('file:%09000x/x.db?mode=memory&cache=shared',1) AS aux1;
|
||||
CREATE TABLE aux1.t1(x,y);
|
||||
INSERT INTO aux1.t1(x,y) VALUES(1,2),(3,4);
|
||||
SELECT * FROM aux1.t1;
|
||||
} {1 2 3 4}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing automatic index creation logic.
|
||||
#
|
||||
# EVIDENCE-OF: R-34271-33106 PRAGMA automatic_index; PRAGMA
|
||||
# automatic_index = boolean; Query, set, or clear the automatic indexing
|
||||
# capability.
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -509,5 +512,12 @@ do_execsql_test autoindex1-901 {
|
||||
WHERE t1.x IN (1,2,3);
|
||||
} {/USING AUTOMATIC COVERING INDEX/}
|
||||
|
||||
# 2015-04-15: A NULL CollSeq pointer in automatic index creation.
|
||||
#
|
||||
do_execsql_test autoindex1-920 {
|
||||
CREATE TABLE t920(x);
|
||||
INSERT INTO t920 VALUES(3),(4),(5);
|
||||
SELECT * FROM t920,(SELECT 0 FROM t920),(VALUES(9)) WHERE 5 IN (x);
|
||||
} {5 0 9 5 0 9 5 0 9}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# 2015-03-25
|
||||
#
|
||||
# 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 script is making multiple calls to saveCursorPosition()
|
||||
# and restoreCursorPosition() when cursors have eState==CURSOR_SKIPNEXT
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
load_static_extension db eval
|
||||
do_execsql_test btree02-100 {
|
||||
CREATE TABLE t1(a TEXT, ax INTEGER, b INT, PRIMARY KEY(a,ax)) WITHOUT ROWID;
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
|
||||
INSERT INTO t1(a,ax,b) SELECT printf('%02x',i), random(), i FROM c;
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
CREATE TABLE t2(x,y);
|
||||
CREATE TABLE t3(cnt);
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<4)
|
||||
INSERT INTO t3(cnt) SELECT i FROM c;
|
||||
SELECT count(*) FROM t1;
|
||||
} {10}
|
||||
do_test btree02-110 {
|
||||
db eval BEGIN
|
||||
set i 0
|
||||
db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} {
|
||||
db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)}
|
||||
# puts "a,b,cnt = ($a,$b,$cnt)"
|
||||
incr i
|
||||
if {$i%2==1} {
|
||||
set bx [expr {$b+1000}]
|
||||
# puts "INSERT ($a),$bx"
|
||||
db eval {INSERT INTO t1(a,ax,b) VALUES(printf('(%s)',$a),random(),$bx)}
|
||||
} else {
|
||||
# puts "DELETE a=$a"
|
||||
db eval {DELETE FROM t1 WHERE a=$a}
|
||||
}
|
||||
db eval {COMMIT; BEGIN}
|
||||
}
|
||||
db one {COMMIT; SELECT count(*) FROM t1;}
|
||||
} {20}
|
||||
|
||||
finish_test
|
||||
+13
-1
@@ -452,9 +452,21 @@ proc check_data {STMT test types ints doubles strings} {
|
||||
# types
|
||||
do_test $test.1 {
|
||||
set types [list]
|
||||
foreach i $idxlist {lappend types [sqlite3_column_type $STMT $i]}
|
||||
foreach i $idxlist {
|
||||
set x [sqlite3_column_type $STMT $i]
|
||||
# EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five
|
||||
# fundamental datatypes: 64-bit signed integer 64-bit IEEE floating
|
||||
# point number string BLOB NULL
|
||||
if {[lsearch {INTEGER FLOAT TEXT BLOB NULL} $x]<0} {
|
||||
set types ERROR
|
||||
break
|
||||
} else {
|
||||
lappend types $x
|
||||
}
|
||||
}
|
||||
set types
|
||||
} $types
|
||||
|
||||
|
||||
# Integers
|
||||
do_test $test.2 {
|
||||
|
||||
+70
-2
@@ -10,12 +10,12 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is page cache subsystem.
|
||||
# focus of this script is testing collation sequences.
|
||||
#
|
||||
# $Id: collate1.test,v 1.5 2007/02/01 23:02:46 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix collate1
|
||||
|
||||
#
|
||||
# Tests are roughly organised as follows:
|
||||
@@ -333,4 +333,72 @@ do_test collate1-5.3 {
|
||||
}
|
||||
} {1 2}
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Fix problems with handling collation sequences named '"""'.
|
||||
#
|
||||
do_execsql_test 6.1 {
|
||||
SELECT """""""";
|
||||
} {\"\"\"}
|
||||
|
||||
do_catchsql_test 6.2 {
|
||||
CREATE TABLE x1(a);
|
||||
SELECT a FROM x1 ORDER BY a COLLATE """""""";
|
||||
} {1 {no such collation sequence: """}}
|
||||
|
||||
do_catchsql_test 6.3 {
|
||||
SELECT a FROM x1 ORDER BY 1 COLLATE """""""";
|
||||
} {1 {no such collation sequence: """}}
|
||||
|
||||
do_catchsql_test 6.4 {
|
||||
SELECT 0 UNION SELECT 0 ORDER BY 1 COLLATE """""""";
|
||||
} {1 {no such collation sequence: """}}
|
||||
|
||||
db collate {"""} [list string compare -nocase]
|
||||
|
||||
do_execsql_test 6.5 {
|
||||
PRAGMA foreign_keys = ON;
|
||||
CREATE TABLE p1(a PRIMARY KEY COLLATE '"""');
|
||||
CREATE TABLE c1(x, y REFERENCES p1);
|
||||
} {}
|
||||
|
||||
do_execsql_test 6.6 {
|
||||
INSERT INTO p1 VALUES('abc');
|
||||
INSERT INTO c1 VALUES(1, 'ABC');
|
||||
}
|
||||
|
||||
ifcapable foreignkey {
|
||||
do_catchsql_test 6.7 {
|
||||
DELETE FROM p1 WHERE rowid = 1
|
||||
} {1 {FOREIGN KEY constraint failed}}
|
||||
}
|
||||
|
||||
do_execsql_test 6.8 {
|
||||
INSERT INTO p1 VALUES('abb');
|
||||
INSERT INTO p1 VALUES('wxz');
|
||||
INSERT INTO p1 VALUES('wxy');
|
||||
|
||||
INSERT INTO c1 VALUES(2, 'abb');
|
||||
INSERT INTO c1 VALUES(3, 'wxz');
|
||||
INSERT INTO c1 VALUES(4, 'WXY');
|
||||
SELECT x, y FROM c1 ORDER BY y COLLATE """""""";
|
||||
} {2 abb 1 ABC 4 WXY 3 wxz}
|
||||
|
||||
# 2015-04-15: Nested COLLATE operators
|
||||
#
|
||||
do_execsql_test 7.0 {
|
||||
SELECT 'abc' UNION ALL SELECT 'DEF'
|
||||
ORDER BY 1 COLLATE nocase COLLATE nocase COLLATE nocase COLLATE nocase;
|
||||
} {abc DEF}
|
||||
do_execsql_test 7.1 {
|
||||
SELECT 'abc' UNION ALL SELECT 'DEF'
|
||||
ORDER BY 1 COLLATE nocase COLLATE nocase COLLATE nocase COLLATE binary;
|
||||
} {DEF abc}
|
||||
do_execsql_test 7.2 {
|
||||
SELECT 'abc' UNION ALL SELECT 'DEF'
|
||||
ORDER BY 1 COLLATE binary COLLATE binary COLLATE binary COLLATE nocase;
|
||||
} {abc DEF}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+6
-1
@@ -32,7 +32,7 @@ source $testdir/tester.tcl
|
||||
#
|
||||
do_test collate3-1.0 {
|
||||
execsql {
|
||||
CREATE TABLE collate3t1(c1);
|
||||
CREATE TABLE collate3t1(c1 UNIQUE);
|
||||
}
|
||||
} {}
|
||||
do_test collate3-1.1 {
|
||||
@@ -40,6 +40,11 @@ do_test collate3-1.1 {
|
||||
SELECT * FROM collate3t1 ORDER BY 1 collate garbage;
|
||||
}
|
||||
} {1 {no such collation sequence: garbage}}
|
||||
do_test collate3-1.1.2 {
|
||||
catchsql {
|
||||
SELECT DISTINCT c1 COLLATE garbage FROM collate3t1;
|
||||
}
|
||||
} {1 {no such collation sequence: garbage}}
|
||||
do_test collate3-1.2 {
|
||||
catchsql {
|
||||
CREATE TABLE collate3t2(c1 collate garbage);
|
||||
|
||||
+33
-1
@@ -13,7 +13,9 @@
|
||||
# focus of this script is making sure collations pass through the
|
||||
# unary + operator.
|
||||
#
|
||||
# $Id: collate8.test,v 1.2 2008/08/25 12:14:09 drh Exp $
|
||||
# 2015-02-09: Added tests to make sure COLLATE passes through function
|
||||
# calls. Ticket [ca0d20b6cdddec5e81b8d66f89c46a5583b5f6f6].
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -122,4 +124,34 @@ do_test collate8-2.8 {
|
||||
}
|
||||
} {abc}
|
||||
|
||||
# Make sure the COLLATE operator perculates up through function calls
|
||||
# and other Expr structures that use the Expr.x.pList field.
|
||||
#
|
||||
do_execsql_test collate8-3.1 {
|
||||
SELECT 'abc'==('ABC'||'') COLLATE nocase;
|
||||
SELECT 'abc'==('ABC'||'' COLLATE nocase);
|
||||
SELECT 'abc'==('ABC'||('' COLLATE nocase));
|
||||
SELECT 'abc'==('ABC'||upper('' COLLATE nocase));
|
||||
} {1 1 1 1}
|
||||
do_execsql_test collate8-3.2 {
|
||||
SELECT 'abc'==('ABC'||max('' COLLATE nocase,'' COLLATE binary));
|
||||
} {1}
|
||||
|
||||
# The COLLATE binary is on the left and so takes precedence
|
||||
do_execsql_test collate8-3.3 {
|
||||
SELECT 'abc'==('ABC'||max('' COLLATE binary,'' COLLATE nocase));
|
||||
} {0}
|
||||
|
||||
do_execsql_test collate8-3.4 {
|
||||
SELECT 'abc'==('ABC'||CASE WHEN 1-1=2 THEN '' COLLATE nocase
|
||||
ELSE '' COLLATE binary END);
|
||||
SELECT 'abc'==('ABC'||CASE WHEN 1+1=2 THEN '' COLLATE nocase
|
||||
ELSE '' COLLATE binary END);
|
||||
} {1 1}
|
||||
do_execsql_test collate8-3.5 {
|
||||
SELECT 'abc'==('ABC'||CASE WHEN 1=2 THEN '' COLLATE binary
|
||||
ELSE '' COLLATE nocase END);
|
||||
} {0}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -292,7 +292,7 @@ do_test corruptC-2.15 {
|
||||
hexio_write test.db 986 b9
|
||||
sqlite3 db test.db
|
||||
catchsql {SELECT count(*) FROM sqlite_master;}
|
||||
} {1 {malformed database schema (t1i1) - no such table: main.t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#
|
||||
# Now test for a series of quasi-random seeds.
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# 2015-03-30
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Corruption consisting of a database page that thinks it is a child
|
||||
# of itself.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix corruptJ
|
||||
|
||||
if {[permutation]=="mmap"} {
|
||||
finish_test
|
||||
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
|
||||
database_may_be_corrupt
|
||||
|
||||
# Initialize the database.
|
||||
#
|
||||
do_execsql_test 1.1 {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA auto_vacuum=0;
|
||||
CREATE TABLE t1(a,b);
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
|
||||
INSERT INTO t1(a,b) SELECT i, zeroblob(700) FROM c;
|
||||
} {}
|
||||
db close
|
||||
|
||||
# Corrupt the root page of the t1 table such that the left-child pointer
|
||||
# for the very first cell points back to the root. Then try to DROP the
|
||||
# table. The clearDatabasePage() routine should not loop.
|
||||
#
|
||||
do_test 1.2 {
|
||||
hexio_write test.db [expr {2*1024-2}] 02
|
||||
sqlite3 db test.db
|
||||
catchsql { DROP TABLE t1 }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
# Similar test using a WITHOUT ROWID table
|
||||
#
|
||||
do_test 2.1 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA auto_vacuum=0;
|
||||
CREATE TABLE t1(a,b,PRIMARY KEY(a,b)) WITHOUT ROWID;
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<100)
|
||||
INSERT INTO t1(a,b) SELECT i, zeroblob(200) FROM c;
|
||||
}
|
||||
} {}
|
||||
|
||||
# The table is three levels deep. Corrupt the left child of an intermediate
|
||||
# page so that it points back to the root page.
|
||||
#
|
||||
do_test 2.2 {
|
||||
db close
|
||||
hexio_read test.db [expr {9*1024+391}] 8
|
||||
} {00000008814D0401}
|
||||
do_test 2.2b {
|
||||
hexio_write test.db [expr {9*1024+391}] 00000002
|
||||
sqlite3 db test.db
|
||||
catchsql { PRAGMA secure_delete=ON; DROP TABLE t1; }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
@@ -191,4 +191,9 @@ do_execsql_test count-5.1 {
|
||||
SELECT count(*) FROM t5;
|
||||
} {1}
|
||||
|
||||
do_catchsql_test count-6.1 {
|
||||
CREATE TABLE t6(x);
|
||||
SELECT count(DISTINCT) FROM t6 GROUP BY x;
|
||||
} {1 {DISTINCT aggregates must have exactly one argument}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# 2015 Mar 13
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Crash tests for the multiplex module with 8.3 filenames enabled.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix crashM
|
||||
|
||||
ifcapable !crashtest||!8_3_names {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
|
||||
foreach f [glob -nocomplain test1.* test2.*] { forcedelete $f }
|
||||
sqlite3_multiplex_initialize "" 1
|
||||
sqlite3 db file:test1.db?8_3_names=1
|
||||
sqlite3_multiplex_control db main chunk_size [expr 64*1024]
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
ATTACH 'file:test2.db?8_3_names=1' AS aux;
|
||||
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
|
||||
CREATE TABLE aux.t2(x, y);
|
||||
CREATE INDEX aux.t2x ON t2(x);
|
||||
CREATE INDEX aux.t2y ON t2(y);
|
||||
|
||||
WITH s(a) AS (
|
||||
SELECT 1 UNION ALL SELECT a+1 FROM s WHERE a<1000
|
||||
)
|
||||
INSERT INTO t1 SELECT a, randomblob(500) FROM s;
|
||||
|
||||
WITH s(a) AS (
|
||||
SELECT 1 UNION ALL SELECT a+1 FROM s WHERE a<1000
|
||||
)
|
||||
INSERT INTO t2 SELECT a, randomblob(500) FROM s;
|
||||
} {}
|
||||
|
||||
for {set i 0} {$i < 20} {incr i} {
|
||||
do_test 2.$i.1 {
|
||||
crashsql -delay 1 -file test1.db -opendb {
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
sqlite3_multiplex_initialize crash 1
|
||||
sqlite3 db file:test1.db?8_3_names=1
|
||||
sqlite3_multiplex_control db main chunk_size [expr 64*1024]
|
||||
} {
|
||||
ATTACH 'file:test2.db?8_3_names=1' AS aux;
|
||||
BEGIN;
|
||||
UPDATE t1 SET y = randomblob(500) WHERE (x%10)==0;
|
||||
UPDATE t2 SET y = randomblob(500) WHERE (x%10)==0;
|
||||
COMMIT;
|
||||
}
|
||||
} {1 {child process exited abnormally}}
|
||||
|
||||
do_execsql_test 2.$i.2 {
|
||||
PRAGMA main.integrity_check;
|
||||
PRAGMA aux.integrity_check;
|
||||
} {ok ok}
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
sqlite3_multiplex_shutdown
|
||||
finish_test
|
||||
+3
-3
@@ -348,9 +348,9 @@ do_insert_tests e_insert-3.2 {
|
||||
6.2 "SELECT * FROM a1" {{} {} {} {}}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-46928-50290 The optional conflict-clause allows the
|
||||
# specification of an alternative constraint conflict resolution
|
||||
# algorithm to use during this one INSERT command.
|
||||
# EVIDENCE-OF: R-03235-45250 The "REPLACE" and "INSERT OR action" forms
|
||||
# specify an alternative constraint conflict resolution algorithm to use
|
||||
# during this one INSERT command.
|
||||
#
|
||||
# EVIDENCE-OF: R-23110-47146 the parser allows the use of the single
|
||||
# keyword REPLACE as an alias for "INSERT OR REPLACE".
|
||||
|
||||
+6
-2
@@ -48,8 +48,11 @@ do_execsql_test e_reindex-1.1 {
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
|
||||
CREATE TABLE saved(a,b,c,d,e);
|
||||
INSERT INTO saved SELECT * FROM sqlite_master WHERE type = 'index';
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET sql = '-- ' || sql WHERE type = 'index';
|
||||
DELETE FROM sqlite_master WHERE type = 'index';
|
||||
} {}
|
||||
|
||||
db close
|
||||
@@ -59,7 +62,8 @@ do_execsql_test e_reindex-1.2 {
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
INSERT INTO t1 VALUES(9, 10);
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET sql = substr(sql, 4) WHERE type = 'index';
|
||||
INSERT INTO sqlite_master SELECT * FROM saved;
|
||||
DROP TABLE saved;
|
||||
} {}
|
||||
|
||||
db close
|
||||
|
||||
+5
-4
@@ -200,10 +200,11 @@ do_test 3.4.2 {
|
||||
db close
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-22428-28959 To prevent older versions of SQLite from
|
||||
# trying to recover a WAL-mode database (and making matters worse) the
|
||||
# database file format version numbers (bytes 18 and 19 in the database
|
||||
# header) are increased from 1 to 2 in WAL mode.
|
||||
# EVIDENCE-OF: R-45540-25505 To prevent older versions of SQLite (prior
|
||||
# to version 3.7.0, 2010-07-22) from trying to recover a WAL-mode
|
||||
# database (and making matters worse) the database file format version
|
||||
# numbers (bytes 18 and 19 in the database header) are increased from 1
|
||||
# to 2 in WAL mode.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.1.1 { CREATE TABLE t1(x, y) }
|
||||
|
||||
@@ -15,6 +15,14 @@ source $testdir/tester.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
set testprefix e_walauto
|
||||
|
||||
# Do not run this test on OpenBSD, as it depends on read() and mmap both
|
||||
# accessing the same coherent view of the "test.db-shm" file. This doesn't
|
||||
# work on OpenBSD.
|
||||
#
|
||||
if {$tcl_platform(os) == "OpenBSD"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc read_nbackfill {} {
|
||||
seek $::shmfd 96
|
||||
|
||||
@@ -943,5 +943,13 @@ do_realnum_test expr-13.7 {
|
||||
}
|
||||
} {9.22337203685478e+18}
|
||||
|
||||
do_execsql_test expr-13.8 {
|
||||
SELECT "" <= '';
|
||||
} {1}
|
||||
do_execsql_test expr-13.9 {
|
||||
SELECT '' <= "";
|
||||
} {1}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -121,4 +121,34 @@ do_test fkey1-3.5 {
|
||||
sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
|
||||
} {0 0 0}
|
||||
|
||||
# Stress the dequoting logic. The first test is not so bad.
|
||||
do_execsql_test fkey1-4.0 {
|
||||
PRAGMA foreign_keys=ON;
|
||||
CREATE TABLE "xx1"("xx2" TEXT PRIMARY KEY, "xx3" TEXT);
|
||||
INSERT INTO "xx1"("xx2","xx3") VALUES('abc','def');
|
||||
CREATE TABLE "xx4"("xx5" TEXT REFERENCES "xx1" ON DELETE CASCADE);
|
||||
INSERT INTO "xx4"("xx5") VALUES('abc');
|
||||
INSERT INTO "xx1"("xx2","xx3") VALUES('uvw','xyz');
|
||||
SELECT 1, "xx5" FROM "xx4";
|
||||
DELETE FROM "xx1";
|
||||
SELECT 2, "xx5" FROM "xx4";
|
||||
} {1 abc}
|
||||
|
||||
# This case is identical to the previous except the "xx" in each name
|
||||
# is changed to a single escaped double-quote character.
|
||||
do_execsql_test fkey1-4.1 {
|
||||
PRAGMA foreign_keys=ON;
|
||||
CREATE TABLE """1"("""2" TEXT PRIMARY KEY, """3" TEXT);
|
||||
INSERT INTO """1"("""2","""3") VALUES('abc','def');
|
||||
CREATE TABLE """4"("""5" TEXT REFERENCES """1" ON DELETE CASCADE);
|
||||
INSERT INTO """4"("""5") VALUES('abc');
|
||||
INSERT INTO """1"("""2","""3") VALUES('uvw','xyz');
|
||||
SELECT 1, """5" FROM """4";
|
||||
DELETE FROM """1";
|
||||
SELECT 2, """5" FROM """4";
|
||||
} {1 abc}
|
||||
do_execsql_test fkey1-4.2 {
|
||||
PRAGMA table_info="""1";
|
||||
} {0 {"2} TEXT 0 {} 1 1 {"3} TEXT 0 {} 0}
|
||||
|
||||
finish_test
|
||||
|
||||
+21
-2
@@ -676,6 +676,11 @@ do_test fkey2-9.2.3 {
|
||||
SELECT * FROM cc;
|
||||
}
|
||||
} {{} A {} {} B {} 3 A 2 3 B 2}
|
||||
do_execsql_test fkey2-9.3.0 {
|
||||
CREATE TABLE t3(x PRIMARY KEY REFERENCES t3 ON DELETE SET NULL);
|
||||
INSERT INTO t3(x) VALUES(12345);
|
||||
DROP TABLE t3;
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests, fkey2-10.*, test "foreign key mismatch" and
|
||||
@@ -746,10 +751,10 @@ do_test fkey2-10.2.2 {
|
||||
drop_all_tables
|
||||
do_test fkey2-11.1.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, rowid, _rowid_, oid);
|
||||
CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(a) ON UPDATE CASCADE);
|
||||
|
||||
INSERT INTO t1 VALUES(10, 100);
|
||||
INSERT INTO t1 VALUES(10, 100, 'abc', 'def', 'ghi');
|
||||
INSERT INTO t2 VALUES(10, 100);
|
||||
UPDATE t1 SET a = 15;
|
||||
SELECT * FROM t2;
|
||||
@@ -2014,4 +2019,18 @@ do_test fkey2-ce7c13.1.6 {
|
||||
}
|
||||
} {1 {FOREIGN KEY constraint failed}}
|
||||
|
||||
# 2015-04-16: Foreign key errors propagate back up to the parser.
|
||||
#
|
||||
do_test fkey2-20150416-100 {
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
catchsql {
|
||||
PRAGMA foreign_keys=1;
|
||||
CREATE TABLE t1(x PRIMARY KEY);
|
||||
CREATE TABLE t(y REFERENCES t0(x)ON DELETE SET DEFAULT);
|
||||
CREATE TABLE t0(y REFERENCES t1 ON DELETE SET NULL);
|
||||
REPLACE INTO t1 SELECT(0);CREATE TABLE t2(x);CREATE TABLE t3;
|
||||
}
|
||||
} {1 {foreign key mismatch - "t" referencing "t0"}}
|
||||
|
||||
finish_test
|
||||
|
||||
+27
-2
@@ -12,8 +12,13 @@
|
||||
#
|
||||
# This file tests the PRAGMA foreign_key_check command.
|
||||
#
|
||||
# EVIDENCE-OF: R-05426-18119 PRAGMA foreign_key_check; PRAGMA
|
||||
# foreign_key_check(table-name);
|
||||
# EVIDENCE-OF: R-01427-50262 PRAGMA database.foreign_key_check; PRAGMA
|
||||
# database.foreign_key_check(table-name);
|
||||
#
|
||||
# EVIDENCE-OF: R-23918-17301 The foreign_key_check pragma checks the
|
||||
# database, or the table called "table-name", for foreign key
|
||||
# constraints that are violated and returns one row of output for each
|
||||
# violation.
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -74,6 +79,16 @@ do_test fkey5-1.2 {
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c1 87 p1 0 c1 90 p1 0}
|
||||
do_test fkey5-1.2b {
|
||||
db eval {
|
||||
PRAGMA main.foreign_key_check;
|
||||
}
|
||||
} {c1 87 p1 0 c1 90 p1 0}
|
||||
do_test fkey5-1.2c {
|
||||
db eval {
|
||||
PRAGMA temp.foreign_key_check;
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-1.3 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c1);
|
||||
@@ -84,6 +99,16 @@ do_test fkey5-1.4 {
|
||||
PRAGMA foreign_key_check(c2);
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-1.5 {
|
||||
db eval {
|
||||
PRAGMA main.foreign_key_check(c2);
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-1.6 {
|
||||
catchsql {
|
||||
PRAGMA temp.foreign_key_check(c2);
|
||||
}
|
||||
} {1 {no such table: temp.c2}}
|
||||
|
||||
# EVIDENCE-OF: R-45728-08709 There are four columns in each result row.
|
||||
#
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts3aa
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts3 {
|
||||
@@ -221,5 +222,26 @@ do_catchsql_test fts3aa-7.5 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts4(tokenize=simple, tokenize=simple);
|
||||
} {1 {unrecognized parameter: tokenize=simple}}
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts4(order=desc);
|
||||
BEGIN;
|
||||
INSERT INTO t0(rowid, content) VALUES(1, 'abc');
|
||||
UPDATE t0 SET docid=5 WHERE docid=1;
|
||||
INSERT INTO t0(rowid, content) VALUES(6, 'abc');
|
||||
}
|
||||
do_execsql_test 8.1 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH 'abc';
|
||||
} {6 5}
|
||||
do_execsql_test 8.2 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH '"abc abc"';
|
||||
} {}
|
||||
do_execsql_test 8.3 { COMMIT }
|
||||
do_execsql_test 8.4 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH 'abc';
|
||||
} {6 5}
|
||||
do_execsql_test 8.5 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH '"abc abc"';
|
||||
} {}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+23
-1
@@ -186,10 +186,32 @@ ifcapable icu {
|
||||
} {}
|
||||
}
|
||||
|
||||
|
||||
do_test fts3token-internal {
|
||||
execsql { SELECT fts3_tokenizer_internal_test() }
|
||||
} {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test empty tokenizer names.
|
||||
#
|
||||
do_catchsql_test 6.1.1 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts4(tokenize="");
|
||||
} {1 {unknown tokenizer: }}
|
||||
do_catchsql_test 6.1.2 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts4(tokenize=);
|
||||
} {1 {unknown tokenizer: }}
|
||||
do_catchsql_test 6.1.3 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts4(tokenize=" ");
|
||||
} {1 {unknown tokenizer: }}
|
||||
|
||||
do_catchsql_test 6.2.1 {
|
||||
SELECT fts3_tokenizer(NULL);
|
||||
} {1 {unknown 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}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# 2006 September 9
|
||||
#
|
||||
# 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 script is testing the FTS3 module.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts3expr5
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Various forms of empty phrase expressions.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts3(x);
|
||||
SELECT rowid FROM t0 WHERE x MATCH '';
|
||||
} {}
|
||||
do_execsql_test 1.1 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '""';
|
||||
} {}
|
||||
do_execsql_test 1.2 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '"" ""';
|
||||
} {}
|
||||
do_execsql_test 1.3 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '"" OR ""';
|
||||
} {}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '"" NOT ""';
|
||||
} {}
|
||||
do_execsql_test 1.5 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '""""';
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
@@ -155,4 +155,23 @@ ifcapable fts3_unicode {
|
||||
}
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_test 6.0 {
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE t6 USING fts4(x,order=DESC);
|
||||
INSERT INTO t6(docid, x) VALUES(-1,'a b');
|
||||
INSERT INTO t6(docid, x) VALUES(1, 'b');
|
||||
}
|
||||
faultsim_save_and_close
|
||||
} {}
|
||||
|
||||
do_faultsim_test 6.1 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db eval {SELECT * FROM sqlite_master}
|
||||
} -body {
|
||||
execsql { SELECT docid FROM t6 WHERE t6 MATCH '"a* b"' }
|
||||
} -test {
|
||||
faultsim_test_result {0 -1}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -449,5 +449,68 @@ do_execsql_test 10.1 {
|
||||
ORDER BY 1;
|
||||
} {1 1 one 2 2 two 3 3 three}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Test the 'y' matchinfo flag
|
||||
#
|
||||
set sqlite_fts3_enable_parentheses 1
|
||||
reset_db
|
||||
do_execsql_test 11.0 {
|
||||
CREATE VIRTUAL TABLE tt USING fts3(x, y);
|
||||
INSERT INTO tt VALUES('c d a c d d', 'e a g b d a'); -- 1
|
||||
INSERT INTO tt VALUES('c c g a e b', 'c g d g e c'); -- 2
|
||||
INSERT INTO tt VALUES('b e f d e g', 'b a c b c g'); -- 3
|
||||
INSERT INTO tt VALUES('a c f f g d', 'd b f d e g'); -- 4
|
||||
INSERT INTO tt VALUES('g a c f c f', 'd g g b c c'); -- 5
|
||||
INSERT INTO tt VALUES('g a c e b b', 'd b f b g g'); -- 6
|
||||
INSERT INTO tt VALUES('f d a a f c', 'e e a d c f'); -- 7
|
||||
INSERT INTO tt VALUES('a c b b g f', 'a b a e d f'); -- 8
|
||||
INSERT INTO tt VALUES('b a f e c c', 'f d b b a b'); -- 9
|
||||
INSERT INTO tt VALUES('f d c e a c', 'f a f a a f'); -- 10
|
||||
}
|
||||
|
||||
db func mit mit
|
||||
foreach {tn expr res} {
|
||||
1 "a" {
|
||||
1 {1 2} 2 {1 0} 3 {0 1} 4 {1 0} 5 {1 0}
|
||||
6 {1 0} 7 {2 1} 8 {1 2} 9 {1 1} 10 {1 3}
|
||||
}
|
||||
|
||||
2 "b" {
|
||||
1 {0 1} 2 {1 0} 3 {1 2} 4 {0 1} 5 {0 1}
|
||||
6 {2 2} 8 {2 1} 9 {1 3}
|
||||
}
|
||||
|
||||
3 "y:a" {
|
||||
1 {0 2} 3 {0 1}
|
||||
7 {0 1} 8 {0 2} 9 {0 1} 10 {0 3}
|
||||
}
|
||||
|
||||
4 "x:a" {
|
||||
1 {1 0} 2 {1 0} 4 {1 0} 5 {1 0}
|
||||
6 {1 0} 7 {2 0} 8 {1 0} 9 {1 0} 10 {1 0}
|
||||
}
|
||||
|
||||
5 "a OR b" {
|
||||
1 {1 2 0 1} 2 {1 0 1 0} 3 {0 1 1 2} 4 {1 0 0 1} 5 {1 0 0 1}
|
||||
6 {1 0 2 2} 7 {2 1 0 0} 8 {1 2 2 1} 9 {1 1 1 3} 10 {1 3 0 0}
|
||||
}
|
||||
|
||||
6 "a AND b" {
|
||||
1 {1 2 0 1} 2 {1 0 1 0} 3 {0 1 1 2} 4 {1 0 0 1} 5 {1 0 0 1}
|
||||
6 {1 0 2 2} 8 {1 2 2 1} 9 {1 1 1 3}
|
||||
}
|
||||
|
||||
7 "a OR (a AND b)" {
|
||||
1 {1 2 1 2 0 1} 2 {1 0 1 0 1 0} 3 {0 1 0 1 1 2} 4 {1 0 1 0 0 1}
|
||||
5 {1 0 1 0 0 1} 6 {1 0 1 0 2 2} 7 {2 1 0 0 0 0} 8 {1 2 1 2 2 1}
|
||||
9 {1 1 1 1 1 3} 10 {1 3 0 0 0 0}
|
||||
}
|
||||
|
||||
} {
|
||||
do_execsql_test 11.1.$tn {
|
||||
SELECT rowid, mit(matchinfo(tt, 'y')) FROM tt WHERE tt MATCH $expr
|
||||
} $res
|
||||
}
|
||||
set sqlite_fts3_enable_parentheses 0
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -209,5 +209,87 @@ do_catchsql_test 5.1 {
|
||||
do_catchsql_test 5.2 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts4(prefix="");
|
||||
} {0 {}}
|
||||
do_catchsql_test 5.3 {
|
||||
CREATE VIRTUAL TABLE t5 USING fts4(prefix="-1");
|
||||
} {1 {error parsing prefix parameter: -1}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Prefix indexes of size 0 are ignored. Demonstrate this by showing that
|
||||
# adding prefix=0 does not change the contents of the %_segdir table.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 6.1.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(prefix=0);
|
||||
CREATE VIRTUAL TABLE t2 USING fts4;
|
||||
INSERT INTO t1 VALUES('Twas Mulga Bill, from Eaglehawk, ');
|
||||
INSERT INTO t2 VALUES('Twas Mulga Bill, from Eaglehawk, ');
|
||||
} {}
|
||||
do_execsql_test 6.1.2 {
|
||||
SELECT md5sum(quote(root)) FROM t1_segdir;
|
||||
} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
|
||||
|
||||
reset_db
|
||||
do_execsql_test 6.2.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(prefix="1,0,2");
|
||||
CREATE VIRTUAL TABLE t2 USING fts4(prefix="1,2");
|
||||
INSERT INTO t1 VALUES('that caught the cycling craze;');
|
||||
INSERT INTO t2 VALUES('that caught the cycling craze;');
|
||||
} {}
|
||||
do_execsql_test 6.2.2 {
|
||||
SELECT md5sum(quote(root)) FROM t1_segdir;
|
||||
} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
|
||||
|
||||
reset_db
|
||||
do_execsql_test 6.3.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(prefix="1,3,2");
|
||||
CREATE VIRTUAL TABLE t2 USING fts4(prefix="1,2");
|
||||
INSERT INTO t1 VALUES('He turned away the good old horse');
|
||||
INSERT INTO t2 VALUES('He turned away the good old horse');
|
||||
} {}
|
||||
do_test 6.3.2 {
|
||||
set one [db eval {SELECT md5sum(quote(root)) FROM t1_segdir}]
|
||||
set two [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
|
||||
expr {$one == $two}
|
||||
} 0
|
||||
|
||||
reset_db
|
||||
do_execsql_test 6.4.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(prefix="1,600,2");
|
||||
CREATE VIRTUAL TABLE t2 USING fts4(prefix="1,2");
|
||||
INSERT INTO t1 VALUES('that served him many days;');
|
||||
INSERT INTO t2 VALUES('that served him many days;');
|
||||
} {}
|
||||
do_execsql_test 6.4.2 {
|
||||
SELECT md5sum(quote(root)) FROM t1_segdir;
|
||||
} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
|
||||
|
||||
reset_db
|
||||
do_execsql_test 6.5.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(prefix="2147483647,2147483648,2147483649");
|
||||
CREATE VIRTUAL TABLE t2 USING fts4(prefix=);
|
||||
INSERT INTO t1 VALUES('He dressed himself in cycling clothes');
|
||||
INSERT INTO t2 VALUES('He dressed himself in cycling clothes');
|
||||
} {}
|
||||
do_execsql_test 6.5.2 {
|
||||
SELECT md5sum(quote(root)) FROM t1_segdir;
|
||||
} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}]
|
||||
|
||||
|
||||
do_execsql_test 7.0 {
|
||||
CREATE VIRTUAL TABLE t6 USING fts4(x,order=DESC);
|
||||
INSERT INTO t6(docid, x) VALUES(-1,'a b');
|
||||
INSERT INTO t6(docid, x) VALUES(1, 'b');
|
||||
}
|
||||
do_execsql_test 7.1 {
|
||||
SELECT docid FROM t6 WHERE t6 MATCH '"a* b"';
|
||||
} {-1}
|
||||
do_execsql_test 7.2 {
|
||||
SELECT docid FROM t6 WHERE t6 MATCH 'a*';
|
||||
} {-1}
|
||||
do_execsql_test 7.3 {
|
||||
SELECT docid FROM t6 WHERE t6 MATCH 'a* b';
|
||||
} {-1}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -208,5 +208,81 @@ do_select_tests 6.2 {
|
||||
{{ZZZthe hand XXXgesturesYYY (called beatsZZZ}}
|
||||
}
|
||||
|
||||
# Test some range queries on the rowid field.
|
||||
#
|
||||
do_execsql_test 7.1 {
|
||||
CREATE VIRTUAL TABLE ft4 USING fts4(x);
|
||||
CREATE TABLE t4(x);
|
||||
}
|
||||
|
||||
set SMALLINT -9223372036854775808
|
||||
set LARGEINT 9223372036854775807
|
||||
do_test 7.2 {
|
||||
db transaction {
|
||||
foreach {iFirst nEntry} [subst {
|
||||
0 100
|
||||
$SMALLINT 100
|
||||
[expr $LARGEINT - 99] 100
|
||||
}] {
|
||||
for {set i 0} {$i < $nEntry} {incr i} {
|
||||
set iRowid [expr $i + $iFirst]
|
||||
execsql {
|
||||
INSERT INTO ft4(rowid, x) VALUES($iRowid, 'x y z');
|
||||
INSERT INTO t4(rowid, x) VALUES($iRowid, 'x y z');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
foreach {tn iFirst iLast} [subst {
|
||||
1 5 10
|
||||
2 $SMALLINT [expr $SMALLINT+5]
|
||||
3 $SMALLINT [expr $SMALLINT+50]
|
||||
4 [expr $LARGEINT-5] $LARGEINT
|
||||
5 $LARGEINT $LARGEINT
|
||||
6 $SMALLINT $LARGEINT
|
||||
7 $SMALLINT $SMALLINT
|
||||
8 $LARGEINT $SMALLINT
|
||||
}] {
|
||||
set res [db eval {
|
||||
SELECT rowid FROM t4 WHERE rowid BETWEEN $iFirst AND $iLast
|
||||
} ]
|
||||
|
||||
do_execsql_test 7.2.$tn.1.[llength $res] {
|
||||
SELECT rowid FROM ft4 WHERE rowid BETWEEN $iFirst AND $iLast
|
||||
} $res
|
||||
set res [db eval {
|
||||
SELECT rowid FROM t4 WHERE rowid BETWEEN $iFirst AND $iLast
|
||||
ORDER BY +rowid DESC
|
||||
} ]
|
||||
do_execsql_test 7.2.$tn.2.[llength $res] {
|
||||
SELECT rowid FROM ft4 WHERE rowid BETWEEN $iFirst AND $iLast
|
||||
ORDER BY rowid DESC
|
||||
} $res
|
||||
}
|
||||
|
||||
foreach ii [db eval {SELECT rowid FROM t4}] {
|
||||
set res1 [db eval {SELECT rowid FROM t4 WHERE rowid > $ii}]
|
||||
set res2 [db eval {SELECT rowid FROM t4 WHERE rowid < $ii}]
|
||||
set res1s [db eval {SELECT rowid FROM t4 WHERE rowid > $ii ORDER BY +rowid DESC}]
|
||||
set res2s [db eval {SELECT rowid FROM t4 WHERE rowid < $ii ORDER BY +rowid DESC}]
|
||||
|
||||
do_execsql_test 7.3.$ii.1 {
|
||||
SELECT rowid FROM ft4 WHERE rowid > $ii
|
||||
} $res1
|
||||
|
||||
do_execsql_test 7.3.$ii.2 {
|
||||
SELECT rowid FROM ft4 WHERE rowid < $ii
|
||||
} $res2
|
||||
|
||||
do_execsql_test 7.3.$ii.3 {
|
||||
SELECT rowid FROM ft4 WHERE rowid > $ii ORDER BY rowid DESC
|
||||
} $res1s
|
||||
|
||||
do_execsql_test 7.3.$ii.4 {
|
||||
SELECT rowid FROM ft4 WHERE rowid < $ii ORDER BY rowid DESC
|
||||
} $res2s
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -520,5 +520,43 @@ do_execsql_test 2.6 {
|
||||
{[one] two three [four] five}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 3 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts4;
|
||||
INSERT INTO t3 VALUES('[one two three]');
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one';
|
||||
} {{[<b>one</b> two three]}}
|
||||
do_execsql_test 3.2 {
|
||||
SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'two';
|
||||
} {{[one <b>two</b> three]}}
|
||||
do_execsql_test 3.3 {
|
||||
SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'three';
|
||||
} {{[one two <b>three</b>]}}
|
||||
do_execsql_test 3.4 {
|
||||
SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one OR two OR three';
|
||||
} {{[<b>one</b> <b>two</b> <b>three</b>]}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Request a snippet 0 tokens in size. This is always an empty string.
|
||||
do_execsql_test 4.1 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts4;
|
||||
INSERT INTO t4 VALUES('a b c d');
|
||||
SELECT snippet(t4, '[', ']', '...', 0, 0) FROM t4 WHERE t4 MATCH 'b';
|
||||
} {{}}
|
||||
|
||||
do_test 4.2 {
|
||||
set x35 [string trim [string repeat "x " 35]]
|
||||
execsql "INSERT INTO t4 VALUES('$x35 E $x35 F $x35 G $x35');"
|
||||
llength [db one {
|
||||
SELECT snippet(t4, '', '', '', 0, 64) FROM t4 WHERE t4 MATCH 'E'
|
||||
}]
|
||||
} {64}
|
||||
|
||||
|
||||
|
||||
|
||||
set sqlite_fts3_enable_parentheses 0
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -110,5 +110,15 @@ do_catchsql_test 2.1 {
|
||||
SELECT * FROM t4;
|
||||
} {1 {SQL logic error or missing database}}
|
||||
|
||||
do_catchsql_test 2.2 {
|
||||
CREATE VIRTUAL TABLE t USING fts4(tokenize=simple"");
|
||||
} {0 {}}
|
||||
|
||||
ifcapable fts3_unicode {
|
||||
do_catchsql_test 2.3 {
|
||||
CREATE VIRTUAL TABLE u USING fts4(tokenize=unicode61"");
|
||||
} {1 {unknown tokenizer}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -179,5 +179,35 @@ do_test 4.2 {
|
||||
} {1 {database disk image is malformed}}
|
||||
reset_db
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test case 5.*
|
||||
#
|
||||
# Test that the integrity-check works if there is uncommitted data.
|
||||
#
|
||||
do_execsql_test 5.0 {
|
||||
BEGIN;
|
||||
CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3");
|
||||
INSERT INTO t5 VALUES('And down by Kosiosko, where the reed-banks sweep');
|
||||
INSERT INTO t5 VALUES('and sway, and the rolling plains are wide, the');
|
||||
INSERT INTO t5 VALUES('man from snowy river is a household name today,');
|
||||
INSERT INTO t5 VALUES('and the stockmen tell the story of his ride');
|
||||
}
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
INSERT INTO t5(t5) VALUES('integrity-check');
|
||||
} {}
|
||||
|
||||
do_catchsql_test 5.2 {
|
||||
INSERT INTO t5_content VALUES(5, 'his hardy mountain pony');
|
||||
INSERT INTO t5(t5) VALUES('integrity-check');
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_execsql_test 5.3 ROLLBACK
|
||||
|
||||
do_execsql_test 5.4 {
|
||||
CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3");
|
||||
INSERT INTO t5(t5) VALUES('integrity-check');
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+16
-2
@@ -48,6 +48,9 @@ ifcapable !fts3 {
|
||||
#
|
||||
# 9.* - Test using content=xxx where xxx is a virtual table.
|
||||
#
|
||||
# 11.* - Test that circular references (e.g. "t1(content=t1)") are
|
||||
# detected.
|
||||
#
|
||||
|
||||
do_execsql_test 1.1.1 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
@@ -406,7 +409,7 @@ do_execsql_test 5.1.7 {
|
||||
#
|
||||
do_catchsql_test 6.1.1 {
|
||||
CREATE VIRTUAL TABLE ft7 USING fts4(content=t7);
|
||||
} {1 {vtable constructor failed: ft7}}
|
||||
} {1 {no such table: main.t7}}
|
||||
|
||||
do_execsql_test 6.2.1 {
|
||||
CREATE TABLE t7(one, two);
|
||||
@@ -433,7 +436,7 @@ do_execsql_test 6.2.3 {
|
||||
}
|
||||
do_catchsql_test 6.2.4 {
|
||||
SELECT * FROM ft7;
|
||||
} {1 {vtable constructor failed: ft7}}
|
||||
} {1 {no such table: main.t7}}
|
||||
do_execsql_test 6.2.5 {
|
||||
CREATE TABLE t7(x, y);
|
||||
INSERT INTO t7 VALUES('A B', 'B A');
|
||||
@@ -622,4 +625,15 @@ do_execsql_test 10.7 {
|
||||
{...c d [e] f g...}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test cases 11.*
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_catchsql_test 11.1 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts4(content=x1);
|
||||
} {1 {vtable constructor called recursively: x1}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -125,5 +125,15 @@ do_test fuzz2-6.4b {
|
||||
db eval {SELECT quote(t) FROM t0}
|
||||
} {NULL}
|
||||
|
||||
# Another test case discovered by Michal Zalewski, this on on 2015-01-22.
|
||||
# Ticket 32b63d542433ca6757cd695aca42addf8ed67aa6
|
||||
#
|
||||
do_test fuzz2-7.1 {
|
||||
catchsql {select e.*,0 from(s,(L))e;}
|
||||
} {1 {no such table: s}}
|
||||
do_test fuzz2-7.2 {
|
||||
catchsql {SELECT c.* FROM (a,b) AS c}
|
||||
} {1 {no such table: a}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -109,6 +109,11 @@ do_execsql_test hexlit-301 {
|
||||
do_catchsql_test hexlist-400 {
|
||||
SELECT 0x10000000000000000;
|
||||
} {1 {hex literal too big: 0x10000000000000000}}
|
||||
do_catchsql_test hexlist-410 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(1+0x10000000000000000);
|
||||
} {1 {hex literal too big: 0x10000000000000000}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
# 2015-01-30
|
||||
#
|
||||
# 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 tests for SQLite library.
|
||||
#
|
||||
# The focus of this file is adding extra entries in the symbol table
|
||||
# using sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER) and verifying that
|
||||
# SQLite handles those as expected.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix imposter
|
||||
|
||||
# Create a bunch of data to sort against
|
||||
#
|
||||
do_test imposter-1.0 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d NOT NULL);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE UNIQUE INDEX t1c ON t1(c);
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<30)
|
||||
INSERT INTO t1(a,b,c,d) SELECT i,1000+i,2000+i,3000+i FROM c;
|
||||
}
|
||||
set t1_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1'}]
|
||||
set t1b_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1b'}]
|
||||
set t1c_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1c'}]
|
||||
|
||||
# Create an imposter table that uses the same b-tree as t1 but which does
|
||||
# not have the indexes
|
||||
#
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 $t1_root
|
||||
db eval {CREATE TABLE xt1(a,b,c,d)}
|
||||
|
||||
# And create an imposter table for the t1c index.
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 $t1c_root
|
||||
db eval {CREATE TABLE xt1c(c,rowid,PRIMARY KEY(c,rowid))WITHOUT ROWID;}
|
||||
|
||||
# Go out of imposter mode for now.
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 0
|
||||
|
||||
# Create triggers to record changes to xt1.
|
||||
#
|
||||
db eval {
|
||||
CREATE TEMP TABLE chnglog(desc TEXT);
|
||||
CREATE TEMP TRIGGER xt1_del AFTER DELETE ON xt1 BEGIN
|
||||
INSERT INTO chnglog VALUES(
|
||||
printf('DELETE t1: rowid=%d, a=%s, b=%s, c=%s, d=%s',
|
||||
old.rowid, quote(old.a), quote(old.b), quote(old.c),
|
||||
quote(old.d)));
|
||||
END;
|
||||
CREATE TEMP TRIGGER xt1_ins AFTER INSERT ON xt1 BEGIN
|
||||
INSERT INTO chnglog VALUES(
|
||||
printf('INSERT t1: rowid=%d, a=%s, b=%s, c=%s, d=%s',
|
||||
new.rowid, quote(new.a), quote(new.b), quote(new.c),
|
||||
quote(new.d)));
|
||||
END;
|
||||
}
|
||||
} {}
|
||||
|
||||
# The xt1 table has separate xt1.rowid and xt1.a columns. The xt1.rowid
|
||||
# column corresponds to t1.rowid and t1.a, but the xt1.a column is always
|
||||
# NULL
|
||||
#
|
||||
do_execsql_test imposter-1.1 {
|
||||
SELECT rowid FROM xt1 WHERE a IS NOT NULL;
|
||||
} {}
|
||||
do_execsql_test imposter-1.2 {
|
||||
SELECT a,b,c,d FROM t1 EXCEPT SELECT rowid,b,c,d FROM xt1;
|
||||
SELECT rowid,b,c,d FROM xt1 EXCEPT SELECT a,b,c,d FROM t1;
|
||||
} {}
|
||||
|
||||
|
||||
# Make changes via the xt1 shadow table. This will not update the
|
||||
# indexes on t1 nor check the uniqueness constraint on t1.c nor check
|
||||
# the NOT NULL constraint on t1.d, resulting in a logically inconsistent
|
||||
# database.
|
||||
#
|
||||
do_execsql_test imposter-1.3 {
|
||||
DELETE FROM xt1 WHERE rowid=5;
|
||||
INSERT INTO xt1(rowid,a,b,c,d) VALUES(99,'hello',1099,2022,NULL);
|
||||
SELECT * FROM chnglog ORDER BY rowid;
|
||||
} [list \
|
||||
{DELETE t1: rowid=5, a=NULL, b=1005, c=2005, d=3005} \
|
||||
{INSERT t1: rowid=99, a='hello', b=1099, c=2022, d=NULL} \
|
||||
]
|
||||
|
||||
do_execsql_test imposter-1.4a {
|
||||
PRAGMA integrity_check;
|
||||
} {/NULL value in t1.d/}
|
||||
do_execsql_test imposter-1.4b {
|
||||
PRAGMA integrity_check;
|
||||
} {/row # missing from index t1b/}
|
||||
do_execsql_test imposter-1.4c {
|
||||
PRAGMA integrity_check;
|
||||
} {/row # missing from index t1c/}
|
||||
|
||||
# Cleanup the corruption.
|
||||
# Then demonstrate that the xt1c imposter table can insert non-unique
|
||||
# and NULL values into the UNIQUE index.
|
||||
#
|
||||
do_execsql_test imposter-2.0 {
|
||||
DELETE FROM t1;
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
|
||||
INSERT INTO t1(a,b,c,d) SELECT i,i,i,i FROM c;
|
||||
UPDATE xt1c SET c=NULL WHERE rowid=5;
|
||||
PRAGMA integrity_check;
|
||||
} {/row # missing from index t1c/}
|
||||
|
||||
do_execsql_test imposter-2.1 {
|
||||
DELETE FROM t1;
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
|
||||
INSERT INTO t1(a,b,c,d) SELECT i,i,i,i FROM c;
|
||||
UPDATE xt1c SET c=99 WHERE rowid IN (5,7,9);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
} {1 2 3 4 6 8 10 99 99 99}
|
||||
do_execsql_test imposter-2.2 {
|
||||
UPDATE xt1 SET c=99 WHERE rowid IN (5,7,9);
|
||||
PRAGMA integrity_check;
|
||||
} {/non-unique entry in index t1c/}
|
||||
|
||||
# Erase the imposter tables
|
||||
#
|
||||
do_test imposter-3.1 {
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 1
|
||||
db eval {
|
||||
DELETE FROM t1 WHERE rowid IN (5,7,9);
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} {ok}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -615,6 +615,12 @@ do_test in-13.14 {
|
||||
}
|
||||
} {}
|
||||
|
||||
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}}
|
||||
|
||||
|
||||
do_test in-13.X {
|
||||
db nullvalue ""
|
||||
|
||||
@@ -324,12 +324,44 @@ do_test incrblob2-6.2 {
|
||||
sqlite3_blob_read $rdHandle 0 2
|
||||
} {AB}
|
||||
|
||||
if {$::tcl_platform(pointerSize)>=8} {
|
||||
do_test incrblob2-6.2b {
|
||||
set rc [catch {
|
||||
# Prior to 2015-02-07, the following caused a segfault due to
|
||||
# integer overflow.
|
||||
sqlite3_blob_read $rdHandle 2147483647 2147483647
|
||||
} errmsg]
|
||||
lappend rc $errmsg
|
||||
} {1 SQLITE_ERROR}
|
||||
}
|
||||
do_test incrblob2-6.2c {
|
||||
set rc [catch {
|
||||
# Prior to 2015-02-07, the following caused a segfault due to
|
||||
# integer overflow.
|
||||
sqlite3_blob_read $rdHandle 2147483647 100
|
||||
} errmsg]
|
||||
lappend rc $errmsg
|
||||
} {1 SQLITE_ERROR}
|
||||
|
||||
do_test incrblob2-6.3 {
|
||||
set wrHandle [db incrblob t1 data 1]
|
||||
sqlite3_blob_write $wrHandle 0 ZZZZZZZZZZ
|
||||
sqlite3_blob_read $rdHandle 2 4
|
||||
} {ZZZZ}
|
||||
|
||||
do_test incrblob2-6.3b {
|
||||
set rc [catch {
|
||||
# Prior to 2015-02-07, the following caused a segfault due to
|
||||
# integer overflow.
|
||||
sqlite3_blob_write $wrHandle 2147483647 YYYYYYYYYYYYYYYYYY
|
||||
} errmsg]
|
||||
lappend rc $errmsg
|
||||
} {1 SQLITE_ERROR}
|
||||
do_test incrblob2-6.3c {
|
||||
sqlite3_blob_read $rdHandle 2 4
|
||||
} {ZZZZ}
|
||||
|
||||
|
||||
do_test incrblob2-6.4 {
|
||||
close $wrHandle
|
||||
close $rdHandle
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
# 2001 October 12
|
||||
#
|
||||
# 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 that "PRAGMA incremental_vacuum" detects and reports database
|
||||
# corruption properly. And that "PRAGMA auto_vacuum = INCREMENTAL"
|
||||
# does as well.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix incrcorrupt
|
||||
|
||||
# If this build of the library does not support auto-vacuum, omit this
|
||||
# whole file.
|
||||
ifcapable {!autovacuum} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA auto_vacuum = 2;
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
|
||||
WITH data(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM data
|
||||
)
|
||||
INSERT INTO t1 SELECT i, randomblob(600) FROM data LIMIT 20;
|
||||
PRAGMA page_count;
|
||||
} {24}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
PRAGMA incremental_vacuum;
|
||||
} {}
|
||||
|
||||
do_test 1.2 {
|
||||
db_save
|
||||
hexio_write test.db 36 00000019
|
||||
catchsql { PRAGMA incremental_vacuum; }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_test 1.3 {
|
||||
set stmt [sqlite3_prepare_v2 db "PRAGMA incremental_vacuum" -1 dummy]
|
||||
sqlite3_step $stmt
|
||||
} {SQLITE_CORRUPT}
|
||||
do_test 1.4 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 1.5 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
do_test 1.6 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
|
||||
do_test 1.7 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 1.8 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
do_test 1.9 {
|
||||
set stmt [sqlite3_prepare_v2 db "PRAGMA incremental_vacuum" -1 dummy]
|
||||
sqlite3_step $stmt
|
||||
} {SQLITE_CORRUPT}
|
||||
do_test 1.10 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 1.11 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
do_test 1.12 {
|
||||
set stmt2 [sqlite3_prepare_v2 db "SELECT 1" -1 dummy]
|
||||
sqlite3_finalize $stmt2
|
||||
} {SQLITE_OK}
|
||||
do_test 1.13 { sqlite3_errcode db } {SQLITE_OK}
|
||||
do_test 1.14 { sqlite3_errmsg db } {not an error}
|
||||
|
||||
do_test 1.15 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
|
||||
do_test 1.16 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 1.17 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
PRAGMA auto_vacuum = 1;
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
WITH data(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM data
|
||||
)
|
||||
INSERT INTO t1 SELECT i, randomblob(600) FROM data LIMIT 20;
|
||||
PRAGMA page_count;
|
||||
} {24}
|
||||
|
||||
do_test 2.2 {
|
||||
db_save
|
||||
set fd [open test.db r+]
|
||||
chan truncate $fd [expr 22*1024]
|
||||
close $fd
|
||||
catchsql { PRAGMA incremental_vacuum; }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_test 2.3 {
|
||||
set stmt [sqlite3_prepare_v2 db "PRAGMA auto_vacuum = INCREMENTAL" -1 dummy]
|
||||
sqlite3_step $stmt
|
||||
} {SQLITE_CORRUPT}
|
||||
do_test 2.4 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 2.5 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
do_test 2.6 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
|
||||
do_test 2.7 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 2.8 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
do_test 2.9 {
|
||||
set stmt [sqlite3_prepare_v2 db "PRAGMA auto_vacuum = INCREMENTAL" -1 dummy]
|
||||
sqlite3_step $stmt
|
||||
} {SQLITE_CORRUPT}
|
||||
do_test 2.10 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 2.11 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
do_test 2.12 {
|
||||
set stmt2 [sqlite3_prepare_v2 db "SELECT 1" -1 dummy]
|
||||
sqlite3_finalize $stmt2
|
||||
} {SQLITE_OK}
|
||||
do_test 2.13 { sqlite3_errcode db } {SQLITE_OK}
|
||||
do_test 2.14 { sqlite3_errmsg db } {not an error}
|
||||
|
||||
do_test 2.15 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
|
||||
do_test 2.16 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 2.17 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -188,8 +188,10 @@ ifcapable wal {
|
||||
execsql {
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA incremental_vacuum(1);
|
||||
PRAGMA wal_checkpoint;
|
||||
}
|
||||
} {wal}
|
||||
do_test 4.2.1 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
file size test.db-wal
|
||||
} [expr {32+2*(512+24)}]
|
||||
|
||||
|
||||
+1
-1
@@ -51,6 +51,6 @@ do_test index3-99.1 {
|
||||
db close
|
||||
catch { sqlite3 db test.db }
|
||||
catchsql { DROP INDEX i1 }
|
||||
} {1 {malformed database schema (t1) - near "nonsense": syntax error}}
|
||||
} {1 {malformed database schema (t1)}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -296,4 +296,35 @@ do_execsql_test index6-7.4 {
|
||||
SELECT * FROM t7a JOIN t7b ON (x=99) ORDER BY x;
|
||||
} {/USING COVERING INDEX t7ax/}
|
||||
|
||||
|
||||
do_execsql_test index6-8.0 {
|
||||
CREATE TABLE t8a(a,b);
|
||||
CREATE TABLE t8b(x,y);
|
||||
CREATE INDEX i8c ON t8b(y) WHERE x = 'value';
|
||||
|
||||
INSERT INTO t8a VALUES(1, 'one');
|
||||
INSERT INTO t8a VALUES(2, 'two');
|
||||
INSERT INTO t8a VALUES(3, 'three');
|
||||
|
||||
INSERT INTO t8b VALUES('value', 1);
|
||||
INSERT INTO t8b VALUES('dummy', 2);
|
||||
INSERT INTO t8b VALUES('value', 3);
|
||||
INSERT INTO t8b VALUES('dummy', 4);
|
||||
} {}
|
||||
|
||||
do_eqp_test index6-8.1 {
|
||||
SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t8a}
|
||||
0 1 1 {SEARCH TABLE t8b USING INDEX i8c (y=?)}
|
||||
}
|
||||
|
||||
do_execsql_test index6-8.2 {
|
||||
SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
|
||||
} {
|
||||
1 one value 1
|
||||
2 two {} {}
|
||||
3 three value 3
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -21,6 +21,31 @@ ifcapable !vtab {
|
||||
return
|
||||
}
|
||||
|
||||
# Capture the output of a pragma in a TEMP table.
|
||||
#
|
||||
proc capture_pragma {db tabname sql} {
|
||||
$db eval "DROP TABLE IF EXISTS temp.$tabname"
|
||||
set once 1
|
||||
$db eval $sql x {
|
||||
if {$once} {
|
||||
set once 0
|
||||
set ins "INSERT INTO $tabname VALUES"
|
||||
set crtab "CREATE TEMP TABLE $tabname "
|
||||
set sep "("
|
||||
foreach col $x(*) {
|
||||
append ins ${sep}\$x($col)
|
||||
append crtab ${sep}\"$col\"
|
||||
set sep ,
|
||||
}
|
||||
append ins )
|
||||
append crtab )
|
||||
$db eval $crtab
|
||||
}
|
||||
$db eval $ins
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
load_static_extension db wholenumber;
|
||||
do_test index7-1.1 {
|
||||
# Able to parse and manage partial indices
|
||||
@@ -37,6 +62,15 @@ do_test index7-1.1 {
|
||||
}
|
||||
} {14 20 ok}
|
||||
|
||||
# (The "partial" column of the PRAGMA index_list output is...)
|
||||
# EVIDENCE-OF: R-34457-09668 "1" if the index is a partial index and "0"
|
||||
# if not.
|
||||
#
|
||||
do_test index7-1.1a {
|
||||
capture_pragma db out {PRAGMA index_list(t1)}
|
||||
db eval {SELECT "name", "partial", '|' FROM out ORDER BY "name"}
|
||||
} {sqlite_autoindex_t1_1 0 | t1a 1 | t1b 1 |}
|
||||
|
||||
# Make sure the count(*) optimization works correctly with
|
||||
# partial indices. Ticket [a5c8ed66cae16243be6] 2013-10-03.
|
||||
#
|
||||
@@ -277,5 +311,9 @@ do_eqp_test index7-6.4 {
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t4 USING INDEX i4 (c=?)}
|
||||
}
|
||||
do_catchsql_test index7-6.5 {
|
||||
CREATE INDEX t5a ON t5(a) WHERE a=#1;
|
||||
} {1 {near "#1": syntax error}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+46
-3
@@ -1,4 +1,4 @@
|
||||
# 2008 October 4
|
||||
# 2008-10-04
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
@@ -9,7 +9,6 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# $Id: indexedby.test,v 1.5 2009/03/22 20:36:19 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -58,20 +57,45 @@ do_execsql_test indexedby-1.4 {
|
||||
# attached to a table in the FROM clause, but not to a sub-select or
|
||||
# SQL view. Also test that specifying an index that does not exist or
|
||||
# is attached to a different table is detected as an error.
|
||||
#
|
||||
# EVIDENCE-OF: R-63761-48810 -- syntax diagram qualified-table-name
|
||||
#
|
||||
# EVIDENCE-OF: R-58230-57098 The "INDEXED BY index-name" phrase
|
||||
# specifies that the named index must be used in order to look up values
|
||||
# on the preceding table.
|
||||
#
|
||||
do_test indexedby-2.1 {
|
||||
execsql { SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'}
|
||||
} {}
|
||||
do_test indexedby-2.1b {
|
||||
execsql { SELECT * FROM main.t1 NOT INDEXED WHERE a = 'one' AND b = 'two'}
|
||||
} {}
|
||||
do_test indexedby-2.2 {
|
||||
execsql { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'}
|
||||
} {}
|
||||
do_test indexedby-2.2b {
|
||||
execsql { SELECT * FROM main.t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'}
|
||||
} {}
|
||||
do_test indexedby-2.3 {
|
||||
execsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'}
|
||||
} {}
|
||||
|
||||
# EVIDENCE-OF: R-44699-55558 The INDEXED BY clause does not give the
|
||||
# optimizer hints about which index to use; it gives the optimizer a
|
||||
# requirement of which index to use.
|
||||
# EVIDENCE-OF: R-15800-25719 If index-name does not exist or cannot be
|
||||
# used for the query, then the preparation of the SQL statement fails.
|
||||
#
|
||||
do_test indexedby-2.4 {
|
||||
catchsql { SELECT * FROM t1 INDEXED BY i3 WHERE a = 'one' AND b = 'two'}
|
||||
} {1 {no such index: i3}}
|
||||
|
||||
# EVIDENCE-OF: R-62112-42456 If the query optimizer is unable to use the
|
||||
# index specified by the INDEX BY clause, then the query will fail with
|
||||
# an error.
|
||||
do_test indexedby-2.4.1 {
|
||||
catchsql { SELECT b FROM t1 INDEXED BY i1 WHERE b = 'two' }
|
||||
} {1 {no query solution}}
|
||||
|
||||
do_test indexedby-2.5 {
|
||||
catchsql { SELECT * FROM t1 INDEXED BY i5 WHERE a = 'one' AND b = 'two'}
|
||||
} {1 {no such index: i5}}
|
||||
@@ -82,11 +106,26 @@ do_test indexedby-2.7 {
|
||||
catchsql { SELECT * FROM v1 INDEXED BY i1 WHERE a = 'one' }
|
||||
} {1 {no such index: i1}}
|
||||
|
||||
|
||||
# Tests for single table cases.
|
||||
#
|
||||
# EVIDENCE-OF: R-37002-28871 The "NOT INDEXED" clause specifies that no
|
||||
# index shall be used when accessing the preceding table, including
|
||||
# implied indices create by UNIQUE and PRIMARY KEY constraints. However,
|
||||
# the rowid can still be used to look up entries even when "NOT INDEXED"
|
||||
# is specified.
|
||||
#
|
||||
do_execsql_test indexedby-3.1 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a = 'one' AND b = 'two'
|
||||
} {/SEARCH TABLE t1 USING INDEX/}
|
||||
do_execsql_test indexedby-3.1.1 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
do_execsql_test indexedby-3.1.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE rowid=1
|
||||
} {/SEARCH TABLE t1 USING INTEGER PRIMARY KEY .rowid=/}
|
||||
|
||||
|
||||
do_execsql_test indexedby-3.2 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'
|
||||
@@ -184,6 +223,10 @@ do_execsql_test indexedby-6.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
|
||||
# EVIDENCE-OF: R-40297-14464 The INDEXED BY phrase forces the SQLite
|
||||
# query planner to use a particular named index on a DELETE, SELECT, or
|
||||
# UPDATE statement.
|
||||
#
|
||||
# Test that "INDEXED BY" can be used in a DELETE statement.
|
||||
#
|
||||
do_execsql_test indexedby-7.1 {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix insert2
|
||||
|
||||
# Create some tables with data that we can select against
|
||||
#
|
||||
@@ -275,4 +276,23 @@ ifcapable subquery {
|
||||
} {1 2 1 3 1 4}
|
||||
}
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t5(a, b, c DEFAULT 'c', d);
|
||||
}
|
||||
do_execsql_test 6.1 {
|
||||
INSERT INTO t5(a) SELECT 456 UNION ALL SELECT 123 ORDER BY 1;
|
||||
SELECT * FROM t5 ORDER BY rowid;
|
||||
} {123 {} c {} 456 {} c {}}
|
||||
|
||||
ifcapable fts3 {
|
||||
do_execsql_test 6.2 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts4(a);
|
||||
}
|
||||
do_execsql_test 6.3 {
|
||||
INSERT INTO t0 SELECT 0 UNION SELECT 0 AS 'x' ORDER BY x;
|
||||
SELECT * FROM t0;
|
||||
} {0}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -560,5 +560,10 @@ do_test insert4-8.25 {
|
||||
}
|
||||
} {1 3}
|
||||
|
||||
do_catchsql_test insert4-9.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1(x) VALUES(5 COLLATE xyzzy) UNION SELECT 0;
|
||||
} {1 {no such collation sequence: xyzzy}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -555,4 +555,18 @@ do_execsql_test jrnlmode-8.28 { PRAGMA journal_mode=DELETE } {delete}
|
||||
do_execsql_test jrnlmode-8.29 { COMMIT } {}
|
||||
do_execsql_test jrnlmode-8.30 { PRAGMA journal_mode=DELETE } {delete}
|
||||
|
||||
# Assertion fault on 2015-05-01
|
||||
do_test jrnlmode-9.1 {
|
||||
forcedelete test2.db
|
||||
sqlite3 db2 test2.db
|
||||
db2 eval {CREATE TEMP TABLE t(l); PRAGMA journal_mode=off;}
|
||||
db2 close
|
||||
} {}
|
||||
do_execsql_test jrnlmode-9.2 {
|
||||
PRAGMA locking_mode = exclusive;
|
||||
CREATE TABLE tx(a);
|
||||
PRAGMA journal_mode = off;
|
||||
} {exclusive off}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+2
-2
@@ -749,7 +749,7 @@ ifcapable like_opt&&!icu {
|
||||
count {
|
||||
SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 3 like 0}
|
||||
} {12 123 scan 4 like 0}
|
||||
do_test like-10.6 {
|
||||
count {
|
||||
SELECT a FROM t10 WHERE a LIKE '12%' ORDER BY +a;
|
||||
@@ -790,7 +790,7 @@ ifcapable like_opt&&!icu {
|
||||
count {
|
||||
SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 3 like 0}
|
||||
} {12 123 scan 4 like 0}
|
||||
do_test like-10.15 {
|
||||
count {
|
||||
SELECT a FROM t10b WHERE a GLOB '12*' ORDER BY +a;
|
||||
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
# 2015-03-06
|
||||
#
|
||||
# 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 LIKE and GLOB operators and
|
||||
# in particular the optimizations that occur to help those operators
|
||||
# run faster and that those optimizations work correctly when there
|
||||
# are both strings and blobs being tested.
|
||||
#
|
||||
# Ticket 05f43be8fdda9fbd948d374319b99b054140bc36 shows that the following
|
||||
# SQL was not working correctly:
|
||||
#
|
||||
# CREATE TABLE t1(x TEXT UNIQUE COLLATE nocase);
|
||||
# INSERT INTO t1(x) VALUES(x'616263');
|
||||
# SELECT 'query-1', x FROM t1 WHERE x LIKE 'a%';
|
||||
# SELECT 'query-2', x FROM t1 WHERE +x LIKE 'a%';
|
||||
#
|
||||
# This script verifies that it works right now.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_execsql_test like3-1.1 {
|
||||
PRAGMA encoding=UTF8;
|
||||
CREATE TABLE t1(a,b TEXT COLLATE nocase);
|
||||
INSERT INTO t1(a,b)
|
||||
VALUES(1,'abc'),
|
||||
(2,'ABX'),
|
||||
(3,'BCD'),
|
||||
(4,x'616263'),
|
||||
(5,x'414258'),
|
||||
(6,x'424344');
|
||||
CREATE INDEX t1ba ON t1(b,a);
|
||||
|
||||
SELECT a, b FROM t1 WHERE b LIKE 'aB%' ORDER BY +a;
|
||||
} {1 abc 2 ABX 4 abc 5 ABX}
|
||||
do_execsql_test like3-1.2 {
|
||||
SELECT a, b FROM t1 WHERE +b LIKE 'aB%' ORDER BY +a;
|
||||
} {1 abc 2 ABX 4 abc 5 ABX}
|
||||
|
||||
do_execsql_test like3-2.0 {
|
||||
CREATE TABLE t2(a, b TEXT);
|
||||
INSERT INTO t2 SELECT a, b FROM t1;
|
||||
CREATE INDEX t2ba ON t2(b,a);
|
||||
SELECT a, b FROM t2 WHERE b GLOB 'ab*' ORDER BY +a;
|
||||
} {1 abc 4 abc}
|
||||
do_execsql_test like3-2.1 {
|
||||
SELECT a, b FROM t2 WHERE +b GLOB 'ab*' ORDER BY +a;
|
||||
} {1 abc 4 abc}
|
||||
do_execsql_test like3-2.2 {
|
||||
SELECT a, b FROM t2 WHERE b>=x'6162' AND b GLOB 'ab*'
|
||||
} {4 abc}
|
||||
do_execsql_test like3-2.3 {
|
||||
SELECT a, b FROM t2 WHERE +b>=x'6162' AND +b GLOB 'ab*'
|
||||
} {4 abc}
|
||||
do_execsql_test like3-2.4 {
|
||||
SELECT a, b FROM t2 WHERE b GLOB 'ab*' AND b>=x'6162'
|
||||
} {4 abc}
|
||||
do_execsql_test like3-2.5 {
|
||||
SELECT a, b FROM t2 WHERE +b GLOB 'ab*' AND +b>=x'6162'
|
||||
} {4 abc}
|
||||
|
||||
do_execsql_test like3-3.0 {
|
||||
CREATE TABLE t3(x TEXT PRIMARY KEY COLLATE nocase);
|
||||
INSERT INTO t3(x) VALUES('aaa'),('abc'),('abd'),('abe'),('acz');
|
||||
INSERT INTO t3(x) SELECT CAST(x AS blob) FROM t3;
|
||||
SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY x;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
do_execsql_test like3-3.1 {
|
||||
SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY x DESC;
|
||||
} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'}
|
||||
do_execsql_test like3-3.1ck {
|
||||
SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY +x DESC;
|
||||
} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'}
|
||||
do_execsql_test like3-3.2 {
|
||||
SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY x ASC;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
do_execsql_test like3-3.2ck {
|
||||
SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY +x ASC;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
|
||||
do_execsql_test like3-4.0 {
|
||||
CREATE TABLE t4(x TEXT COLLATE nocase);
|
||||
CREATE INDEX t4x ON t4(x DESC);
|
||||
INSERT INTO t4(x) SELECT x FROM t3;
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY x;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
do_execsql_test like3-4.1 {
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY x DESC;
|
||||
} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'}
|
||||
do_execsql_test like3-4.1ck {
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY +x DESC;
|
||||
} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'}
|
||||
do_execsql_test like3-4.2 {
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY x ASC;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
do_execsql_test like3-4.2ck {
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY +x ASC;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -251,6 +251,12 @@ do_test limit-6.8 {
|
||||
# Make sure LIMIT works well with compound SELECT statements.
|
||||
# Ticket #393
|
||||
#
|
||||
# EVIDENCE-OF: R-13512-64012 In a compound SELECT, only the last or
|
||||
# right-most simple SELECT may contain a LIMIT clause.
|
||||
#
|
||||
# EVIDENCE-OF: R-03782-50113 In a compound SELECT, the LIMIT clause
|
||||
# applies to the entire compound, not just the final SELECT.
|
||||
#
|
||||
ifcapable compound {
|
||||
do_test limit-7.1.1 {
|
||||
catchsql {
|
||||
|
||||
@@ -241,6 +241,9 @@ execsql {ROLLBACK}
|
||||
|
||||
# Test the built-in busy timeout handler
|
||||
#
|
||||
# EVIDENCE-OF: R-23579-05241 PRAGMA busy_timeout; PRAGMA busy_timeout =
|
||||
# milliseconds; Query or change the setting of the busy timeout.
|
||||
#
|
||||
do_test lock-2.8 {
|
||||
db2 timeout 400
|
||||
execsql BEGIN
|
||||
|
||||
+44
-14
@@ -86,21 +86,51 @@ proc launch_testfixture {{prg ""}} {
|
||||
# Execute a command in a child testfixture process, connected by two-way
|
||||
# channel $chan. Return the result of the command, or an error message.
|
||||
#
|
||||
proc testfixture {chan cmd} {
|
||||
puts $chan $cmd
|
||||
puts $chan OVER
|
||||
set r ""
|
||||
while { 1 } {
|
||||
proc testfixture {chan cmd args} {
|
||||
|
||||
if {[llength $args] == 0} {
|
||||
fconfigure $chan -blocking 1
|
||||
puts $chan $cmd
|
||||
puts $chan OVER
|
||||
|
||||
set r ""
|
||||
while { 1 } {
|
||||
set line [gets $chan]
|
||||
if { $line == "OVER" } {
|
||||
set res [lindex $r 1]
|
||||
if { [lindex $r 0] } { error $res }
|
||||
return $res
|
||||
}
|
||||
if {[eof $chan]} {
|
||||
return "ERROR: Child process hung up"
|
||||
}
|
||||
append r $line
|
||||
}
|
||||
return $r
|
||||
} else {
|
||||
set ::tfnb($chan) ""
|
||||
fconfigure $chan -blocking 0 -buffering none
|
||||
puts $chan $cmd
|
||||
puts $chan OVER
|
||||
fileevent $chan readable [list testfixture_script_cb $chan [lindex $args 0]]
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
proc testfixture_script_cb {chan script} {
|
||||
if {[eof $chan]} {
|
||||
append ::tfnb($chan) "ERROR: Child process hung up"
|
||||
set line "OVER"
|
||||
} else {
|
||||
set line [gets $chan]
|
||||
if { $line == "OVER" } {
|
||||
set res [lindex $r 1]
|
||||
if { [lindex $r 0] } { error $res }
|
||||
return $res
|
||||
}
|
||||
if {[eof $chan]} {
|
||||
return "ERROR: Child process hung up"
|
||||
}
|
||||
append r $line
|
||||
}
|
||||
|
||||
if { $line == "OVER" } {
|
||||
uplevel #0 $script [list [lindex $::tfnb($chan) 1]]
|
||||
unset ::tfnb($chan)
|
||||
fileevent $chan readable ""
|
||||
} else {
|
||||
append ::tfnb($chan) $line
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -923,6 +923,27 @@ do_faultsim_test 41.2 -faults oom* -body {
|
||||
faultsim_integrity_check
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 42.0 {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y, z);
|
||||
CREATE TABLE t2(a, b);
|
||||
CREATE VIEW a002 AS SELECT *, sum(b) AS m FROM t2 GROUP BY a;
|
||||
}
|
||||
faultsim_save_and_close
|
||||
do_faultsim_test 42 -faults oom-tran* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql { SELECT * FROM sqlite_master }
|
||||
} -body {
|
||||
execsql {
|
||||
SELECT t1.z, a002.m
|
||||
FROM t1 JOIN a002 ON t1.y=a002.m
|
||||
WHERE t1.x IN (1,2,3);
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
|
||||
# Ensure that no file descriptors were leaked.
|
||||
do_test malloc-99.X {
|
||||
catch {db close}
|
||||
|
||||
+23
-6
@@ -71,6 +71,23 @@ do_test malloc5-1.3 {
|
||||
expr $::pgalloc > 0
|
||||
} {1}
|
||||
|
||||
# The sizes of memory allocations from system malloc() might vary,
|
||||
# depending on the memory allocator algorithms used. The following
|
||||
# routine is designed to support answers that fall within a range
|
||||
# of values while also supplying easy-to-understand "expected" values
|
||||
# when errors occur.
|
||||
#
|
||||
proc value_in_range {target x args} {
|
||||
set v [lindex $args 0]
|
||||
if {$v!=""} {
|
||||
if {$v<$target*$x} {return $v}
|
||||
if {$v>$target/$x} {return $v}
|
||||
}
|
||||
return "number between [expr {int($target*$x)}] and [expr {int($target/$x)}]"
|
||||
}
|
||||
set mrange 0.98 ;# plus or minus 2%
|
||||
|
||||
|
||||
do_test malloc5-1.4 {
|
||||
# Commit the transaction and open a new one. Read 1 page into the cache.
|
||||
# Because the page is not dirty, it is eligible for collection even
|
||||
@@ -81,16 +98,16 @@ do_test malloc5-1.4 {
|
||||
BEGIN;
|
||||
SELECT * FROM abc;
|
||||
}
|
||||
sqlite3_release_memory
|
||||
} $::pgalloc
|
||||
value_in_range $::pgalloc $::mrange [sqlite3_release_memory]
|
||||
} [value_in_range $::pgalloc $::mrange]
|
||||
|
||||
do_test malloc5-1.5 {
|
||||
# Conclude the transaction opened in the previous [do_test] block. This
|
||||
# causes another page (page 1) to become eligible for recycling.
|
||||
#
|
||||
execsql { COMMIT }
|
||||
sqlite3_release_memory
|
||||
} $::pgalloc
|
||||
value_in_range $::pgalloc $::mrange [sqlite3_release_memory]
|
||||
} [value_in_range $::pgalloc $::mrange]
|
||||
|
||||
do_test malloc5-1.6 {
|
||||
# Manipulate the cache so that it contains two unused pages. One requires
|
||||
@@ -101,8 +118,8 @@ do_test malloc5-1.6 {
|
||||
SELECT * FROM abc;
|
||||
CREATE TABLE def(d, e, f);
|
||||
}
|
||||
sqlite3_release_memory 500
|
||||
} $::pgalloc
|
||||
value_in_range $::pgalloc $::mrange [sqlite3_release_memory 500]
|
||||
} [value_in_range $::pgalloc $::mrange]
|
||||
|
||||
do_test malloc5-1.7 {
|
||||
# Database should not be locked this time.
|
||||
|
||||
@@ -134,5 +134,42 @@ do_faultsim_test 6 -faults oom* -body {
|
||||
faultsim_test_result {0 {12 13 14 15}}
|
||||
}
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
CREATE TABLE x1(a INTEGER PRIMARY KEY, b);
|
||||
}
|
||||
do_faultsim_test 7.2 -faults oom* -body {
|
||||
execsql { SELECT * FROM x1 WHERE a = (SELECT 1) }
|
||||
} -test {
|
||||
faultsim_test_result [list 0 {}]
|
||||
}
|
||||
|
||||
reset_db
|
||||
|
||||
proc isqrt {i} { expr { int(sqrt($i)) } }
|
||||
db func isqrt isqrt
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
PRAGMA encoding = 'utf-16';
|
||||
CREATE TABLE x2(x TEXT, y TEXT);
|
||||
WITH data(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM data
|
||||
)
|
||||
INSERT INTO x2 SELECT isqrt(i), isqrt(i) FROM data LIMIT 400;
|
||||
CREATE INDEX x2x ON x2(x);
|
||||
CREATE INDEX x2y ON x2(y);
|
||||
ANALYZE;
|
||||
DELETE FROM x2;
|
||||
}
|
||||
|
||||
proc str {a} { return $a }
|
||||
db func str -deterministic str
|
||||
|
||||
do_faultsim_test 8 -faults oom* -body {
|
||||
execsql { SELECT * FROM x2 WHERE x = str('19') AND y = str('4') }
|
||||
} -test {
|
||||
faultsim_test_result [list 0 {}]
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+64
-1
@@ -13,7 +13,6 @@
|
||||
# This file implements tests for miscellanous features that were
|
||||
# left out of other test files.
|
||||
#
|
||||
# $Id: misc1.test,v 1.42 2007/11/05 14:58:23 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -621,4 +620,68 @@ do_test misc1-19.2 {
|
||||
set fault_callbacks
|
||||
} {0}
|
||||
|
||||
# 2015-01-26: Valgrind-detected over-read.
|
||||
# Reported on sqlite-users@sqlite.org by Michal Zalewski. Found by afl-fuzz
|
||||
# presumably.
|
||||
#
|
||||
do_execsql_test misc1-20.1 {
|
||||
CREATE TABLE t0(x INTEGER DEFAULT(0==0) NOT NULL);
|
||||
REPLACE INTO t0(x) VALUES('');
|
||||
SELECT rowid, quote(x) FROM t0;
|
||||
} {1 ''}
|
||||
|
||||
# 2015-03-22: NULL pointer dereference after a syntax error
|
||||
#
|
||||
do_catchsql_test misc1-21.1 {
|
||||
select''like''like''like#0;
|
||||
} {1 {near "#0": syntax error}}
|
||||
do_catchsql_test misc1-21.2 {
|
||||
VALUES(0,0x0MATCH#0;
|
||||
} {1 {near ";": syntax error}}
|
||||
|
||||
# 2015-04-15
|
||||
do_execsql_test misc1-22.1 {
|
||||
SELECT ""+3 FROM (SELECT ""+5);
|
||||
} {3}
|
||||
|
||||
# 2015-04-19: NULL pointer dereference on a corrupt schema
|
||||
#
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_execsql_test misc1-23.1 {
|
||||
CREATE TABLE t1(x);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE table t(d CHECK(T(#0)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(y);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS t3;
|
||||
} {}
|
||||
|
||||
# 2015-04-19: Faulty assert() statement
|
||||
#
|
||||
db close
|
||||
database_may_be_corrupt
|
||||
sqlite3 db :memory:
|
||||
do_catchsql_test misc1-23.2 {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE TABLE IF not EXISTS t(c)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(x);
|
||||
ROLLBACK;
|
||||
DROP TABLE F;
|
||||
} {1 {no such table: F}}
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_catchsql_test misc1-23.3 {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE table y(a TEXT, a TEXT)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(y);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS t;
|
||||
} {0 {}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -583,6 +583,24 @@ do_test misc5-7.1 {
|
||||
catchsql $sql
|
||||
} {1 {parser stack overflow}}
|
||||
|
||||
# Parser stack overflow is silently ignored when it occurs while parsing the
|
||||
# schema and PRAGMA writable_schema is turned on.
|
||||
#
|
||||
do_test misc5-7.2 {
|
||||
sqlite3 db2 :memory:
|
||||
catchsql {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE table t(o CHECK(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((;VALUES(o)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(y);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS D;
|
||||
} db2
|
||||
} {0 {}}
|
||||
db2 close
|
||||
|
||||
|
||||
# Ticket #1911
|
||||
#
|
||||
ifcapable compound {
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# Run this script in order to rebuild the fuzzdata1.txt file containing
|
||||
# fuzzer data for the fuzzershell utility that is create by afl-fuzz.
|
||||
#
|
||||
# This script gathers all of the test cases identified by afl-fuzz and
|
||||
# runs afl-cmin and afl-tmin over them all to try to generate a mimimum
|
||||
# set of tests that cover all observed behavior.
|
||||
#
|
||||
# Options:
|
||||
#
|
||||
# --afl-bin DIR1 DIR1 contains the AFL binaries
|
||||
# --fuzzershell PATH Full pathname of instrumented fuzzershell
|
||||
# --afl-data DIR3 DIR3 is the "-o" directory from afl-fuzz
|
||||
# -o FILE Write results into FILE
|
||||
#
|
||||
set AFLBIN {}
|
||||
set FUZZERSHELL {}
|
||||
set AFLDATA {}
|
||||
set OUTFILE {}
|
||||
|
||||
proc usage {} {
|
||||
puts stderr "Usage: $::argv0 --afl-bin DIR --fuzzershell PATH\
|
||||
--afl-data DIR -o FILE"
|
||||
exit 1
|
||||
}
|
||||
proc cmdlineerr {msg} {
|
||||
puts stderr $msg
|
||||
usage
|
||||
}
|
||||
|
||||
for {set i 0} {$i<[llength $argv]} {incr i} {
|
||||
set x [lindex $argv $i]
|
||||
if {[string index $x 0]!="-"} {cmdlineerr "illegal argument: $x"}
|
||||
set x [string trimleft $x -]
|
||||
incr i
|
||||
if {$i>=[llength $argv]} {cmdlineerr "no argument on --$x"}
|
||||
set a [lindex $argv $i]
|
||||
switch -- $x {
|
||||
afl-bin {set AFLBIN $a}
|
||||
afl-data {set AFLDATA $a}
|
||||
fuzzershell {set FUZZERSHELL $a}
|
||||
o {set OUTFILE $a}
|
||||
default {cmdlineerr "unknown option: --$x"}
|
||||
}
|
||||
}
|
||||
proc checkarg {varname option} {
|
||||
set val [set ::$varname]
|
||||
if {$val==""} {cmdlineerr "required option missing: --$option"}
|
||||
}
|
||||
checkarg AFLBIN afl-bin
|
||||
checkarg AFLDATA afl-data
|
||||
checkarg FUZZERSHELL fuzzershell
|
||||
checkarg OUTFILE o
|
||||
proc checkexec {x} {
|
||||
if {![file exec $x]} {cmdlineerr "cannot find $x"}
|
||||
}
|
||||
checkexec $AFLBIN/afl-cmin
|
||||
checkexec $AFLBIN/afl-tmin
|
||||
checkexec $FUZZERSHELL
|
||||
proc checkdir {x} {
|
||||
if {![file isdir $x]} {cmdlineerr "no such directory: $x"}
|
||||
}
|
||||
checkdir $AFLDATA/queue
|
||||
|
||||
proc progress {msg} {
|
||||
puts "******** $msg"
|
||||
flush stdout
|
||||
}
|
||||
progress "mkdir tmp1 tmp2"
|
||||
file mkdir tmp1 tmp2
|
||||
progress "copying test cases from $AFLDATA into tmp1..."
|
||||
set n 0
|
||||
foreach file [glob -nocomplain $AFLDATA/queue/id:*] {
|
||||
incr n
|
||||
file copy $file tmp1/$n
|
||||
}
|
||||
foreach file [glob -nocomplain $AFLDATA/crash*/id:*] {
|
||||
incr n
|
||||
file copy $file tmp1/$n
|
||||
}
|
||||
progress "total $n files copied."
|
||||
progress "running: $AFLBIN/afl-cmin -i tmp1 -o tmp2 $FUZZERSHELL"
|
||||
exec $AFLBIN/afl-cmin -i tmp1 -o tmp2 $FUZZERSHELL >&@ stdout
|
||||
progress "afl-cmin complete."
|
||||
#
|
||||
# Experiments show that running afl-tmin is too slow for this application.
|
||||
# And it doesn't really make the test cases that much smaller. So let's
|
||||
# just skip it.
|
||||
#
|
||||
# foreach file [glob tmp2/*] {
|
||||
# progress "$AFLBIN/afl-tmin -i $file -o tmp3/[file tail $file] $FUZZERSHELL"
|
||||
# exec $AFLBIN/afl-tmin -i $file -o tmp3/[file tail $file] \
|
||||
# $FUZZERSHELL >&@ stdout
|
||||
# }
|
||||
progress "generating final output into $OUTFILE"
|
||||
set out [open $OUTFILE wb]
|
||||
puts $out "# Test data for use with fuzzershell. Automatically
|
||||
# generated using $argv0. This file contains binary data
|
||||
#"
|
||||
set n 0
|
||||
foreach file [glob tmp2/*] {
|
||||
incr n
|
||||
puts -nonewline $out "/****<$n>****/"
|
||||
set in [open $file rb]
|
||||
puts -nonewline $out [read $in]
|
||||
close $in
|
||||
}
|
||||
close $out
|
||||
progress "done. $n test cases written to $OUTFILE"
|
||||
progress "clean-up..."
|
||||
file delete -force tmp1
|
||||
progress "culled test cases left in the tmp2 directory"
|
||||
@@ -59,6 +59,14 @@ do_test multiplex4-1.1 {
|
||||
multiplex_file_list mx4test
|
||||
} {mx4test.db}
|
||||
|
||||
# NB: The PRAGMA multiplex_truncate command is implemented using the
|
||||
# SQLITE_FCNTL_PRAGMA file-control...
|
||||
#
|
||||
# EVIDENCE-OF: R-12238-55120 Whenever a PRAGMA statement is parsed, an
|
||||
# SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file
|
||||
# object corresponding to the database file to which the pragma
|
||||
# statement refers.
|
||||
#
|
||||
do_test multiplex4-1.2 {
|
||||
db eval {PRAGMA multiplex_truncate}
|
||||
} {on}
|
||||
@@ -84,6 +92,16 @@ do_test multiplex4-1.9 {
|
||||
db eval {PRAGMA multiplex_truncate=0}
|
||||
} {off}
|
||||
|
||||
# EVIDENCE-OF: R-26188-08449 If the SQLITE_FCNTL_PRAGMA file control
|
||||
# returns SQLITE_OK, then the parser assumes that the VFS has handled
|
||||
# the PRAGMA itself and the parser generates a no-op prepared statement
|
||||
# if result string is NULL, or that returns a copy of the result string
|
||||
# if the string is non-NULL.
|
||||
#
|
||||
do_test multiplex4-1.9-explain {
|
||||
db eval {EXPLAIN PRAGMA multiplex_truncate=0;}
|
||||
} {/String8 \d \d \d off/}
|
||||
|
||||
do_test multiplex4-1.10 {
|
||||
db eval {
|
||||
INSERT INTO t1(x) VALUES(randomblob(250000));
|
||||
|
||||
@@ -278,6 +278,23 @@ do_test null-8.15 {
|
||||
}
|
||||
} {1}
|
||||
|
||||
do_execsql_test null-9.1 {
|
||||
CREATE TABLE t5(a, b, c);
|
||||
CREATE UNIQUE INDEX t5ab ON t5(a, b);
|
||||
|
||||
INSERT INTO t5 VALUES(1, NULL, 'one');
|
||||
INSERT INTO t5 VALUES(1, NULL, 'i');
|
||||
INSERT INTO t5 VALUES(NULL, 'x', 'two');
|
||||
INSERT INTO t5 VALUES(NULL, 'x', 'ii');
|
||||
}
|
||||
|
||||
do_execsql_test null-9.2 {
|
||||
SELECT * FROM t5 WHERE a = 1 AND b IS NULL;
|
||||
} {1 {} one 1 {} i}
|
||||
|
||||
do_execsql_test null-9.3 {
|
||||
SELECT * FROM t5 WHERE a IS NULL AND b = 'x';
|
||||
} {{} x two {} x ii}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -463,6 +463,9 @@ do_execsql_test 5.1 {
|
||||
do_execsql_test 5.2 {
|
||||
SELECT 5 UNION ALL SELECT 3 ORDER BY 1
|
||||
} {3 5}
|
||||
do_execsql_test 5.3 {
|
||||
SELECT 986 AS x GROUP BY X ORDER BY X
|
||||
} {986}
|
||||
|
||||
# The following test (originally derived from a single test within fuzz.test)
|
||||
# verifies that a PseudoTable cursor is not closed prematurely in a deeply
|
||||
@@ -495,5 +498,34 @@ do_execsql_test 7.0 {
|
||||
SELECT * FROM t7 WHERE a=?1 ORDER BY rowid;
|
||||
} {~/ORDER BY/}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test a partial sort large enough to cause the sorter to spill data
|
||||
# to disk.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.0 {
|
||||
PRAGMA cache_size = 5;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
}
|
||||
|
||||
do_eqp_test 8.1 {
|
||||
SELECT * FROM t1 ORDER BY a, b;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING INDEX i1}
|
||||
0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
}
|
||||
|
||||
do_execsql_test 8.2 {
|
||||
WITH cnt(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000
|
||||
)
|
||||
INSERT INTO t1 SELECT i%2, randomblob(500) FROM cnt;
|
||||
}
|
||||
|
||||
do_test 8.3 {
|
||||
db eval { SELECT * FROM t1 ORDER BY a, b } { incr res $a }
|
||||
set res
|
||||
} 5000
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -216,4 +216,22 @@ foreach PGSZ {512 2048 4096 8192} {
|
||||
} [list $PGSZ $PGSZ]
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test pagesize-3.1 {
|
||||
BEGIN;
|
||||
SELECT * FROM sqlite_master;
|
||||
PRAGMA page_size=2048;
|
||||
PRAGMA main.page_size;
|
||||
} {1024}
|
||||
do_execsql_test pagesize-3.2 {
|
||||
CREATE TABLE t1(x);
|
||||
COMMIT;
|
||||
}
|
||||
do_execsql_test pagesize-3.3 {
|
||||
BEGIN;
|
||||
PRAGMA page_size = 2048;
|
||||
COMMIT;
|
||||
PRAGMA main.page_size;
|
||||
} {1024}
|
||||
|
||||
finish_test
|
||||
|
||||
+186
-17
@@ -51,6 +51,30 @@ ifcapable !pragma {
|
||||
return
|
||||
}
|
||||
|
||||
# Capture the output of a pragma in a TEMP table.
|
||||
#
|
||||
proc capture_pragma {db tabname sql} {
|
||||
$db eval "DROP TABLE IF EXISTS temp.$tabname"
|
||||
set once 1
|
||||
$db eval $sql x {
|
||||
if {$once} {
|
||||
set once 0
|
||||
set ins "INSERT INTO $tabname VALUES"
|
||||
set crtab "CREATE TEMP TABLE $tabname "
|
||||
set sep "("
|
||||
foreach col $x(*) {
|
||||
append ins ${sep}\$x($col)
|
||||
append crtab ${sep}\"$col\"
|
||||
set sep ,
|
||||
}
|
||||
append ins )
|
||||
append crtab )
|
||||
$db eval $crtab
|
||||
}
|
||||
$db eval $ins
|
||||
}
|
||||
}
|
||||
|
||||
# Delete the preexisting database to avoid the special setup
|
||||
# that the "all.test" script does.
|
||||
#
|
||||
@@ -59,7 +83,11 @@ delete_file test.db test.db-journal
|
||||
delete_file test3.db test3.db-journal
|
||||
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-24197-42751 PRAGMA database.cache_size; PRAGMA
|
||||
# database.cache_size = pages; PRAGMA database.cache_size = -kibibytes;
|
||||
# Query or change the suggested maximum number of database disk pages
|
||||
# that SQLite will hold in memory at once per open database file.
|
||||
#
|
||||
ifcapable pager_pragmas {
|
||||
set DFLT_CACHE_SZ [db one {PRAGMA default_cache_size}]
|
||||
set TEMP_CACHE_SZ [db one {PRAGMA temp.default_cache_size}]
|
||||
@@ -71,6 +99,8 @@ do_test pragma-1.1 {
|
||||
}
|
||||
} [list $DFLT_CACHE_SZ $DFLT_CACHE_SZ 2]
|
||||
do_test pragma-1.2 {
|
||||
# EVIDENCE-OF: R-42059-47211 If the argument N is positive then the
|
||||
# suggested cache size is set to N.
|
||||
execsql {
|
||||
PRAGMA synchronous=OFF;
|
||||
PRAGMA cache_size=1234;
|
||||
@@ -189,6 +219,24 @@ do_test pragma-1.14 {
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {2}
|
||||
do_test pragma-1.14.1 {
|
||||
execsql {
|
||||
PRAGMA synchronous=4;
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {0}
|
||||
do_test pragma-1.14.2 {
|
||||
execsql {
|
||||
PRAGMA synchronous=3;
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {0}
|
||||
do_test pragma-1.14.3 {
|
||||
execsql {
|
||||
PRAGMA synchronous=10;
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {2}
|
||||
} ;# ifcapable pager_pragmas
|
||||
|
||||
# Test turning "flag" pragmas on and off.
|
||||
@@ -620,9 +668,10 @@ ifcapable {foreignkey} {
|
||||
}
|
||||
} {}
|
||||
do_test pragma-6.4 {
|
||||
execsql {
|
||||
capture_pragma db out {
|
||||
pragma index_list(t3);
|
||||
}
|
||||
db eval {SELECT seq, "name", "unique" FROM out ORDER BY seq}
|
||||
} {0 sqlite_autoindex_t3_1 1}
|
||||
}
|
||||
ifcapable {!foreignkey} {
|
||||
@@ -631,9 +680,43 @@ ifcapable {!foreignkey} {
|
||||
do_test pragma-6.5.1 {
|
||||
execsql {
|
||||
CREATE INDEX t3i1 ON t3(a,b);
|
||||
}
|
||||
capture_pragma db out {
|
||||
pragma index_info(t3i1);
|
||||
}
|
||||
db eval {SELECT seqno, cid, name FROM out ORDER BY seqno}
|
||||
} {0 0 a 1 1 b}
|
||||
|
||||
# EVIDENCE-OF: R-23114-21695 The auxiliary index-columns are not shown
|
||||
# by the index_info pragma, but they are listed by the index_xinfo
|
||||
# pragma.
|
||||
#
|
||||
do_test pragma-6.5.1b {
|
||||
capture_pragma db out {PRAGMA index_xinfo(t3i1)}
|
||||
db eval {SELECT seqno, cid, name FROM out ORDER BY seqno}
|
||||
} {0 0 a 1 1 b 2 -1 {}}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-62725-03366 PRAGMA database.index_info(index-name);
|
||||
# This pragma returns one row for each key column in the named index.
|
||||
#
|
||||
# (The first column of output from PRAGMA index_info is...)
|
||||
# EVIDENCE-OF: R-34186-52914 The rank of the column within the index. (0
|
||||
# means left-most.)
|
||||
#
|
||||
# (The second column of output from PRAGMA index_info is...)
|
||||
# EVIDENCE-OF: R-65019-08383 The rank of the column within the table
|
||||
# being indexed.
|
||||
#
|
||||
# (The third column of output from PRAGMA index_info is...)
|
||||
# EVIDENCE-OF: R-09773-34266 The name of the column being indexed.
|
||||
#
|
||||
do_execsql_test pragma-6.5.1c {
|
||||
CREATE INDEX t3i2 ON t3(b,a);
|
||||
PRAGMA index_info='t3i2';
|
||||
DROP INDEX t3i2;
|
||||
} {0 1 b 1 0 a}
|
||||
|
||||
do_test pragma-6.5.2 {
|
||||
execsql {
|
||||
pragma index_info(t3i1_bogus);
|
||||
@@ -676,8 +759,10 @@ do_test pragma-6.7 {
|
||||
four REAL DEFAULT X'abcdef',
|
||||
five DEFAULT CURRENT_TIME
|
||||
);
|
||||
PRAGMA table_info(test_table);
|
||||
}
|
||||
capture_pragma db out {PRAGMA table_info(test_table)}
|
||||
db eval {SELECT cid, "name", type, "notnull", dflt_value, pk FROM out
|
||||
ORDER BY cid}
|
||||
} [concat \
|
||||
{0 one INT 1 -1 0} \
|
||||
{1 two text 0 {} 0} \
|
||||
@@ -685,18 +770,30 @@ do_test pragma-6.7 {
|
||||
{3 four REAL 0 X'abcdef' 0} \
|
||||
{4 five {} 0 CURRENT_TIME 0} \
|
||||
]
|
||||
do_test pragma-6.8 {
|
||||
execsql {
|
||||
CREATE TABLE t68(a,b,c,PRIMARY KEY(a,b,a,c));
|
||||
PRAGMA table_info(t68);
|
||||
}
|
||||
} [concat \
|
||||
{0 a {} 0 {} 1} \
|
||||
{1 b {} 0 {} 2} \
|
||||
{2 c {} 0 {} 4} \
|
||||
]
|
||||
} ;# ifcapable schema_pragmas
|
||||
# Miscellaneous tests
|
||||
#
|
||||
ifcapable schema_pragmas {
|
||||
# EVIDENCE-OF: R-63500-32024 PRAGMA database.index_list(table-name);
|
||||
# This pragma returns one row for each index associated with the given
|
||||
# table.
|
||||
do_test pragma-7.1.1 {
|
||||
# Make sure a pragma knows to read the schema if it needs to
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
pragma index_list(t3);
|
||||
}
|
||||
} {0 t3i1 0 1 sqlite_autoindex_t3_1 1}
|
||||
capture_pragma db out "PRAGMA index_list(t3)"
|
||||
db eval {SELECT name, "origin" FROM out ORDER BY name DESC}
|
||||
} {t3i1 c sqlite_autoindex_t3_1 u}
|
||||
do_test pragma-7.1.2 {
|
||||
execsql {
|
||||
pragma index_list(t3_bogus);
|
||||
@@ -1281,18 +1378,23 @@ ifcapable pager_pragmas {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-13905-26312 PRAGMA database.page_count; Return the
|
||||
# total number of pages in the database file.
|
||||
#
|
||||
do_test pragma-14.1 {
|
||||
execsql { pragma auto_vacuum = 0 }
|
||||
execsql { pragma page_count }
|
||||
} {0}
|
||||
execsql { pragma page_count; pragma main.page_count }
|
||||
} {0 0}
|
||||
|
||||
do_test pragma-14.2 {
|
||||
execsql {
|
||||
CREATE TABLE abc(a, b, c);
|
||||
PRAGMA page_count;
|
||||
PRAGMA main.page_count;
|
||||
PRAGMA temp.page_count;
|
||||
}
|
||||
} {2}
|
||||
} {2 2 0}
|
||||
do_test pragma-14.2uc {
|
||||
execsql {pragma PAGE_COUNT}
|
||||
} {2}
|
||||
@@ -1701,23 +1803,90 @@ do_test 23.1 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d);
|
||||
CREATE INDEX i1 ON t1(b,c);
|
||||
CREATE INDEX i2 ON t1(c,d);
|
||||
CREATE INDEX i2x ON t1(d COLLATE nocase, c DESC);
|
||||
CREATE TABLE t2(x INTEGER REFERENCES t1);
|
||||
}
|
||||
db2 eval {SELECT name FROM sqlite_master}
|
||||
} {t1 i1 i2 t2}
|
||||
do_test 23.2 {
|
||||
} {t1 i1 i2 i2x t2}
|
||||
do_test 23.2a {
|
||||
db eval {
|
||||
DROP INDEX i2;
|
||||
CREATE INDEX i2 ON t1(c,d,b);
|
||||
}
|
||||
db2 eval {PRAGMA index_info(i2)}
|
||||
} {0 2 c 1 3 d 2 1 b}
|
||||
capture_pragma db2 out {PRAGMA index_info(i2)}
|
||||
db2 eval {SELECT cid, name, '|' FROM out ORDER BY seqno}
|
||||
} {2 c | 3 d | 1 b |}
|
||||
|
||||
# EVIDENCE-OF: R-44874-46325 PRAGMA database.index_xinfo(index-name);
|
||||
# This pragma returns information about every column in an index.
|
||||
#
|
||||
# EVIDENCE-OF: R-45970-35618 Unlike this index_info pragma, this pragma
|
||||
# returns information about every column in the index, not just the key
|
||||
# columns.
|
||||
#
|
||||
do_test 23.2b {
|
||||
capture_pragma db2 out {PRAGMA index_xinfo(i2)}
|
||||
db2 eval {SELECT cid, name, "desc", coll, "key", '|' FROM out ORDER BY seqno}
|
||||
} {2 c 0 BINARY 1 | 3 d 0 BINARY 1 | 1 b 0 BINARY 1 | -1 {} 0 BINARY 0 |}
|
||||
|
||||
# (The first column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-00197-14279 The rank of the column within the index. (0
|
||||
# means left-most. Key columns come before auxiliary columns.)
|
||||
#
|
||||
# (The second column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-40889-06838 The rank of the column within the table
|
||||
# being indexed, or -1 if the index-column is the rowid of the table
|
||||
# being indexed.
|
||||
#
|
||||
# (The third column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-22751-28901 The name of the column being indexed, or
|
||||
# NULL if the index-column is the rowid of the table being indexed.
|
||||
#
|
||||
# (The fourth column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-11847-09179 1 if the index-column is sorted in reverse
|
||||
# (DESC) order by the index and 0 otherwise.
|
||||
#
|
||||
# (The fifth column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-15313-19540 The name for the collating sequence used to
|
||||
# compare values in the index-column.
|
||||
#
|
||||
# (The sixth column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-14310-64553 1 if the index-column is a key column and 0
|
||||
# if the index-column is an auxiliary column.
|
||||
#
|
||||
do_test 23.2c {
|
||||
db2 eval {PRAGMA index_xinfo(i2)}
|
||||
} {0 2 c 0 BINARY 1 1 3 d 0 BINARY 1 2 1 b 0 BINARY 1 3 -1 {} 0 BINARY 0}
|
||||
do_test 23.2d {
|
||||
db2 eval {PRAGMA index_xinfo(i2x)}
|
||||
} {0 3 d 0 nocase 1 1 2 c 1 BINARY 1 2 -1 {} 0 BINARY 0}
|
||||
|
||||
# EVIDENCE-OF: R-63500-32024 PRAGMA database.index_list(table-name);
|
||||
# This pragma returns one row for each index associated with the given
|
||||
# table.
|
||||
#
|
||||
# (The first column of output from PRAGMA index_list is...)
|
||||
# EVIDENCE-OF: R-02753-24748 A sequence number assigned to each index
|
||||
# for internal tracking purposes.
|
||||
#
|
||||
# (The second column of output from PRAGMA index_list is...)
|
||||
# EVIDENCE-OF: R-35496-03635 The name of the index.
|
||||
#
|
||||
# (The third column of output from PRAGMA index_list is...)
|
||||
# EVIDENCE-OF: R-57301-64506 "1" if the index is UNIQUE and "0" if not.
|
||||
#
|
||||
# (The fourth column of output from PRAGMA index_list is...)
|
||||
# EVIDENCE-OF: R-36609-39554 "c" if the index was created by a CREATE
|
||||
# INDEX statement, "u" if the index was created by a UNIQUE constraint,
|
||||
# or "pk" if the index was created by a PRIMARY KEY constraint.
|
||||
#
|
||||
do_test 23.3 {
|
||||
db eval {
|
||||
CREATE INDEX i3 ON t1(d,b,c);
|
||||
}
|
||||
db2 eval {PRAGMA index_list(t1)}
|
||||
} {0 i3 0 1 i2 0 2 i1 0}
|
||||
capture_pragma db2 out {PRAGMA index_list(t1)}
|
||||
db2 eval {SELECT seq, name, "unique", origin, '|' FROM out ORDER BY seq}
|
||||
} {0 i3 0 c | 1 i2 0 c | 2 i2x 0 c | 3 i1 0 c |}
|
||||
do_test 23.4 {
|
||||
db eval {
|
||||
ALTER TABLE t1 ADD COLUMN e;
|
||||
|
||||
@@ -39,6 +39,10 @@ delete_file test3.db test3.db-journal
|
||||
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
|
||||
db eval {PRAGMA auto_vacuum=0}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-17887-14874 PRAGMA database.freelist_count; Return the
|
||||
# number of unused pages in the database file.
|
||||
#
|
||||
do_test pragma2-1.1 {
|
||||
execsql {
|
||||
PRAGMA freelist_count;
|
||||
|
||||
@@ -472,6 +472,18 @@ do_test printf-1.16.7 {
|
||||
sqlite3_mprintf_int {abc: (%#6d) (%#6x) (%#6o) :xyz}\
|
||||
0xff676981 0xff676981 0xff676981
|
||||
} {abc: (-9999999) (0xff676981) (037731664601) :xyz}
|
||||
do_test printf-1.17.1 {
|
||||
sqlite3_mprintf_int {abd: %2147483647d %2147483647x %2147483647o} 1 1 1
|
||||
} {}
|
||||
do_test printf-1.17.2 {
|
||||
sqlite3_mprintf_int {abd: %*d %x} 2147483647 1 1
|
||||
} {}
|
||||
do_test printf-1.17.3 {
|
||||
sqlite3_mprintf_int {abd: %*d %x} -2147483648 1 1
|
||||
} {abd: 1 1}
|
||||
do_test printf-1.17.4 {
|
||||
sqlite3_mprintf_int {abd: %.2147483648d %x %x} 1 1 1
|
||||
} {/.*/}
|
||||
do_test printf-2.1.1.1 {
|
||||
sqlite3_mprintf_double {abc: (%*.*f) :xyz} 1 1 0.001
|
||||
} {abc: (0.0) :xyz}
|
||||
@@ -526,6 +538,9 @@ do_test printf-2.1.2.8 {
|
||||
do_test printf-2.1.2.9 {
|
||||
sqlite3_mprintf_double {abc: %d %d (%1.1g) :xyz} 1 1 1.0e-20
|
||||
} {abc: 1 1 (1e-20) :xyz}
|
||||
do_test printf-2.1.2.10 {
|
||||
sqlite3_mprintf_double {abc: %*.*f} 2000000000 1000000000 1.0e-20
|
||||
} {abc: }
|
||||
do_test printf-2.1.3.1 {
|
||||
sqlite3_mprintf_double {abc: (%*.*f) :xyz} 1 1 1.0
|
||||
} {abc: (1.0) :xyz}
|
||||
@@ -3466,6 +3481,15 @@ do_test printf-3.5 {
|
||||
do_test printf-3.6 {
|
||||
sqlite3_mprintf_str {%d %d A String: (%-30s)} 1 2 {This is the string}
|
||||
} [format {%d %d A String: (%-30s)} 1 2 {This is the string}]
|
||||
do_test printf-3.7 {
|
||||
sqlite3_mprintf_str {%d A String: (%*s)} 1 2147483647 {This is the string}
|
||||
} []
|
||||
do_test printf-3.8 {
|
||||
sqlite3_mprintf_str {%d A String: (%*s)} 1 -2147483648 {This is the string}
|
||||
} {1 A String: (This is the string)}
|
||||
do_test printf-3.9 {
|
||||
sqlite3_mprintf_str {%d A String: (%.*s)} 1 -2147483648 {This is the string}
|
||||
} {1 A String: (This is the string)}
|
||||
do_test snprintf-3.11 {
|
||||
sqlite3_snprintf_str 2 {x%d %d %s} 10 10 {This is the string}
|
||||
} {x}
|
||||
@@ -3685,6 +3709,9 @@ do_test printf-13.5 {
|
||||
do_test printf-13.6 {
|
||||
sqlite3_mprintf_hexdouble %.20f fff8000000000000
|
||||
} {NaN}
|
||||
do_test printf-13.7 {
|
||||
sqlite3_mprintf_hexdouble %2147483648.10000f 4693b8b5b5056e17
|
||||
} {/100000000000000000000000000000000.00/}
|
||||
|
||||
do_test printf-14.1 {
|
||||
sqlite3_mprintf_str {abc-%y-123} 0 0 {not used}
|
||||
|
||||
@@ -58,6 +58,9 @@ do_execsql_test printf2-1.10 {
|
||||
do_execsql_test printf2-1.11 {
|
||||
SELECT printf('%lld%n',314159.2653,'hi');
|
||||
} {314159}
|
||||
do_execsql_test printf2-1.12 {
|
||||
SELECT printf('%n',0);
|
||||
} {{}}
|
||||
|
||||
# EVIDENCE-OF: R-17002-27534 The %z format is interchangeable with %s.
|
||||
#
|
||||
|
||||
@@ -32,6 +32,11 @@ do_test rdonly-1.1 {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1}
|
||||
|
||||
# EVIDENCE-OF: R-29639-16887 The sqlite3_db_readonly(D,N) interface
|
||||
# returns 1 if the database N of connection D is read-only, 0 if it is
|
||||
# read/write, or -1 if N is not the name of a database on connection D.
|
||||
#
|
||||
do_test rdonly-1.1.1 {
|
||||
sqlite3_db_readonly db main
|
||||
} {0}
|
||||
|
||||
+87
-11
@@ -14,16 +14,19 @@ optional) are:
|
||||
--config CONFIGNAME (Run only CONFIGNAME)
|
||||
--quick (Run "veryquick.test" only)
|
||||
--veryquick (Run "make smoketest" only)
|
||||
--msvc (Use MSVC as the compiler)
|
||||
--buildonly (Just build testfixture - do not run)
|
||||
--dryrun (Print what would have happened)
|
||||
--info (Show diagnostic info)
|
||||
--with-tcl=DIR (Use TCL build at DIR)
|
||||
|
||||
The default value for --srcdir is the parent of the directory holding
|
||||
this script.
|
||||
|
||||
The script determines the default value for --platform using the
|
||||
$tcl_platform(os) and $tcl_platform(machine) variables. Supported
|
||||
platforms are "Linux-x86", "Linux-x86_64" and "Darwin-i386".
|
||||
$tcl_platform(os) and $tcl_platform(machine) variables. Supported
|
||||
platforms are "Linux-x86", "Linux-x86_64", "Darwin-i386",
|
||||
"Darwin-x86_64", "Windows NT-intel", and "Windows NT-amd64".
|
||||
|
||||
Every test begins with a fresh run of the configure script at the top
|
||||
of the SQLite source tree.
|
||||
@@ -108,6 +111,13 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_STAT4
|
||||
-DSQLITE_MAX_ATTACHED=125
|
||||
}
|
||||
"Fast-One" {
|
||||
-O6
|
||||
-DSQLITE_ENABLE_FTS4=1
|
||||
-DSQLITE_ENABLE_RTREE=1
|
||||
-DSQLITE_ENABLE_STAT4
|
||||
-DSQLITE_MAX_ATTACHED=125
|
||||
}
|
||||
"Device-One" {
|
||||
-O2
|
||||
-DSQLITE_DEBUG=1
|
||||
@@ -197,6 +207,8 @@ array set ::Configs [strip_comments {
|
||||
Fail2 {-O0}
|
||||
Fail3 {-O0}
|
||||
Fail4 {-O0}
|
||||
FuzzFail1 {-O0}
|
||||
FuzzFail2 {-O0}
|
||||
}]
|
||||
|
||||
array set ::Platforms [strip_comments {
|
||||
@@ -212,6 +224,7 @@ array set ::Platforms [strip_comments {
|
||||
"No-lookaside" test
|
||||
"Devkit" test
|
||||
"Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test}
|
||||
"Fast-One" fuzzoomtest
|
||||
"Valgrind" valgrindtest
|
||||
"Default" "threadtest fulltest"
|
||||
"Device-One" fulltest
|
||||
@@ -238,6 +251,10 @@ array set ::Platforms [strip_comments {
|
||||
"Default" "mptest fulltestonly"
|
||||
"Have-Not" test
|
||||
}
|
||||
"Windows NT-amd64" {
|
||||
"Default" "mptest fulltestonly"
|
||||
"Have-Not" test
|
||||
}
|
||||
|
||||
# The Failure-Detection platform runs various tests that deliberately
|
||||
# fail. This is used as a test of this script to verify that this script
|
||||
@@ -249,6 +266,8 @@ array set ::Platforms [strip_comments {
|
||||
Fail2 "TEST_FAILURE=2 valgrindtest"
|
||||
Fail3 "TEST_FAILURE=3 valgrindtest"
|
||||
Fail4 "TEST_FAILURE=4 test"
|
||||
FuzzFail1 "TEST_FAILURE=5 test"
|
||||
FuzzFail2 "TEST_FAILURE=5 valgrindtest"
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -296,6 +315,13 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} {
|
||||
set errmsg $msg
|
||||
}
|
||||
}
|
||||
if {[regexp {fatal error +(.*)} $line all msg]} {
|
||||
incr ::NERRCASE
|
||||
if {$rc==0} {
|
||||
set rc 1
|
||||
set errmsg $msg
|
||||
}
|
||||
}
|
||||
if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
|
||||
incr ::NERRCASE
|
||||
if {$rc==0} {
|
||||
@@ -314,7 +340,13 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} {
|
||||
}
|
||||
}
|
||||
close $fd
|
||||
if {!$seen} {
|
||||
if {$::BUILDONLY} {
|
||||
if {$rc==0} {
|
||||
set errmsg "Build complete"
|
||||
} else {
|
||||
set errmsg "Build failed"
|
||||
}
|
||||
} elseif {!$seen} {
|
||||
set rc 1
|
||||
set errmsg "Test did not complete"
|
||||
if {[file readable core]} {
|
||||
@@ -329,10 +361,10 @@ proc run_test_suite {name testtarget config} {
|
||||
# CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
|
||||
# CFLAGS is only passed to gcc.
|
||||
#
|
||||
set cflags "-g"
|
||||
set cflags [expr {$::MSVC ? "-Zi" : "-g"}]
|
||||
set opts ""
|
||||
set title ${name}($testtarget)
|
||||
set configOpts ""
|
||||
set configOpts $::WITHTCL
|
||||
|
||||
regsub -all {#[^\n]*\n} $config \n config
|
||||
foreach arg $config {
|
||||
@@ -349,7 +381,14 @@ proc run_test_suite {name testtarget config} {
|
||||
|
||||
set cflags [join $cflags " "]
|
||||
set opts [join $opts " "]
|
||||
append opts " -DSQLITE_NO_SYNC=1 -DHAVE_USLEEP"
|
||||
append opts " -DSQLITE_NO_SYNC=1"
|
||||
|
||||
# Some configurations already set HAVE_USLEEP; in that case, skip it.
|
||||
#
|
||||
if {![regexp { -DHAVE_USLEEP$} $opts]
|
||||
&& ![regexp { -DHAVE_USLEEP[ =]+} $opts]} {
|
||||
append opts " -DHAVE_USLEEP=1"
|
||||
}
|
||||
|
||||
# Set the sub-directory to use.
|
||||
#
|
||||
@@ -390,10 +429,10 @@ proc run_test_suite {name testtarget config} {
|
||||
if {$rc} {
|
||||
puts " FAIL $tm"
|
||||
incr ::NERR
|
||||
if {$errmsg!=""} {puts " $errmsg"}
|
||||
} else {
|
||||
puts " Ok $tm"
|
||||
}
|
||||
if {$errmsg!=""} {puts " $errmsg"}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,6 +440,7 @@ proc run_test_suite {name testtarget config} {
|
||||
# the current platform, which may be Windows (via MinGW, etc).
|
||||
#
|
||||
proc configureCommand {opts} {
|
||||
if {$::MSVC} return [list]; # This is not needed for MSVC.
|
||||
set result [list trace_cmd exec]
|
||||
if {$::tcl_platform(platform)=="windows"} {
|
||||
lappend result sh
|
||||
@@ -414,7 +454,14 @@ proc configureCommand {opts} {
|
||||
# specified targets, compiler flags, and options.
|
||||
#
|
||||
proc makeCommand { targets cflags opts } {
|
||||
set result [list trace_cmd exec make clean]
|
||||
set result [list trace_cmd exec]
|
||||
if {$::MSVC} {
|
||||
set nmakeDir [file nativename $::SRCDIR]
|
||||
set nmakeFile [file join $nmakeDir Makefile.msc]
|
||||
lappend result nmake /f $nmakeFile TOP=$nmakeDir clean
|
||||
} else {
|
||||
lappend result make clean
|
||||
}
|
||||
foreach target $targets {
|
||||
lappend result $target
|
||||
}
|
||||
@@ -443,10 +490,12 @@ proc trace_cmd {args} {
|
||||
proc process_options {argv} {
|
||||
set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]]
|
||||
set ::QUICK 0
|
||||
set ::MSVC 0
|
||||
set ::BUILDONLY 0
|
||||
set ::DRYRUN 0
|
||||
set ::EXEC exec
|
||||
set ::TRACE 0
|
||||
set ::WITHTCL {}
|
||||
set config {}
|
||||
set platform $::tcl_platform(os)-$::tcl_platform(machine)
|
||||
|
||||
@@ -476,6 +525,10 @@ proc process_options {argv} {
|
||||
set config [lindex $argv $i]
|
||||
}
|
||||
|
||||
-msvc {
|
||||
set ::MSVC 1
|
||||
}
|
||||
|
||||
-buildonly {
|
||||
set ::BUILDONLY 1
|
||||
}
|
||||
@@ -494,6 +547,7 @@ proc process_options {argv} {
|
||||
puts " --platform [list $platform]"
|
||||
puts " --config [list $config]"
|
||||
if {$::QUICK} {puts " --quick"}
|
||||
if {$::MSVC} {puts " --msvc"}
|
||||
if {$::BUILDONLY} {puts " --buildonly"}
|
||||
if {$::DRYRUN} {puts " --dryrun"}
|
||||
if {$::TRACE} {puts " --trace"}
|
||||
@@ -507,7 +561,19 @@ proc process_options {argv} {
|
||||
}
|
||||
exit
|
||||
}
|
||||
-g -
|
||||
|
||||
-g {
|
||||
if {$::MSVC} {
|
||||
lappend ::EXTRACONFIG -Zi
|
||||
} else {
|
||||
lappend ::EXTRACONFIG [lindex $argv $i]
|
||||
}
|
||||
}
|
||||
|
||||
-with-tcl=* {
|
||||
set ::WITHTCL -$x
|
||||
}
|
||||
|
||||
-D* -
|
||||
-O* -
|
||||
-enable-* -
|
||||
@@ -547,6 +613,7 @@ proc process_options {argv} {
|
||||
puts -nonewline "Flags:"
|
||||
if {$::DRYRUN} {puts -nonewline " --dryrun"}
|
||||
if {$::BUILDONLY} {puts -nonewline " --buildonly"}
|
||||
if {$::MSVC} {puts -nonewline " --msvc"}
|
||||
switch -- $::QUICK {
|
||||
1 {puts -nonewline " --quick"}
|
||||
2 {puts -nonewline " --veryquick"}
|
||||
@@ -570,12 +637,20 @@ proc main {argv} {
|
||||
set ::SQLITE_VERSION {}
|
||||
set STARTTIME [clock seconds]
|
||||
foreach {zConfig target} $::CONFIGLIST {
|
||||
if {$::MSVC && ($zConfig eq "Sanitize" || "checksymbols" in $target
|
||||
|| "valgrindtest" in $target)} {
|
||||
puts "Skipping $zConfig / $target for MSVC..."
|
||||
continue
|
||||
}
|
||||
if {$target ne "checksymbols"} {
|
||||
switch -- $::QUICK {
|
||||
1 {set target test}
|
||||
2 {set target smoketest}
|
||||
}
|
||||
if {$::BUILDONLY} {set target testfixture}
|
||||
if {$::BUILDONLY} {
|
||||
set target testfixture
|
||||
if {$::MSVC} {append target .exe}
|
||||
}
|
||||
}
|
||||
set config_options [concat $::Configs($zConfig) $::EXTRACONFIG]
|
||||
|
||||
@@ -586,10 +661,11 @@ proc main {argv} {
|
||||
# it and run veryquick.test. If it did not include the SQLITE_DEBUG option
|
||||
# add it and run veryquick.test.
|
||||
if {$target!="checksymbols" && $target!="valgrindtest"
|
||||
&& !$::BUILDONLY && $::QUICK<2} {
|
||||
&& $target!="fuzzoomtest" && !$::BUILDONLY && $::QUICK<2} {
|
||||
set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]
|
||||
set xtarget $target
|
||||
regsub -all {fulltest[a-z]*} $xtarget test xtarget
|
||||
regsub -all {fuzzoomtest} $xtarget fuzztest xtarget
|
||||
if {$debug_idx < 0} {
|
||||
incr NTEST
|
||||
append config_options " -DSQLITE_DEBUG=1"
|
||||
|
||||
@@ -11,10 +11,12 @@
|
||||
#
|
||||
# This file tests features of the name resolver (the component that
|
||||
# figures out what identifiers in the SQL statement refer to) that
|
||||
# were fixed by ticket [2500cdb9be]
|
||||
# were fixed by ticket [2500cdb9be].
|
||||
#
|
||||
# See also tickets [1c69be2daf] and [f617ea3125] from 2013-08-14.
|
||||
#
|
||||
# Also a fuzzer-discovered problem on 2015-04-23.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -201,6 +203,12 @@ do_execsql_test resolver01-6.3 {
|
||||
GROUP BY lower(name);
|
||||
} {1 {} 1 {}}
|
||||
|
||||
do_execsql_test resolver01-7.1 {
|
||||
SELECT 2 AS x WHERE (SELECT x AS y WHERE 3>y);
|
||||
} {2}
|
||||
do_execsql_test resolver01-7.2 {
|
||||
SELECT 2 AS x WHERE (SELECT x AS y WHERE 1>y);
|
||||
} {}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -307,6 +307,9 @@ do_test select1-4.4 {
|
||||
set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg]
|
||||
lappend v $msg
|
||||
} {1 {misuse of aggregate: min()}}
|
||||
do_catchsql_test select1-4.5 {
|
||||
INSERT INTO test1(f1) SELECT f1 FROM test1 ORDER BY min(f1);
|
||||
} {1 {misuse of aggregate: min()}}
|
||||
|
||||
# The restriction not allowing constants in the ORDER BY clause
|
||||
# has been removed. See ticket #1768
|
||||
@@ -1072,5 +1075,10 @@ if {[db one {PRAGMA locking_mode}]=="normal"} {
|
||||
do_test select1-16.1 {
|
||||
catchsql {SELECT 1 FROM (SELECT *)}
|
||||
} {1 {no tables specified}}
|
||||
|
||||
# 2015-04-17: assertion fix.
|
||||
do_catchsql_test select1-16.2 {
|
||||
SELECT 1 FROM sqlite_master LIMIT 1,#1;
|
||||
} {1 {near "#1": syntax error}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -105,6 +105,10 @@ ifcapable subquery {
|
||||
}
|
||||
} {0 1 2 2 3 3 3 3}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-02644-22131 In a compound SELECT statement, only the
|
||||
# last or right-most simple SELECT may have an ORDER BY clause.
|
||||
#
|
||||
do_test select4-1.3 {
|
||||
set v [catch {execsql {
|
||||
SELECT DISTINCT log FROM t1 ORDER BY log
|
||||
@@ -114,6 +118,10 @@ do_test select4-1.3 {
|
||||
}} msg]
|
||||
lappend v $msg
|
||||
} {1 {ORDER BY clause should come after UNION ALL not before}}
|
||||
do_catchsql_test select4-1.4 {
|
||||
SELECT (VALUES(0) INTERSECT SELECT(0) UNION SELECT(0) ORDER BY 1 UNION
|
||||
SELECT 0 UNION SELECT 0 ORDER BY 1);
|
||||
} {1 {ORDER BY clause should come after UNION not before}}
|
||||
|
||||
# Union operator
|
||||
#
|
||||
@@ -144,6 +152,15 @@ do_test select4-2.3 {
|
||||
}} msg]
|
||||
lappend v $msg
|
||||
} {1 {ORDER BY clause should come after UNION not before}}
|
||||
do_test select4-2.4 {
|
||||
set v [catch {execsql {
|
||||
SELECT 0 ORDER BY (SELECT 0) UNION SELECT 0;
|
||||
}} msg]
|
||||
lappend v $msg
|
||||
} {1 {ORDER BY clause should come after UNION not before}}
|
||||
do_execsql_test select4-2.5 {
|
||||
SELECT 123 AS x ORDER BY (SELECT x ORDER BY 1);
|
||||
} {123}
|
||||
|
||||
# Except operator
|
||||
#
|
||||
@@ -260,6 +277,16 @@ do_test select4-4.3 {
|
||||
}} msg]
|
||||
lappend v $msg
|
||||
} {1 {ORDER BY clause should come after INTERSECT not before}}
|
||||
do_catchsql_test select4-4.4 {
|
||||
SELECT 3 IN (
|
||||
SELECT 0 ORDER BY 1
|
||||
INTERSECT
|
||||
SELECT 1
|
||||
INTERSECT
|
||||
SELECT 2
|
||||
ORDER BY 1
|
||||
);
|
||||
} {1 {ORDER BY clause should come after INTERSECT not before}}
|
||||
|
||||
# Various error messages while processing UNION or INTERSECT
|
||||
#
|
||||
@@ -795,6 +822,11 @@ do_test select4-11.15 {
|
||||
SELECT x FROM t2
|
||||
}
|
||||
} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
|
||||
do_test select4-11.16 {
|
||||
catchsql {
|
||||
INSERT INTO t2(rowid) VALUES(2) UNION SELECT 3,4 UNION SELECT 5,6 ORDER BY 1;
|
||||
}
|
||||
} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
|
||||
|
||||
do_test select4-12.1 {
|
||||
sqlite3 db2 :memory:
|
||||
@@ -859,5 +891,23 @@ do_execsql_test select4-14.8 {
|
||||
do_execsql_test select4-14.9 {
|
||||
SELECT * FROM t14 UNION ALL VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3);
|
||||
} {1 2 3 4 5 6 3 2 1 2 3 1 1 2 3 2 1 3}
|
||||
do_execsql_test select4-14.10 {
|
||||
SELECT (VALUES(1),(2),(3),(4))
|
||||
} {1}
|
||||
do_execsql_test select4-14.11 {
|
||||
SELECT (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4)
|
||||
} {1}
|
||||
do_execsql_test select4-14.12 {
|
||||
VALUES(1) UNION VALUES(2);
|
||||
} {1 2}
|
||||
do_execsql_test select4-14.13 {
|
||||
VALUES(1),(2),(3) EXCEPT VALUES(2);
|
||||
} {1 3}
|
||||
do_execsql_test select4-14.14 {
|
||||
VALUES(1),(2),(3) EXCEPT VALUES(1),(3);
|
||||
} {2}
|
||||
do_execsql_test select4-14.15 {
|
||||
SELECT * FROM (SELECT 123), (SELECT 456) ON likely(0 OR 1) OR 0;
|
||||
} {123 456}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -557,5 +557,61 @@ do_catchsql_test 10.8 {
|
||||
)
|
||||
} $err
|
||||
|
||||
# 2015-02-09 Ticket [2f7170d73bf9abf80339187aa3677dce3dbcd5ca]
|
||||
# "misuse of aggregate" error if aggregate column from FROM
|
||||
# subquery is used in correlated subquery
|
||||
#
|
||||
do_execsql_test 11.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(w INT, x INT);
|
||||
INSERT INTO t1(w,x)
|
||||
VALUES(1,10),(2,20),(3,30),
|
||||
(2,21),(3,31),
|
||||
(3,32);
|
||||
CREATE INDEX t1wx ON t1(w,x);
|
||||
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(w INT, y VARCHAR(8));
|
||||
INSERT INTO t2(w,y) VALUES(1,'one'),(2,'two'),(3,'three'),(4,'four');
|
||||
CREATE INDEX t2wy ON t2(w,y);
|
||||
|
||||
SELECT cnt, xyz, (SELECT y FROM t2 WHERE w=cnt), '|'
|
||||
FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2)
|
||||
ORDER BY cnt, xyz;
|
||||
} {1 1 one | 2 2 two | 3 3 three |}
|
||||
do_execsql_test 11.2 {
|
||||
SELECT cnt, xyz, lower((SELECT y FROM t2 WHERE w=cnt)), '|'
|
||||
FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2)
|
||||
ORDER BY cnt, xyz;
|
||||
} {1 1 one | 2 2 two | 3 3 three |}
|
||||
do_execsql_test 11.3 {
|
||||
SELECT cnt, xyz, '|'
|
||||
FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2)
|
||||
WHERE (SELECT y FROM t2 WHERE w=cnt)!='two'
|
||||
ORDER BY cnt, xyz;
|
||||
} {1 1 | 3 3 |}
|
||||
do_execsql_test 11.4 {
|
||||
SELECT cnt, xyz, '|'
|
||||
FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2)
|
||||
ORDER BY lower((SELECT y FROM t2 WHERE w=cnt));
|
||||
} {1 1 | 3 3 | 2 2 |}
|
||||
do_execsql_test 11.5 {
|
||||
SELECT cnt, xyz,
|
||||
CASE WHEN (SELECT y FROM t2 WHERE w=cnt)=='two'
|
||||
THEN 'aaa' ELSE 'bbb'
|
||||
END, '|'
|
||||
FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2)
|
||||
ORDER BY +cnt;
|
||||
} {1 1 bbb | 2 2 aaa | 3 3 bbb |}
|
||||
|
||||
do_execsql_test 11.100 {
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t1(x);
|
||||
CREATE TABLE t2(y, z);
|
||||
SELECT ( SELECT y FROM t2 WHERE z = cnt )
|
||||
FROM ( SELECT count(*) AS cnt FROM t1 );
|
||||
} {{}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1375,4 +1375,64 @@ do_execsql_test 4.2.2 {
|
||||
} {/2 . 3 . 4 . 5 . 6 . 7 ./}
|
||||
|
||||
|
||||
proc strip_rnd {explain} {
|
||||
regexp -all {sqlite_sq_[0123456789ABCDEF]*} $explain sqlite_sq
|
||||
}
|
||||
|
||||
proc do_same_test {tn q1 args} {
|
||||
set r2 [strip_rnd [db eval "EXPLAIN $q1"]]
|
||||
set i 1
|
||||
foreach q $args {
|
||||
set tst [subst -nocommands {strip_rnd [db eval "EXPLAIN $q"]}]
|
||||
uplevel do_test $tn.$i [list $tst] [list $r2]
|
||||
incr i
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t8(a, b);
|
||||
CREATE TABLE t9(c, d);
|
||||
} {}
|
||||
|
||||
do_same_test 5.1 {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY a;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY t8.a;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY 1;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY c;
|
||||
} {
|
||||
SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY t9.c;
|
||||
}
|
||||
|
||||
do_same_test 5.2 {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY a COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY t8.a COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY 1 COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY c COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY t9.c COLLATE NOCASE
|
||||
}
|
||||
|
||||
do_same_test 5.3 {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY b, c COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY 2, 1 COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY d, a COLLATE NOCASE
|
||||
} {
|
||||
SELECT a, b FROM t8 EXCEPT SELECT * FROM t9 ORDER BY t9.d, c COLLATE NOCASE
|
||||
} {
|
||||
SELECT * FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY d, t8.a COLLATE NOCASE
|
||||
}
|
||||
|
||||
do_catchsql_test 5.4 {
|
||||
SELECT * FROM t8 UNION SELECT * FROM t9 ORDER BY a+b COLLATE NOCASE
|
||||
} {1 {1st ORDER BY term does not match any column in the result set}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -92,4 +92,9 @@ do_test selectE-2.2 {
|
||||
}
|
||||
} {}
|
||||
|
||||
do_catchsql_test selectE-3.1 {
|
||||
SELECT 1 EXCEPT SELECT 2 ORDER BY 1 COLLATE nocase EXCEPT SELECT 3;
|
||||
} {1 {ORDER BY clause should come after EXCEPT not before}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+109
-6
@@ -406,19 +406,22 @@ do_test shell1-3.11.3 {
|
||||
catchcmd "test.db" ".import FOO BAR BAD"
|
||||
} {1 {Usage: .import FILE TABLE}}
|
||||
|
||||
# .indices ?TABLE? Show names of all indices
|
||||
# If TABLE specified, only show indices for tables
|
||||
# .indexes ?TABLE? Show names of all indexes
|
||||
# If TABLE specified, only show indexes for tables
|
||||
# matching LIKE pattern TABLE.
|
||||
do_test shell1-3.12.1 {
|
||||
catchcmd "test.db" ".indices"
|
||||
catchcmd "test.db" ".indexes"
|
||||
} {0 {}}
|
||||
do_test shell1-3.12.2 {
|
||||
catchcmd "test.db" ".indexes FOO"
|
||||
} {0 {}}
|
||||
do_test shell1-3.12.2-legacy {
|
||||
catchcmd "test.db" ".indices FOO"
|
||||
} {0 {}}
|
||||
do_test shell1-3.12.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".indices FOO BAD"
|
||||
} {1 {Usage: .indices ?LIKE-PATTERN?}}
|
||||
catchcmd "test.db" ".indexes FOO BAD"
|
||||
} {1 {Usage: .indexes ?LIKE-PATTERN?}}
|
||||
|
||||
# .mode MODE ?TABLE? Set output mode where MODE is one of:
|
||||
# ascii Columns/rows delimited by 0x1F and 0x1E
|
||||
@@ -735,6 +738,9 @@ do_test shell1-4.1 {
|
||||
PRAGMA encoding=UTF16;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f');
|
||||
CREATE TABLE t3(x,y);
|
||||
INSERT INTO t3 VALUES(1,null), (2,''), (3,1),
|
||||
(4,2.25), (5,'hello'), (6,x'807f');
|
||||
}
|
||||
catchcmd test.db {.dump}
|
||||
} {0 {PRAGMA foreign_keys=OFF;
|
||||
@@ -746,11 +752,18 @@ INSERT INTO "t1" VALUES(1);
|
||||
INSERT INTO "t1" VALUES(2.25);
|
||||
INSERT INTO "t1" VALUES('hello');
|
||||
INSERT INTO "t1" VALUES(X'807F');
|
||||
CREATE TABLE t3(x,y);
|
||||
INSERT INTO "t3" VALUES(1,NULL);
|
||||
INSERT INTO "t3" VALUES(2,'');
|
||||
INSERT INTO "t3" VALUES(3,1);
|
||||
INSERT INTO "t3" VALUES(4,2.25);
|
||||
INSERT INTO "t3" VALUES(5,'hello');
|
||||
INSERT INTO "t3" VALUES(6,X'807F');
|
||||
COMMIT;}}
|
||||
|
||||
# Test the output of ".mode insert"
|
||||
#
|
||||
do_test shell1-4.2 {
|
||||
do_test shell1-4.2.1 {
|
||||
catchcmd test.db ".mode insert t1\nselect * from t1;"
|
||||
} {0 {INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES('');
|
||||
@@ -759,6 +772,39 @@ INSERT INTO t1 VALUES(2.25);
|
||||
INSERT INTO t1 VALUES('hello');
|
||||
INSERT INTO t1 VALUES(X'807f');}}
|
||||
|
||||
# Test the output of ".mode insert" with headers
|
||||
#
|
||||
do_test shell1-4.2.2 {
|
||||
catchcmd test.db ".mode insert t1\n.headers on\nselect * from t1;"
|
||||
} {0 {INSERT INTO t1(x) VALUES(NULL);
|
||||
INSERT INTO t1(x) VALUES('');
|
||||
INSERT INTO t1(x) VALUES(1);
|
||||
INSERT INTO t1(x) VALUES(2.25);
|
||||
INSERT INTO t1(x) VALUES('hello');
|
||||
INSERT INTO t1(x) VALUES(X'807f');}}
|
||||
|
||||
# Test the output of ".mode insert"
|
||||
#
|
||||
do_test shell1-4.2.3 {
|
||||
catchcmd test.db ".mode insert t3\nselect * from t3;"
|
||||
} {0 {INSERT INTO t3 VALUES(1,NULL);
|
||||
INSERT INTO t3 VALUES(2,'');
|
||||
INSERT INTO t3 VALUES(3,1);
|
||||
INSERT INTO t3 VALUES(4,2.25);
|
||||
INSERT INTO t3 VALUES(5,'hello');
|
||||
INSERT INTO t3 VALUES(6,X'807f');}}
|
||||
|
||||
# Test the output of ".mode insert" with headers
|
||||
#
|
||||
do_test shell1-4.2.4 {
|
||||
catchcmd test.db ".mode insert t3\n.headers on\nselect * from t3;"
|
||||
} {0 {INSERT INTO t3(x,y) VALUES(1,NULL);
|
||||
INSERT INTO t3(x,y) VALUES(2,'');
|
||||
INSERT INTO t3(x,y) VALUES(3,1);
|
||||
INSERT INTO t3(x,y) VALUES(4,2.25);
|
||||
INSERT INTO t3(x,y) VALUES(5,'hello');
|
||||
INSERT INTO t3(x,y) VALUES(6,X'807f');}}
|
||||
|
||||
# Test the output of ".mode tcl"
|
||||
#
|
||||
do_test shell1-4.3 {
|
||||
@@ -815,4 +861,61 @@ do_test shell1-4.6 {
|
||||
";"
|
||||
"$"} 7}
|
||||
|
||||
# Test using arbitrary byte data with the shell via standard input/output.
|
||||
#
|
||||
do_test shell1-5.0 {
|
||||
#
|
||||
# NOTE: Skip NUL byte because it appears to be incompatible with command
|
||||
# shell argument parsing.
|
||||
#
|
||||
for {set i 1} {$i < 256} {incr i} {
|
||||
#
|
||||
# NOTE: Due to how the Tcl [exec] command works (i.e. where it treats
|
||||
# command channels opened for it as textual ones), the carriage
|
||||
# return character (and on Windows, the end-of-file character)
|
||||
# cannot be used here.
|
||||
#
|
||||
if {$i==0x0D || ($tcl_platform(platform)=="windows" && $i==0x1A)} {
|
||||
continue
|
||||
}
|
||||
set hex [format %02X $i]
|
||||
set char [subst \\x$hex]; set oldChar $char
|
||||
set escapes [list]
|
||||
if {$tcl_platform(platform)=="windows"} {
|
||||
#
|
||||
# NOTE: On Windows, we need to escape all the whitespace characters,
|
||||
# the alarm (\a) character, and those with special meaning to
|
||||
# the SQLite shell itself.
|
||||
#
|
||||
set escapes [list \
|
||||
\a \\a \b \\b \t \\t \n \\n \v \\v \f \\f \r \\r \
|
||||
" " "\" \"" \" \\\" ' \"'\" \\ \\\\]
|
||||
} else {
|
||||
#
|
||||
# NOTE: On Unix, we need to escape most of the whitespace characters
|
||||
# and those with special meaning to the SQLite shell itself.
|
||||
# The alarm (\a), backspace (\b), and carriage-return (\r)
|
||||
# characters do not appear to require escaping on Unix. For
|
||||
# the alarm and backspace characters, this is probably due to
|
||||
# differences in the command shell. For the carriage-return,
|
||||
# it is probably due to differences in how Tcl handles command
|
||||
# channel end-of-line translations.
|
||||
#
|
||||
set escapes [list \
|
||||
\t \\t \n \\n \v \\v \f \\f \
|
||||
" " "\" \"" \" \\\" ' \"'\" \\ \\\\]
|
||||
}
|
||||
set char [string map $escapes $char]
|
||||
set x [catchcmdex test.db ".print $char\n"]
|
||||
set code [lindex $x 0]
|
||||
set res [lindex $x 1]
|
||||
if {$code ne "0"} {
|
||||
error "failed with error: $res"
|
||||
}
|
||||
if {$res ne "$oldChar\n"} {
|
||||
error "failed with byte $hex mismatch"
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
+22
-2
@@ -12,12 +12,12 @@
|
||||
# The focus of this file is testing the CLI shell tool.
|
||||
# These tests are specific to the .stats command.
|
||||
#
|
||||
# $Id: shell4.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $
|
||||
#
|
||||
# 2015-03-19: Added tests for .trace
|
||||
|
||||
# Test plan:
|
||||
#
|
||||
# shell4-1.*: Basic tests specific to the "stats" command.
|
||||
# shell4-2.*: Basic tests for ".trace"
|
||||
#
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -113,4 +113,24 @@ SELECT 1;
|
||||
[regexp {Autoindex Inserts} $res]
|
||||
} {1 1 1}
|
||||
|
||||
do_test shell4-2.1 {
|
||||
catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace"
|
||||
} {1 {Usage: .trace FILE|off}}
|
||||
do_test shell4-2.2 {
|
||||
catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace off\n.trace off\n"
|
||||
} {0 {}}
|
||||
do_test shell4-2.3 {
|
||||
catchcmd ":memory:" ".trace stdout\n.trace\n.trace off\n.dump\n"
|
||||
} {/^1 {PRAGMA.*Usage:.*}$/}
|
||||
ifcapable trace {
|
||||
do_test shell4-2.4 {
|
||||
catchcmd ":memory:" ".trace stdout\nCREATE TABLE t1(x);SELECT * FROM t1;"
|
||||
} {0 {CREATE TABLE t1(x);
|
||||
SELECT * FROM t1;}}
|
||||
do_test shell4-2.5 {
|
||||
catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace stdout\nSELECT * FROM t1;"
|
||||
} {0 {SELECT * FROM t1;}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -405,4 +405,34 @@ SELECT * FROM t5;
|
||||
set x
|
||||
} "0 \{\"test 1\"\x1F,test 2<EOL>\x1Etest 3\x1Ftest 4<EOL>\x1E\}"
|
||||
|
||||
do_test shell5-4.1 {
|
||||
forcedelete shell5.csv
|
||||
set fd [open shell5.csv w]
|
||||
puts $fd "1,2,3"
|
||||
puts $fd "4,5"
|
||||
puts $fd "6,7,8"
|
||||
close $fd
|
||||
catchcmd test.db [string trim {
|
||||
.mode csv
|
||||
CREATE TABLE t6(a, b, c);
|
||||
.import shell5.csv t6
|
||||
}]
|
||||
db eval { SELECT * FROM t6 ORDER BY a }
|
||||
} {1 2 3 4 5 {} 6 7 8}
|
||||
|
||||
do_test shell5-4.2 {
|
||||
forcedelete shell5.csv
|
||||
set fd [open shell5.csv w]
|
||||
puts $fd "1,2,3"
|
||||
puts $fd "4,5"
|
||||
puts $fd "6,7,8,9"
|
||||
close $fd
|
||||
catchcmd test.db [string trim {
|
||||
.mode csv
|
||||
CREATE TABLE t7(a, b, c);
|
||||
.import shell5.csv t7
|
||||
}]
|
||||
db eval { SELECT * FROM t7 ORDER BY a }
|
||||
} {1 2 3 4 5 {} 6 7 8}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -24,6 +24,9 @@ do_test shrink-1.1 {
|
||||
INSERT INTO t1 VALUES(randomblob(1000000),1);
|
||||
}
|
||||
set ::baseline sqlite3_memory_used
|
||||
# EVIDENCE-OF: R-58814-63508 The sqlite3_db_release_memory(D) interface
|
||||
# attempts to free as much heap memory as possible from database
|
||||
# connection D.
|
||||
sqlite3_db_release_memory db
|
||||
expr {$::baseline > [sqlite3_memory_used]+500000}
|
||||
} {1}
|
||||
|
||||
@@ -24,6 +24,14 @@ ifcapable !integrityck {
|
||||
return
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-26343-45930 This pragma invokes the
|
||||
# sqlite3_soft_heap_limit64() interface with the argument N, if N is
|
||||
# specified and is a non-negative integer.
|
||||
#
|
||||
# EVIDENCE-OF: R-64451-07163 The soft_heap_limit pragma always returns
|
||||
# the same integer that would be returned by the
|
||||
# sqlite3_soft_heap_limit64(-1) C-language function.
|
||||
#
|
||||
do_test softheap1-1.0 {
|
||||
execsql {PRAGMA soft_heap_limit}
|
||||
} [sqlite3_soft_heap_limit -1]
|
||||
|
||||
+14
-1
@@ -25,7 +25,20 @@ sqlite3 db test.db
|
||||
|
||||
|
||||
# Configure the sorter to use 3 background threads.
|
||||
db eval {PRAGMA threads=3}
|
||||
#
|
||||
# EVIDENCE-OF: R-19249-32353 SQLITE_LIMIT_WORKER_THREADS The maximum
|
||||
# number of auxiliary worker threads that a single prepared statement
|
||||
# may start.
|
||||
#
|
||||
do_test sort4-init001 {
|
||||
db eval {PRAGMA threads=5}
|
||||
sqlite3_limit db SQLITE_LIMIT_WORKER_THREADS -1
|
||||
} {5}
|
||||
do_test sort4-init002 {
|
||||
sqlite3_limit db SQLITE_LIMIT_WORKER_THREADS 3
|
||||
db eval {PRAGMA threads}
|
||||
} {3}
|
||||
|
||||
|
||||
# Minimum number of seconds to run for. If the value is 0, each test
|
||||
# is run exactly once. Otherwise, tests are repeated until the timeout
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ static const char zHelp[] =
|
||||
" --explain Like --sqlonly but with added EXPLAIN keywords\n"
|
||||
" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
|
||||
" --incrvacuum Enable incremenatal vacuum mode\n"
|
||||
" --journalmode M Set the journal_mode to MODE\n"
|
||||
" --journal M Set the journal_mode to M\n"
|
||||
" --key KEY Set the encryption key to KEY\n"
|
||||
" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
|
||||
" --nosync Set PRAGMA synchronous=OFF\n"
|
||||
|
||||
@@ -250,6 +250,9 @@ do_test sqllimits1-4.10.1 {
|
||||
# Test cases sqllimits1-5.* test that the SQLITE_MAX_LENGTH limit
|
||||
# is enforced.
|
||||
#
|
||||
# EVIDENCE-OF: R-61987-00541 SQLITE_LIMIT_LENGTH The maximum size of any
|
||||
# string or BLOB or table row, in bytes.
|
||||
#
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set LARGESIZE 99999
|
||||
@@ -406,6 +409,9 @@ unset strvalue
|
||||
# Test cases sqllimits1-6.* test that the SQLITE_MAX_SQL_LENGTH limit
|
||||
# is enforced.
|
||||
#
|
||||
# EVIDENCE-OF: R-09808-17554 SQLITE_LIMIT_SQL_LENGTH The maximum length
|
||||
# of an SQL statement, in bytes.
|
||||
#
|
||||
do_test sqllimits1-6.1 {
|
||||
sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH 50000
|
||||
set sql "SELECT 1 WHERE 1==1"
|
||||
@@ -567,6 +573,11 @@ do_test sqllimits1-7.7.4 {
|
||||
#--------------------------------------------------------------------
|
||||
# Test cases sqllimits1-8.* test the SQLITE_MAX_COLUMN limit.
|
||||
#
|
||||
# EVIDENCE-OF: R-43996-29471 SQLITE_LIMIT_COLUMN The maximum number of
|
||||
# columns in a table definition or in the result set of a SELECT or the
|
||||
# maximum number of columns in an index or in an ORDER BY or GROUP BY
|
||||
# clause.
|
||||
#
|
||||
set SQLITE_LIMIT_COLUMN 200
|
||||
sqlite3_limit db SQLITE_LIMIT_COLUMN $SQLITE_LIMIT_COLUMN
|
||||
do_test sqllimits1-8.1 {
|
||||
@@ -670,6 +681,9 @@ do_test sqllimits1-8.11 {
|
||||
# limit is enforced. The limit refers to the number of terms in
|
||||
# the expression.
|
||||
#
|
||||
# EVIDENCE-OF: R-12723-08526 SQLITE_LIMIT_EXPR_DEPTH The maximum depth
|
||||
# of the parse tree on any expression.
|
||||
#
|
||||
if {$SQLITE_MAX_EXPR_DEPTH==0} {
|
||||
puts -nonewline stderr "WARNING: Compile with -DSQLITE_MAX_EXPR_DEPTH to run "
|
||||
puts stderr "tests sqllimits1-9.X"
|
||||
@@ -729,6 +743,9 @@ if 0 {
|
||||
# Test the SQLITE_LIMIT_FUNCTION_ARG limit works. Test case names
|
||||
# match the pattern "sqllimits1-11.*".
|
||||
#
|
||||
# EVIDENCE-OF: R-59001-45278 SQLITE_LIMIT_FUNCTION_ARG The maximum
|
||||
# number of arguments on a function.
|
||||
#
|
||||
for {set max 5} {$max<=$SQLITE_MAX_FUNCTION_ARG} {incr max} {
|
||||
do_test sqllimits1-11.$max.1 {
|
||||
set vals [list]
|
||||
@@ -762,6 +779,9 @@ for {set max 5} {$max<=$SQLITE_MAX_FUNCTION_ARG} {incr max} {
|
||||
#--------------------------------------------------------------------
|
||||
# Test cases sqllimits1-12.*: Test the SQLITE_MAX_ATTACHED limit.
|
||||
#
|
||||
# EVIDENCE-OF: R-41778-26203 SQLITE_LIMIT_ATTACHED The maximum number of
|
||||
# attached databases.
|
||||
#
|
||||
ifcapable attach {
|
||||
do_test sqllimits1-12.1 {
|
||||
set max $::SQLITE_MAX_ATTACHED
|
||||
@@ -785,6 +805,9 @@ ifcapable attach {
|
||||
# Test cases sqllimits1-13.*: Check that the SQLITE_MAX_VARIABLE_NUMBER
|
||||
# limit works.
|
||||
#
|
||||
# EVIDENCE-OF: R-42363-29104 SQLITE_LIMIT_VARIABLE_NUMBER The maximum
|
||||
# index number of any parameter in an SQL statement.
|
||||
#
|
||||
do_test sqllimits1-13.1 {
|
||||
set max $::SQLITE_MAX_VARIABLE_NUMBER
|
||||
catchsql "SELECT ?[expr {$max+1}] FROM t1"
|
||||
@@ -806,6 +829,9 @@ do_test sqllimits1-13.2 {
|
||||
# implementation by overriding the like() scalar function bypasses
|
||||
# this limitation.
|
||||
#
|
||||
# EVIDENCE-OF: R-12940-37052 SQLITE_LIMIT_LIKE_PATTERN_LENGTH The
|
||||
# maximum length of the pattern argument to the LIKE or GLOB operators.
|
||||
#
|
||||
# These tests check that the limit is not incorrectly applied to
|
||||
# the left-hand-side of the LIKE operator (the string being tested
|
||||
# against the pattern).
|
||||
|
||||
+8
-2
@@ -166,8 +166,10 @@ sqlite3 db test.db
|
||||
register_dbstat_vtab db
|
||||
do_execsql_test stat-5.1 {
|
||||
PRAGMA auto_vacuum = OFF;
|
||||
CREATE VIRTUAL TABLE temp.stat USING dbstat;
|
||||
CREATE TABLE t1(x);
|
||||
CREATE TABLE tx(y);
|
||||
ATTACH ':memory:' AS aux1;
|
||||
CREATE VIRTUAL TABLE temp.stat USING dbstat(aux1);
|
||||
CREATE TABLE aux1.t1(x);
|
||||
INSERT INTO t1 VALUES(zeroblob(1513));
|
||||
INSERT INTO t1 VALUES(zeroblob(1514));
|
||||
SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
|
||||
@@ -178,4 +180,8 @@ do_execsql_test stat-5.1 {
|
||||
t1 /001+000000 4 overflow 0 1020 0 0 \
|
||||
]
|
||||
|
||||
do_catchsql_test stat-6.1 {
|
||||
CREATE VIRTUAL TABLE temp.s2 USING dbstat(mainx);
|
||||
} {1 {no such database: mainx}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# 2015 April 28
|
||||
#
|
||||
# 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/malloc_common.tcl
|
||||
set testprefix statfault
|
||||
|
||||
ifcapable !vtab||!compound {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
register_dbstat_vtab db
|
||||
do_execsql_test statfault-1 {
|
||||
CREATE TABLE t1(a, b UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, randomblob(500));
|
||||
INSERT INTO t1 VALUES(randomblob(500), 1);
|
||||
INSERT INTO t1 VALUES(2, randomblob(250));
|
||||
INSERT INTO t1 VALUES(randomblob(250), 2);
|
||||
CREATE VIRTUAL TABLE sss USING dbstat;
|
||||
} {}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 1 -faults * -prep {
|
||||
faultsim_restore_and_reopen
|
||||
register_dbstat_vtab db
|
||||
execsql { SELECT 1 FROM sqlite_master LIMIT 1 }
|
||||
} -body {
|
||||
execsql { SELECT count(*) FROM sss }
|
||||
} -test {
|
||||
faultsim_test_result {0 8}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -584,4 +584,14 @@ do_test subquery-7.11 {
|
||||
} {30303}
|
||||
} ;############# Disabled
|
||||
|
||||
# 2015-04-21.
|
||||
# Verify that a memory leak in the table column type and collation analysis
|
||||
# is plugged.
|
||||
#
|
||||
do_execsql_test subquery-8.1 {
|
||||
CREATE TABLE t8(a TEXT, b INT);
|
||||
SELECT (SELECT 0 FROM (SELECT * FROM t1)) AS x WHERE x;
|
||||
SELECT (SELECT 0 FROM (SELECT * FROM (SELECT 0))) AS x WHERE x;
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -272,6 +272,25 @@ do_test table-5.2.1 {
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test table-5.2.2 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t0(a,b);
|
||||
CREATE INDEX t ON t0(a);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE TABLE a.b(a UNIQUE';
|
||||
BEGIN;
|
||||
CREATE TABLE t1(x);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS t99;
|
||||
}
|
||||
} {}
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
|
||||
# Make sure an EXPLAIN does not really create a new table
|
||||
#
|
||||
do_test table-5.3 {
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ do_test tcl-1.14 {
|
||||
do_test tcl-1.15 {
|
||||
set v [catch {db function} msg]
|
||||
lappend v $msg
|
||||
} {1 {wrong # args: should be "db function NAME [-argcount N] SCRIPT"}}
|
||||
} {1 {wrong # args: should be "db function NAME ?SWITCHES? SCRIPT"}}
|
||||
do_test tcl-1.16 {
|
||||
set v [catch {db last_insert_rowid xyz} msg]
|
||||
lappend v $msg
|
||||
|
||||
@@ -666,6 +666,15 @@ proc do_test {name cmd expected} {
|
||||
flush stdout
|
||||
}
|
||||
|
||||
proc dumpbytes {s} {
|
||||
set r ""
|
||||
for {set i 0} {$i < [string length $s]} {incr i} {
|
||||
if {$i > 0} {append r " "}
|
||||
append r [format %02X [scan [string index $s $i] %c]]
|
||||
}
|
||||
return $r
|
||||
}
|
||||
|
||||
proc catchcmd {db {cmd ""}} {
|
||||
global CLI
|
||||
set out [open cmds.txt w]
|
||||
@@ -676,6 +685,30 @@ proc catchcmd {db {cmd ""}} {
|
||||
list $rc $msg
|
||||
}
|
||||
|
||||
proc catchcmdex {db {cmd ""}} {
|
||||
global CLI
|
||||
set out [open cmds.txt w]
|
||||
fconfigure $out -encoding binary -translation binary
|
||||
puts -nonewline $out $cmd
|
||||
close $out
|
||||
set line "exec -keepnewline -- $CLI $db < cmds.txt"
|
||||
set chans [list stdin stdout stderr]
|
||||
foreach chan $chans {
|
||||
catch {
|
||||
set modes($chan) [fconfigure $chan]
|
||||
fconfigure $chan -encoding binary -translation binary -buffering none
|
||||
}
|
||||
}
|
||||
set rc [catch { eval $line } msg]
|
||||
foreach chan $chans {
|
||||
catch {
|
||||
eval fconfigure [list $chan] $modes($chan)
|
||||
}
|
||||
}
|
||||
# puts [dumpbytes $msg]
|
||||
list $rc $msg
|
||||
}
|
||||
|
||||
proc filepath_normalize {p} {
|
||||
# test cases should be written to assume "unix"-like file paths
|
||||
if {$::tcl_platform(platform)!="unix"} {
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ ifcapable fts3 {
|
||||
INSERT INTO x1(x1) VALUES('optimize');
|
||||
} {
|
||||
"INSERT INTO x1(x1) VALUES('optimize');"
|
||||
"-- SELECT DISTINCT level / (1024 * ?) FROM 'main'.'x1_segdir'"
|
||||
"-- SELECT ? UNION SELECT level / (1024 * ?) FROM 'main'.'x1_segdir'"
|
||||
"-- SELECT idx, start_block, leaves_end_block, end_block, root FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?ORDER BY level DESC, idx ASC"
|
||||
"-- SELECT max(level) FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?"
|
||||
"-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)"
|
||||
|
||||
@@ -712,4 +712,20 @@ do_test trigger1-16.7 {
|
||||
}
|
||||
} {1 {the INDEXED BY clause is not allowed on UPDATE or DELETE statements within triggers}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that bug [34cd55d68e0e6e7c] has been fixed.
|
||||
#
|
||||
do_execsql_test trigger1-17.0 {
|
||||
CREATE TABLE t17a(ii INT);
|
||||
CREATE TABLE t17b(tt TEXT PRIMARY KEY, ss);
|
||||
CREATE TRIGGER t17a_ai AFTER INSERT ON t17a BEGIN
|
||||
INSERT INTO t17b(tt) VALUES(new.ii);
|
||||
END;
|
||||
CREATE TRIGGER t17b_ai AFTER INSERT ON t17b BEGIN
|
||||
UPDATE t17b SET ss = 4;
|
||||
END;
|
||||
INSERT INTO t17a(ii) VALUES('1');
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -114,6 +114,6 @@ do_test trigger7-99.1 {
|
||||
db close
|
||||
catch { sqlite3 db test.db }
|
||||
catchsql { DROP TRIGGER t2r5 }
|
||||
} {1 {malformed database schema (t2r12) - near "nonsense": syntax error}}
|
||||
} {1 {malformed database schema (t2r12)}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix triggerC
|
||||
ifcapable {!trigger} {
|
||||
finish_test
|
||||
return
|
||||
@@ -993,4 +994,52 @@ reset_db
|
||||
optimization_control db factor-constants 0
|
||||
do_execsql_test triggerC-14.2 $SQL {1 2 3}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that table names used by trigger programs are dequoted exactly
|
||||
# once.
|
||||
#
|
||||
do_execsql_test 15.1.1 {
|
||||
PRAGMA recursive_triggers = 1;
|
||||
CREATE TABLE node(
|
||||
id int not null primary key,
|
||||
pid int not null default 0 references node,
|
||||
key varchar not null,
|
||||
path varchar default '',
|
||||
unique(pid, key)
|
||||
);
|
||||
CREATE TRIGGER node_delete_referencing AFTER DELETE ON "node"
|
||||
BEGIN
|
||||
DELETE FROM "node" WHERE pid = old."id";
|
||||
END;
|
||||
}
|
||||
do_execsql_test 15.1.2 {
|
||||
INSERT INTO node(id, pid, key) VALUES(9, 0, 'test');
|
||||
INSERT INTO node(id, pid, key) VALUES(90, 9, 'test1');
|
||||
INSERT INTO node(id, pid, key) VALUES(900, 90, 'test2');
|
||||
DELETE FROM node WHERE id=9;
|
||||
SELECT * FROM node;
|
||||
}
|
||||
|
||||
do_execsql_test 15.2.1 {
|
||||
CREATE TABLE x1 (x);
|
||||
|
||||
CREATE TABLE x2 (a, b);
|
||||
CREATE TABLE '"x2"'(a, b);
|
||||
|
||||
INSERT INTO x2 VALUES(1, 2);
|
||||
INSERT INTO x2 VALUES(3, 4);
|
||||
INSERT INTO '"x2"' SELECT * FROM x2;
|
||||
|
||||
CREATE TRIGGER x1ai AFTER INSERT ON x1 BEGIN
|
||||
INSERT INTO """x2""" VALUES('x', 'y');
|
||||
DELETE FROM """x2""" WHERE a=1;
|
||||
UPDATE """x2""" SET b = 11 WHERE a = 3;
|
||||
END;
|
||||
|
||||
INSERT INTO x1 VALUES('go!');
|
||||
}
|
||||
|
||||
do_execsql_test 15.2.2 { SELECT * FROM x2; } {1 2 3 4}
|
||||
do_execsql_test 15.2.3 { SELECT * FROM """x2"""; } {3 11 x y}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix vacuum2
|
||||
|
||||
# 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).
|
||||
@@ -227,5 +228,24 @@ do_test vacuum2-5.4 {
|
||||
lappend res2 $res
|
||||
} {1 2 3 4 5 6 7 8 9 10 {1 {cannot VACUUM - SQL statements in progress}}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that if the definition of a collation sequence is changed and
|
||||
# VACUUM run, records are store in the (new) correct order following the
|
||||
# VACUUM. Even if the modified collation is attached to a PK of a WITHOUT
|
||||
# ROWID table.
|
||||
|
||||
proc cmp {lhs rhs} { string compare $lhs $rhs }
|
||||
db collate cmp cmp
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t6(x PRIMARY KEY COLLATE cmp, y) WITHOUT ROWID;
|
||||
CREATE INDEX t6y ON t6(y);
|
||||
INSERT INTO t6 VALUES('i', 'one');
|
||||
INSERT INTO t6 VALUES('ii', 'one');
|
||||
INSERT INTO t6 VALUES('iii', 'one');
|
||||
}
|
||||
integrity_check 6.1
|
||||
proc cmp {lhs rhs} { string compare $rhs $lhs }
|
||||
do_execsql_test 6.2 VACUUM
|
||||
integrity_check 6.3
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1437,4 +1437,95 @@ ifcapable fts3 {
|
||||
} {SQLITE_OK}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests verify that a DROP TABLE command on a virtual
|
||||
# table does not cause other operations to crash.
|
||||
#
|
||||
# 23.1: Dropping a vtab while a SELECT is running on it.
|
||||
#
|
||||
# 23.2: Dropping a vtab while a SELECT that will, but has not yet,
|
||||
# open a cursor on the vtab, is running. In this case the
|
||||
# DROP TABLE succeeds and the SELECT hits an error.
|
||||
#
|
||||
# 23.3: Dropping a vtab from within a user-defined-function callback
|
||||
# in the middle of an "INSERT INTO vtab SELECT ..." statement.
|
||||
#
|
||||
reset_db
|
||||
load_static_extension db wholenumber
|
||||
load_static_extension db eval
|
||||
register_echo_module db
|
||||
|
||||
do_test 23.1 {
|
||||
execsql { CREATE VIRTUAL TABLE t1 USING wholenumber }
|
||||
set res ""
|
||||
db eval { SELECT value FROM t1 WHERE value<10 } {
|
||||
if {$value == 5} {
|
||||
set res [catchsql { DROP TABLE t1 }]
|
||||
}
|
||||
}
|
||||
set res
|
||||
} {1 {database table is locked}}
|
||||
|
||||
do_test 23.2 {
|
||||
execsql {
|
||||
CREATE TABLE t2(value);
|
||||
INSERT INTO t2 VALUES(1), (2), (3);
|
||||
}
|
||||
|
||||
set res2 [list [catch {
|
||||
db eval {
|
||||
SELECT value FROM t2 UNION ALL
|
||||
SELECT value FROM t1 WHERE value<10
|
||||
} {
|
||||
if {$value == 2} { set res1 [catchsql { DROP TABLE t1 }] }
|
||||
}
|
||||
} msg] $msg]
|
||||
list $res1 $res2
|
||||
} {{0 {}} {1 {database table is locked}}}
|
||||
|
||||
do_test 23.3.1 {
|
||||
execsql { CREATE VIRTUAL TABLE t1e USING echo(t2) }
|
||||
execsql { INSERT INTO t1e SELECT 4 }
|
||||
catchsql { INSERT INTO t1e SELECT eval('DROP TABLE t1e') }
|
||||
} {1 {database table is locked}}
|
||||
do_execsql_test 23.3.2 { SELECT * FROM t1e } {1 2 3 4}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# At one point SQL like this:
|
||||
#
|
||||
# SAVEPOINT xyz; -- Opens SQL transaction
|
||||
# INSERT INTO vtab -- Write to virtual table
|
||||
# ROLLBACK TO xyz;
|
||||
# RELEASE xyz;
|
||||
#
|
||||
# was not invoking the xRollbackTo() callback for the ROLLBACK TO
|
||||
# operation. Which meant that virtual tables like FTS3 would incorrectly
|
||||
# commit the results of the INSERT as part of the "RELEASE xyz" command.
|
||||
#
|
||||
# The following tests check that this has been fixed.
|
||||
#
|
||||
ifcapable fts3 {
|
||||
do_execsql_test 24.0 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts3();
|
||||
SAVEPOINT a;
|
||||
INSERT INTO t4 VALUES('a b c');
|
||||
ROLLBACK TO a;
|
||||
RELEASE a;
|
||||
SELECT * FROM t4;
|
||||
} {}
|
||||
|
||||
do_execsql_test 24.1 { SELECT * FROM t4 WHERE t4 MATCH 'b' } {}
|
||||
do_execsql_test 24.2 { INSERT INTO t4(t4) VALUES('integrity-check') } {}
|
||||
|
||||
do_execsql_test 24.3 {
|
||||
SAVEPOINT a;
|
||||
CREATE VIRTUAL TABLE t5 USING fts3();
|
||||
SAVEPOINT b;
|
||||
ROLLBACK TO a;
|
||||
SAVEPOINT c;
|
||||
RELEASE a;
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+21
-1
@@ -10,10 +10,10 @@
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
# $Id: vtab2.test,v 1.9 2008/10/13 10:37:50 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix vtab2
|
||||
|
||||
ifcapable !vtab||!schema_pragmas {
|
||||
finish_test
|
||||
@@ -133,4 +133,24 @@ do_test vtab2-4.5 {
|
||||
execsql { SELECT * FROM fkey }
|
||||
} {t1 a}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
ifcapable fts3 {
|
||||
reset_db
|
||||
do_execsql_test 5.1 {
|
||||
PRAGMA encoding='UTF16';
|
||||
}
|
||||
|
||||
do_test 5.2 {
|
||||
sqlite3_exec_hex db { CREATE VIRTUAL TABLE %C8 USING fts3 }
|
||||
} {0 {}}
|
||||
|
||||
do_test 5.3 {
|
||||
sqlite3_exec_hex db { CREATE VIRTUAL TABLE %C9 USING s }
|
||||
} {/1 {malformed database schema.* already exists}/}
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+17
-6
@@ -74,28 +74,39 @@ do_test vtabA-1.6 {
|
||||
SELECT * FROM t1e;
|
||||
}
|
||||
} {{value a} {value c}}
|
||||
do_execsql_test vtabA-1.7 {
|
||||
DELETE FROM t1e;
|
||||
INSERT INTO t1e SELECT 'abc','def';
|
||||
} {}
|
||||
do_execsql_test vtabA-1.8 {
|
||||
INSERT INTO t1e VALUES('ghi','jkl'),('mno','pqr'),('stu','vwx');
|
||||
} {}
|
||||
do_execsql_test vtabA-1.9 {
|
||||
SELECT a,b,c, '|' FROM t1e ORDER BY 1;
|
||||
} {abc {} def | ghi {} jkl | mno {} pqr | stu {} vwx |}
|
||||
|
||||
|
||||
# Test that the expansion of a '*' expression in the result set of
|
||||
# a SELECT does not include the hidden column.
|
||||
#
|
||||
do_test vtabA-1.7 {
|
||||
do_test vtabA-1.20 {
|
||||
execsql {
|
||||
INSERT INTO t1e SELECT * FROM t1e;
|
||||
}
|
||||
} {}
|
||||
do_test vtabA-1.8 {
|
||||
do_test vtabA-1.21 {
|
||||
execsql {
|
||||
SELECT * FROM t1e;
|
||||
SELECT * FROM t1e ORDER BY 1;
|
||||
}
|
||||
} {{value a} {value c} {value a} {value c}}
|
||||
} {abc def abc def ghi jkl ghi jkl mno pqr mno pqr stu vwx stu vwx}
|
||||
|
||||
# Test that the declaration type of the hidden column does not include
|
||||
# the token "HIDDEN".
|
||||
#
|
||||
do_test vtabA-1.9 {
|
||||
do_test vtabA-1.22 {
|
||||
get_decltype t1e b
|
||||
} {VARCHAR}
|
||||
do_test vtabA-1.10 {
|
||||
do_test vtabA-1.23 {
|
||||
get_collist t1e
|
||||
} {a c}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user