1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-19 21:43:15 +03:00

Merge in the latest trunk changes, including partial indexes, the MAX_PATH

fix in os_win.c, and the sqlite3_cancel_auto_extension() API.

FossilOrigin-Name: 7e1acb390770d1bd189fac7a3a7f96106f96e3a4
This commit is contained in:
drh
2013-08-02 20:44:48 +00:00
42 changed files with 1323 additions and 470 deletions

View File

@@ -43,6 +43,8 @@ ifcapable !stat3 {
# analyze3-5.*: Check that the query plans of applicable statements are
# invalidated if the values of SQL parameter are modified
# using the clear_bindings() or transfer_bindings() APIs.
#
# analyze3-6.*: Test that the problem fixed by commit [127a5b776d] is fixed.
#
proc getvar {varname} { uplevel #0 set $varname }
@@ -612,4 +614,29 @@ do_test analyze3-5.1.3 {
sqlite3_finalize $S1
} {SQLITE_OK}
#-------------------------------------------------------------------------
do_test analyze3-6.1 {
execsql { DROP TABLE IF EXISTS t1 }
execsql BEGIN
execsql { CREATE TABLE t1(a, b, c) }
for {set i 0} {$i < 1000} {incr i} {
execsql "INSERT INTO t1 VALUES([expr $i/100], 'x', [expr $i/10])"
}
execsql {
CREATE INDEX i1 ON t1(a, b);
CREATE INDEX i2 ON t1(c);
}
execsql COMMIT
execsql ANALYZE
} {}
do_eqp_test analyze3-6-3 {
SELECT * FROM t1 WHERE a = 5 AND c = 13;
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
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=?)}}
finish_test

View File

@@ -451,5 +451,11 @@ do_test 7.8 {
catchsql { INSERT INTO t6 VALUES(12) } db2
} {1 {constraint failed}}
# 2013-08-02: Silently ignore database name qualifiers in CHECK constraints.
#
do_execsql_test 8.1 {
CREATE TABLE t810(a, CHECK( main.t810.a>0 ));
CREATE TABLE t811(b, CHECK( xyzzy.t811.b BETWEEN 5 AND 10 ));
} {}
finish_test

75
test/corruptG.test Normal file
View File

@@ -0,0 +1,75 @@
# 2013-08-01
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptG
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec
# Create a simple database with a single entry. Then corrupt the
# header-size varint on the index payload so that it maps into a
# negative number. Try to use the database.
#
do_execsql_test 1.1 {
PRAGMA page_size=512;
CREATE TABLE t1(a,b,c);
INSERT INTO t1(rowid,a,b,c) VALUES(52,'abc','xyz','123');
CREATE INDEX t1abc ON t1(a,b,c);
}
# Corrupt the file
db close
hexio_write test.db [expr {3*512 - 15}] 888080807f
sqlite3 db test.db
# Try to use the file.
do_test 1.2 {
catchsql {
SELECT c FROM t1 WHERE a>'abc';
}
} {0 {}}
do_test 1.3 {
catchsql {
PRAGMA integrity_check
}
} {0 ok}
do_test 1.4 {
catchsql {
SELECT c FROM t1 ORDER BY a;
}
} {1 {database disk image is malformed}}
# Corrupt the same file in a slightly different way. Make the record header
# sane, but corrupt one of the serial_type value to indicate a huge payload
# such that the payload begins in allocated space but overflows the buffer.
#
db close
hexio_write test.db [expr {3*512-15}] 0513ff7f01
sqlite3 db test.db
do_test 2.1 {
catchsql {
SELECT rowid FROM t1 WHERE a='abc' and b='xyz123456789XYZ';
}
# The following test result is brittle. The point above is to try to
# force a buffer overread by a corrupt database file. If we get an
# incorrect answer from a corrupt database file, that is OK. If the
# result below changes, that just means that "undefined behavior" has
# changed.
} {0 52}
finish_test

View File

@@ -14,6 +14,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix func
# Create a table to work with.
#
@@ -682,6 +683,32 @@ do_test func-13.7 {
lappend res [sqlite3_finalize $STMT]
} {{0 0} {1 0} SQLITE_OK}
# Test that auxiliary data is discarded when a statement is reset.
do_execsql_test 13.8.1 {
SELECT test_auxdata('constant') FROM t4;
} {0 1}
do_execsql_test 13.8.2 {
SELECT test_auxdata('constant') FROM t4;
} {0 1}
db cache flush
do_execsql_test 13.8.3 {
SELECT test_auxdata('constant') FROM t4;
} {0 1}
set V "one"
do_execsql_test 13.8.4 {
SELECT test_auxdata($V), $V FROM t4;
} {0 one 1 one}
set V "two"
do_execsql_test 13.8.5 {
SELECT test_auxdata($V), $V FROM t4;
} {0 two 1 two}
db cache flush
set V "three"
do_execsql_test 13.8.6 {
SELECT test_auxdata($V), $V FROM t4;
} {0 three 1 three}
# Make sure that a function with a very long name is rejected
do_test func-14.1 {
catch {

View File

@@ -715,6 +715,23 @@ do_test index-20.2 {
DROP INDEX "t6i1";
}
} {}
# Try to create a TEMP index on a non-TEMP table. */
#
do_test index-21.1 {
catchsql {
CREATE INDEX temp.i21 ON t6(c);
}
} {1 {cannot create a TEMP index on non-TEMP table "t6"}}
do_test index-21.2 {
catchsql {
CREATE TEMP TABLE t6(x);
INSERT INTO temp.t6 values(1),(5),(9);
CREATE INDEX temp.i21 ON t6(x);
SELECT x FROM t6 ORDER BY x DESC;
}
} {0 {9 5 1}}
finish_test

230
test/index6.test Normal file
View File

@@ -0,0 +1,230 @@
# 2013-07-31
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Test cases for partial indices
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
load_static_extension db wholenumber;
do_test index6-1.1 {
# Able to parse and manage partial indices
execsql {
CREATE TABLE t1(a,b,c);
CREATE INDEX t1a ON t1(a) WHERE a IS NOT NULL;
CREATE INDEX t1b ON t1(b) WHERE b>10;
CREATE VIRTUAL TABLE nums USING wholenumber;
INSERT INTO t1(a,b,c)
SELECT CASE WHEN value%3!=0 THEN value END, value, value
FROM nums WHERE value<=20;
SELECT count(a), count(b) FROM t1;
PRAGMA integrity_check;
}
} {14 20 ok}
# Error conditions during parsing...
#
do_test index6-1.2 {
catchsql {
CREATE INDEX bad1 ON t1(a,b) WHERE x IS NOT NULL;
}
} {1 {no such column: x}}
do_test index6-1.3 {
catchsql {
CREATE INDEX bad1 ON t1(a,b) WHERE EXISTS(SELECT * FROM t1);
}
} {1 {subqueries prohibited in partial index WHERE clauses}}
do_test index6-1.4 {
catchsql {
CREATE INDEX bad1 ON t1(a,b) WHERE a!=?1;
}
} {1 {parameters prohibited in partial index WHERE clauses}}
do_test index6-1.5 {
catchsql {
CREATE INDEX bad1 ON t1(a,b) WHERE a!=random();
}
} {1 {functions prohibited in partial index WHERE clauses}}
do_test index6-1.6 {
catchsql {
CREATE INDEX bad1 ON t1(a,b) WHERE a NOT LIKE 'abc%';
}
} {1 {functions prohibited in partial index WHERE clauses}}
do_test index6-1.10 {
execsql {
ANALYZE;
SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
PRAGMA integrity_check;
}
} {{} 20 t1a {14 1} t1b {10 1} ok}
# STAT1 shows the partial indices have a reduced number of
# rows.
#
do_test index6-1.11 {
execsql {
UPDATE t1 SET a=b;
ANALYZE;
SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
PRAGMA integrity_check;
}
} {{} 20 t1a {20 1} t1b {10 1} ok}
do_test index6-1.11 {
execsql {
UPDATE t1 SET a=NULL WHERE b%3!=0;
UPDATE t1 SET b=b+100;
ANALYZE;
SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
PRAGMA integrity_check;
}
} {{} 20 t1a {6 1} t1b {20 1} ok}
do_test index6-1.12 {
execsql {
UPDATE t1 SET a=CASE WHEN b%3!=0 THEN b END;
UPDATE t1 SET b=b-100;
ANALYZE;
SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
PRAGMA integrity_check;
}
} {{} 20 t1a {13 1} t1b {10 1} ok}
do_test index6-1.13 {
execsql {
DELETE FROM t1 WHERE b BETWEEN 8 AND 12;
ANALYZE;
SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
PRAGMA integrity_check;
}
} {{} 15 t1a {10 1} t1b {8 1} ok}
do_test index6-1.14 {
execsql {
REINDEX;
ANALYZE;
SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
PRAGMA integrity_check;
}
} {{} 15 t1a {10 1} t1b {8 1} ok}
do_test index6-1.15 {
execsql {
CREATE INDEX t1c ON t1(c);
ANALYZE;
SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
PRAGMA integrity_check;
}
} {t1a {10 1} t1b {8 1} t1c {15 1} ok}
# Queries use partial indices as appropriate times.
#
do_test index6-2.1 {
execsql {
CREATE TABLE t2(a,b);
INSERT INTO t2(a,b) SELECT value, value FROM nums WHERE value<1000;
UPDATE t2 SET a=NULL WHERE b%5==0;
CREATE INDEX t2a1 ON t2(a) WHERE a IS NOT NULL;
SELECT count(*) FROM t2 WHERE a IS NOT NULL;
}
} {800}
do_test index6-2.2 {
execsql {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a=5;
}
} {/.* TABLE t2 USING INDEX t2a1 .*/}
do_test index6-2.3 {
execsql {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a IS NOT NULL;
}
} {/.* TABLE t2 USING INDEX t2a1 .*/}
do_test index6-2.4 {
execsql {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a IS NULL;
}
} {~/.*INDEX t2a1.*/}
do_execsql_test index6-2.101 {
DROP INDEX t2a1;
UPDATE t2 SET a=b, b=b+10000;
SELECT b FROM t2 WHERE a=15;
} {10015}
do_execsql_test index6-2.102 {
CREATE INDEX t2a2 ON t2(a) WHERE a<100 OR a>200;
SELECT b FROM t2 WHERE a=15;
PRAGMA integrity_check;
} {10015 ok}
do_execsql_test index6-2.102eqp {
EXPLAIN QUERY PLAN
SELECT b FROM t2 WHERE a=15;
} {~/.*INDEX t2a2.*/}
do_execsql_test index6-2.103 {
SELECT b FROM t2 WHERE a=15 AND a<100;
} {10015}
do_execsql_test index6-2.103eqp {
EXPLAIN QUERY PLAN
SELECT b FROM t2 WHERE a=15 AND a<100;
} {/.*INDEX t2a2.*/}
do_execsql_test index6-2.104 {
SELECT b FROM t2 WHERE a=515 AND a>200;
} {10515}
do_execsql_test index6-2.104eqp {
EXPLAIN QUERY PLAN
SELECT b FROM t2 WHERE a=515 AND a>200;
} {/.*INDEX t2a2.*/}
# Partial UNIQUE indices
#
do_execsql_test index6-3.1 {
CREATE TABLE t3(a,b);
INSERT INTO t3 SELECT value, value FROM nums WHERE value<200;
UPDATE t3 SET a=999 WHERE b%5!=0;
CREATE UNIQUE INDEX t3a ON t3(a) WHERE a<>999;
} {}
do_test index6-3.2 {
# unable to insert a duplicate row a-value that is not 999.
catchsql {
INSERT INTO t3(a,b) VALUES(150, 'test1');
}
} {1 {column a is not unique}}
do_test index6-3.3 {
# can insert multiple rows with a==999 because such rows are not
# part of the unique index.
catchsql {
INSERT INTO t3(a,b) VALUES(999, 'test1'), (999, 'test2');
}
} {0 {}}
do_execsql_test index6-3.4 {
SELECT count(*) FROM t3 WHERE a=999;
} {162}
integrity_check index6-3.5
do_execsql_test index6-4.0 {
VACUUM;
PRAGMA integrity_check;
} {ok}
# Silently ignore database name qualifiers in partial indices.
#
do_execsql_test index6-5.0 {
CREATE INDEX t3b ON t3(b) WHERE xyzzy.t3.b BETWEEN 5 AND 10;
/* ^^^^^-- ignored */
ANALYZE;
SELECT count(*) FROM t3 WHERE t3.b BETWEEN 5 AND 10;
SELECT stat+0 FROM sqlite_stat1 WHERE idx='t3b';
} {6 6}
finish_test

View File

@@ -43,6 +43,19 @@ do_test loadext2-1.2 {
}
} {1 {no such function: cube}}
# Extensions loaders not currently registered
#
do_test loadext2-1.2.1 {
sqlite3_cancel_auto_extension_sqr
} {0}
do_test loadext2-1.2.2 {
sqlite3_cancel_auto_extension_sqr
} {0}
do_test loadext2-1.2.3 {
sqlite3_cancel_auto_extension_sqr
} {0}
# Register auto-loaders. Still functions do not exist.
#
do_test loadext2-1.3 {
@@ -76,8 +89,19 @@ do_test loadext2-1.6 {
# Reset extension auto loading. Existing extensions still exist.
#
do_test loadext2-1.7 {
sqlite3_reset_auto_extension
do_test loadext2-1.7.1 {
sqlite3_cancel_auto_extension_sqr
} {1}
do_test loadext2-1.7.2 {
sqlite3_cancel_auto_extension_sqr
} {0}
do_test loadext2-1.7.3 {
sqlite3_cancel_auto_extension_cube
} {1}
do_test loadext2-1.7.4 {
sqlite3_cancel_auto_extension_cube
} {0}
do_test loadext2-1.7.5 {
catchsql {
SELECT sqr(2)
}

View File

@@ -699,5 +699,16 @@ do_test where2-11.4 {
}
} {4 8 10}
# Verify that the OR clause is used in an outer loop even when
# the OR clause scores slightly better on an inner loop.
do_execsql_test where2-12.1 {
CREATE TABLE t12(x INTEGER PRIMARY KEY, y);
CREATE INDEX t12y ON t12(y);
EXPLAIN QUERY PLAN
SELECT a.x, b.x
FROM t12 AS a JOIN t12 AS b ON a.y=b.x
WHERE (b.x=$abc OR b.y=$abc);
} {/.*SEARCH TABLE t12 AS b .*SEARCH TABLE t12 AS b .*/}
finish_test

View File

@@ -212,8 +212,9 @@ do_test where8-3.4 {
do_test where8-3.5 {
execsql_status {
SELECT a, d FROM t1, t2 WHERE (a = 2 OR a = 3) AND (d = a OR e = 'sixteen')
ORDER BY +a, +d;
}
} {2 2 2 4 3 3 3 4 0 0}
} {2 2 2 4 3 3 3 4 0 1}
do_test where8-3.6 {
# The first part of the WHERE clause in this query, (a=2 OR a=3) is
@@ -233,7 +234,7 @@ do_test where8-3.7 {
WHERE a = 2 AND (d = a OR e = 'sixteen')
ORDER BY t1.rowid
}
} {2 2 2 4 0 0}
} {/2 2 2 4 0 [01]/}
do_test where8-3.8 {
execsql_status {
SELECT a, d