summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsqlite/test
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libsqlite/test')
-rw-r--r--usr/src/lib/libsqlite/test/all.test112
-rw-r--r--usr/src/lib/libsqlite/test/attach.test589
-rw-r--r--usr/src/lib/libsqlite/test/attach2.test149
-rw-r--r--usr/src/lib/libsqlite/test/auth.test1895
-rw-r--r--usr/src/lib/libsqlite/test/bigfile.test180
-rw-r--r--usr/src/lib/libsqlite/test/bigrow.test218
-rw-r--r--usr/src/lib/libsqlite/test/bind.test75
-rw-r--r--usr/src/lib/libsqlite/test/btree.test1023
-rw-r--r--usr/src/lib/libsqlite/test/btree2.test449
-rw-r--r--usr/src/lib/libsqlite/test/btree3.test89
-rw-r--r--usr/src/lib/libsqlite/test/btree3rb.test87
-rw-r--r--usr/src/lib/libsqlite/test/btree4.test101
-rw-r--r--usr/src/lib/libsqlite/test/btree4rb.test98
-rw-r--r--usr/src/lib/libsqlite/test/capi2.test478
-rw-r--r--usr/src/lib/libsqlite/test/conflict.test697
-rw-r--r--usr/src/lib/libsqlite/test/copy.test268
-rw-r--r--usr/src/lib/libsqlite/test/crashme2.off52
-rw-r--r--usr/src/lib/libsqlite/test/crashtest1.c99
-rw-r--r--usr/src/lib/libsqlite/test/date.test260
-rw-r--r--usr/src/lib/libsqlite/test/delete.test294
-rw-r--r--usr/src/lib/libsqlite/test/expr.test522
-rw-r--r--usr/src/lib/libsqlite/test/fkey1.test56
-rw-r--r--usr/src/lib/libsqlite/test/format3.test741
-rw-r--r--usr/src/lib/libsqlite/test/func.test348
-rw-r--r--usr/src/lib/libsqlite/test/hook.test86
-rw-r--r--usr/src/lib/libsqlite/test/in.test306
-rw-r--r--usr/src/lib/libsqlite/test/index.test536
-rw-r--r--usr/src/lib/libsqlite/test/insert.test289
-rw-r--r--usr/src/lib/libsqlite/test/insert2.test197
-rw-r--r--usr/src/lib/libsqlite/test/interrupt.test170
-rw-r--r--usr/src/lib/libsqlite/test/intpkey.test490
-rw-r--r--usr/src/lib/libsqlite/test/ioerr.test123
-rw-r--r--usr/src/lib/libsqlite/test/join.test396
-rw-r--r--usr/src/lib/libsqlite/test/join2.test76
-rw-r--r--usr/src/lib/libsqlite/test/join3_28.test37
-rw-r--r--usr/src/lib/libsqlite/test/join4_28.test80
-rw-r--r--usr/src/lib/libsqlite/test/lastinsert.test322
-rw-r--r--usr/src/lib/libsqlite/test/laststmtchanges.test247
-rw-r--r--usr/src/lib/libsqlite/test/limit.test320
-rw-r--r--usr/src/lib/libsqlite/test/lock.test352
-rw-r--r--usr/src/lib/libsqlite/test/main.test300
-rw-r--r--usr/src/lib/libsqlite/test/malloc.test228
-rw-r--r--usr/src/lib/libsqlite/test/memdb.test399
-rw-r--r--usr/src/lib/libsqlite/test/memleak.test94
-rw-r--r--usr/src/lib/libsqlite/test/minmax.test362
-rw-r--r--usr/src/lib/libsqlite/test/misc1.test543
-rw-r--r--usr/src/lib/libsqlite/test/misc2.test238
-rw-r--r--usr/src/lib/libsqlite/test/misc3.test307
-rw-r--r--usr/src/lib/libsqlite/test/misuse.test169
-rw-r--r--usr/src/lib/libsqlite/test/notnull.test503
-rw-r--r--usr/src/lib/libsqlite/test/null.test240
-rw-r--r--usr/src/lib/libsqlite/test/pager.test426
-rw-r--r--usr/src/lib/libsqlite/test/pragma.test420
-rw-r--r--usr/src/lib/libsqlite/test/printf.test129
-rw-r--r--usr/src/lib/libsqlite/test/progress.test121
-rw-r--r--usr/src/lib/libsqlite/test/quick.test56
-rw-r--r--usr/src/lib/libsqlite/test/quote.test91
-rw-r--r--usr/src/lib/libsqlite/test/rowid.test636
-rw-r--r--usr/src/lib/libsqlite/test/select1.test744
-rw-r--r--usr/src/lib/libsqlite/test/select2.test165
-rw-r--r--usr/src/lib/libsqlite/test/select3.test228
-rw-r--r--usr/src/lib/libsqlite/test/select4.test498
-rw-r--r--usr/src/lib/libsqlite/test/select5.test122
-rw-r--r--usr/src/lib/libsqlite/test/select6.test438
-rw-r--r--usr/src/lib/libsqlite/test/sort.test364
-rw-r--r--usr/src/lib/libsqlite/test/subselect.test158
-rw-r--r--usr/src/lib/libsqlite/test/table.test506
-rw-r--r--usr/src/lib/libsqlite/test/tableapi.test204
-rw-r--r--usr/src/lib/libsqlite/test/tclsqlite.test122
-rw-r--r--usr/src/lib/libsqlite/test/temptable.test402
-rw-r--r--usr/src/lib/libsqlite/test/tester.tcl267
-rw-r--r--usr/src/lib/libsqlite/test/thread1.test161
-rw-r--r--usr/src/lib/libsqlite/test/threadtest1.c285
-rw-r--r--usr/src/lib/libsqlite/test/threadtest2.c127
-rw-r--r--usr/src/lib/libsqlite/test/trans.test905
-rw-r--r--usr/src/lib/libsqlite/test/trigger1.test522
-rw-r--r--usr/src/lib/libsqlite/test/trigger2.test721
-rw-r--r--usr/src/lib/libsqlite/test/trigger3.test169
-rw-r--r--usr/src/lib/libsqlite/test/trigger4.test130
-rw-r--r--usr/src/lib/libsqlite/test/unique.test235
-rw-r--r--usr/src/lib/libsqlite/test/update.test565
-rw-r--r--usr/src/lib/libsqlite/test/vacuum.test176
-rw-r--r--usr/src/lib/libsqlite/test/version.test201
-rw-r--r--usr/src/lib/libsqlite/test/view.test410
-rw-r--r--usr/src/lib/libsqlite/test/where.test745
85 files changed, 27739 insertions, 0 deletions
diff --git a/usr/src/lib/libsqlite/test/all.test b/usr/src/lib/libsqlite/test/all.test
new file mode 100644
index 0000000000..2cdd89c2bf
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/all.test
@@ -0,0 +1,112 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 runs all tests.
+#
+# $Id: all.test,v 1.19 2003/02/16 22:21:33 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+rename finish_test really_finish_test
+proc finish_test {} {memleak_check}
+
+if {[file exists ./sqlite_test_count]} {
+ set COUNT [exec cat ./sqlite_test_count]
+} else {
+ set COUNT 4
+}
+
+if {[llength $argv]>0} {
+ foreach {name value} $argv {
+ switch -- $name {
+ -count {
+ set COUNT $value
+ }
+ -quick {
+ set ISQUICK $value
+ }
+ default {
+ puts stderr "Unknown option: $name"
+ exit
+ }
+ }
+ }
+}
+set argv {}
+
+# LeakList will hold a list of the number of unfreed mallocs after
+# each round of the test. This number should be constant. If it
+# grows, it may mean there is a memory leak in the library.
+#
+set LeakList {}
+
+set EXCLUDE {
+ all.test
+ quick.test
+ malloc.test
+ misuse.test
+ memleak.test
+}
+# btree2.test
+
+for {set Counter 0} {$Counter<$COUNT && $nErr==0} {incr Counter} {
+ set btree_native_byte_order [expr {($Counter>>1)&0x1}]
+ if {$Counter%2} {
+ set ::SETUP_SQL {PRAGMA default_synchronous=off;}
+ } else {
+ catch {unset ::SETUP_SQL}
+ }
+ foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
+ set tail [file tail $testfile]
+ if {[lsearch -exact $EXCLUDE $tail]>=0} continue
+ source $testfile
+ catch {db close}
+ if {$sqlite_open_file_count>0} {
+ puts "$tail did not close all files: $sqlite_open_file_count"
+ incr nErr
+ lappend ::failList $tail
+ }
+ }
+ if {[info exists Leak]} {
+ lappend LeakList $Leak
+ }
+}
+
+# Do one last test to look for a memory leak in the library. This will
+# only work if SQLite is compiled with the -DMEMORY_DEBUG=1 flag.
+#
+if {$LeakList!=""} {
+ puts -nonewline memory-leak-test...
+ incr ::nTest
+ foreach x $LeakList {
+ if {$x!=[lindex $LeakList 0]} {
+ puts " failed!"
+ puts "Expected: all values to be the same"
+ puts " Got: $LeakList"
+ incr ::nErr
+ lappend ::failList memory-leak-test
+ break
+ }
+ }
+ puts " Ok"
+}
+
+# Run the malloc tests and the misuse test after memory leak detection.
+# Both tests leak memory.
+#
+catch {source $testdir/misuse.test}
+catch {source $testdir/malloc.test}
+
+catch {db close}
+set sqlite_open_file_count 0
+really_finish_test
diff --git a/usr/src/lib/libsqlite/test/attach.test b/usr/src/lib/libsqlite/test/attach.test
new file mode 100644
index 0000000000..67521eaa85
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/attach.test
@@ -0,0 +1,589 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2003 April 4
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is testing the ATTACH and DETACH commands
+# and related functionality.
+#
+# $Id: attach.test,v 1.13 2004/02/14 01:39:50 drh Exp $
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+for {set i 2} {$i<=15} {incr i} {
+ file delete -force test$i.db
+ file delete -force test$i.db-journal
+}
+
+do_test attach-1.1 {
+ execsql {
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1 VALUES(1,2);
+ INSERT INTO t1 VALUES(3,4);
+ SELECT * FROM t1;
+ }
+} {1 2 3 4}
+do_test attach-1.2 {
+ sqlite db2 test2.db
+ execsql {
+ CREATE TABLE t2(x,y);
+ INSERT INTO t2 VALUES(1,'x');
+ INSERT INTO t2 VALUES(2,'y');
+ SELECT * FROM t2;
+ } db2
+} {1 x 2 y}
+do_test attach-1.3 {
+ execsql {
+ ATTACH DATABASE 'test2.db' AS two;
+ SELECT * FROM two.t2;
+ }
+} {1 x 2 y}
+do_test attach-1.4 {
+ execsql {
+ SELECT * FROM t2;
+ }
+} {1 x 2 y}
+do_test attach-1.5 {
+ execsql {
+ DETACH DATABASE two;
+ SELECT * FROM t1;
+ }
+} {1 2 3 4}
+do_test attach-1.6 {
+ catchsql {
+ SELECT * FROM t2;
+ }
+} {1 {no such table: t2}}
+do_test attach-1.7 {
+ catchsql {
+ SELECT * FROM two.t2;
+ }
+} {1 {no such table: two.t2}}
+do_test attach-1.8 {
+ catchsql {
+ ATTACH DATABASE 'test3.db' AS three;
+ }
+} {1 {cannot attach empty database: three}}
+do_test attach-1.9 {
+ catchsql {
+ SELECT * FROM three.sqlite_master;
+ }
+} {1 {no such table: three.sqlite_master}}
+do_test attach-1.10 {
+ catchsql {
+ DETACH DATABASE three;
+ }
+} {1 {no such database: three}}
+do_test attach-1.11 {
+ execsql {
+ ATTACH 'test.db' AS db2;
+ ATTACH 'test.db' AS db3;
+ ATTACH 'test.db' AS db4;
+ ATTACH 'test.db' AS db5;
+ ATTACH 'test.db' AS db6;
+ ATTACH 'test.db' AS db7;
+ ATTACH 'test.db' AS db8;
+ ATTACH 'test.db' AS db9;
+ }
+} {}
+proc db_list {db} {
+ set list {}
+ foreach {idx name file} [execsql {PRAGMA database_list} $db] {
+ lappend list $idx $name
+ }
+ return $list
+}
+do_test attach-1.11b {
+ db_list db
+} {0 main 1 temp 2 db2 3 db3 4 db4 5 db5 6 db6 7 db7 8 db8 9 db9}
+do_test attach-1.12 {
+ catchsql {
+ ATTACH 'test.db' as db2;
+ }
+} {1 {database db2 is already in use}}
+do_test attach-1.13 {
+ catchsql {
+ ATTACH 'test.db' as db5;
+ }
+} {1 {database db5 is already in use}}
+do_test attach-1.14 {
+ catchsql {
+ ATTACH 'test.db' as db9;
+ }
+} {1 {database db9 is already in use}}
+do_test attach-1.15 {
+ catchsql {
+ ATTACH 'test.db' as main;
+ }
+} {1 {database main is already in use}}
+do_test attach-1.16 {
+ catchsql {
+ ATTACH 'test.db' as temp;
+ }
+} {1 {database temp is already in use}}
+do_test attach-1.17 {
+ catchsql {
+ ATTACH 'test.db' as MAIN;
+ }
+} {1 {database MAIN is already in use}}
+do_test attach-1.18 {
+ catchsql {
+ ATTACH 'test.db' as db10;
+ ATTACH 'test.db' as db11;
+ }
+} {0 {}}
+do_test attach-1.19 {
+ catchsql {
+ ATTACH 'test.db' as db12;
+ }
+} {1 {too many attached databases - max 10}}
+do_test attach-1.20.1 {
+ execsql {
+ DETACH db5;
+ }
+ db_list db
+} {0 main 1 temp 2 db2 3 db3 4 db4 5 db11 6 db6 7 db7 8 db8 9 db9 10 db10}
+integrity_check attach-1.20.2
+do_test attach-1.21 {
+ catchsql {
+ ATTACH 'test.db' as db12;
+ }
+} {0 {}}
+do_test attach-1.22 {
+ catchsql {
+ ATTACH 'test.db' as db13;
+ }
+} {1 {too many attached databases - max 10}}
+do_test attach-1.23 {
+ catchsql {
+ DETACH db14;
+ }
+} {1 {no such database: db14}}
+do_test attach-1.24 {
+ catchsql {
+ DETACH db12;
+ }
+} {0 {}}
+do_test attach-1.25 {
+ catchsql {
+ DETACH db12;
+ }
+} {1 {no such database: db12}}
+do_test attach-1.26 {
+ catchsql {
+ DETACH main;
+ }
+} {1 {cannot detach database main}}
+do_test attach-1.27 {
+ catchsql {
+ DETACH Temp;
+ }
+} {1 {cannot detach database Temp}}
+do_test attach-1.28 {
+ catchsql {
+ DETACH db11;
+ DETACH db10;
+ DETACH db9;
+ DETACH db8;
+ DETACH db7;
+ DETACH db6;
+ DETACH db4;
+ DETACH db3;
+ DETACH db2;
+ }
+} {0 {}}
+do_test attach-1.29 {
+ db_list db
+} {0 main 1 temp}
+
+do_test attach-2.1 {
+ execsql {
+ CREATE TABLE tx(x1,x2,y1,y2);
+ CREATE TRIGGER r1 AFTER UPDATE ON t2 FOR EACH ROW BEGIN
+ INSERT INTO tx(x1,x2,y1,y2) VALUES(OLD.x,NEW.x,OLD.y,NEW.y);
+ END;
+ SELECT * FROM tx;
+ } db2;
+} {}
+do_test attach-2.2 {
+ execsql {
+ UPDATE t2 SET x=x+10;
+ SELECT * FROM tx;
+ } db2;
+} {1 11 x x 2 12 y y}
+do_test attach-2.3 {
+ execsql {
+ CREATE TABLE tx(x1,x2,y1,y2);
+ SELECT * FROM tx;
+ }
+} {}
+do_test attach-2.4 {
+ execsql {
+ ATTACH 'test2.db' AS db2;
+ }
+} {}
+do_test attach-2.5 {
+ execsql {
+ UPDATE db2.t2 SET x=x+10;
+ SELECT * FROM db2.tx;
+ }
+} {1 11 x x 2 12 y y 11 21 x x 12 22 y y}
+do_test attach-2.6 {
+ execsql {
+ SELECT * FROM main.tx;
+ }
+} {}
+do_test attach-2.7 {
+ execsql {
+ SELECT type, name, tbl_name FROM db2.sqlite_master;
+ }
+} {table t2 t2 table tx tx trigger r1 t2}
+do_test attach-2.8 {
+ db_list db
+} {0 main 1 temp 2 db2}
+do_test attach-2.9 {
+ execsql {
+ CREATE INDEX i2 ON t2(x);
+ SELECT * FROM t2 WHERE x>5;
+ } db2
+} {21 x 22 y}
+do_test attach-2.10 {
+ execsql {
+ SELECT type, name, tbl_name FROM sqlite_master;
+ } db2
+} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
+#do_test attach-2.11 {
+# catchsql {
+# SELECT * FROM t2 WHERE x>5;
+# }
+#} {1 {database schema has changed}}
+do_test attach-2.12 {
+ db_list db
+} {0 main 1 temp 2 db2}
+do_test attach-2.13 {
+ catchsql {
+ SELECT * FROM t2 WHERE x>5;
+ }
+} {0 {21 x 22 y}}
+do_test attach-2.14 {
+ execsql {
+ SELECT type, name, tbl_name FROM sqlite_master;
+ }
+} {table t1 t1 table tx tx}
+do_test attach-2.15 {
+ execsql {
+ SELECT type, name, tbl_name FROM db2.sqlite_master;
+ }
+} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
+do_test attach-2.16 {
+ db close
+ sqlite db test.db
+ execsql {
+ ATTACH 'test2.db' AS db2;
+ SELECT type, name, tbl_name FROM db2.sqlite_master;
+ }
+} {table t2 t2 table tx tx trigger r1 t2 index i2 t2}
+
+do_test attach-3.1 {
+ db close
+ db2 close
+ sqlite db test.db
+ sqlite db2 test2.db
+ execsql {
+ SELECT * FROM t1
+ }
+} {1 2 3 4}
+do_test attach-3.2 {
+ catchsql {
+ SELECT * FROM t2
+ }
+} {1 {no such table: t2}}
+do_test attach-3.3 {
+ catchsql {
+ ATTACH DATABASE 'test2.db' AS db2;
+ SELECT * FROM t2
+ }
+} {0 {21 x 22 y}}
+
+# Even though main has a transaction, test2.db should not be locked.
+do_test attach-3.4 {
+ execsql BEGIN
+ catchsql {
+ SELECT * FROM t2;
+ } db2;
+} {0 {21 x 22 y}}
+
+# Reading from db2 should not lock test2.db
+do_test attach-3.5 {
+ execsql {SELECT * FROM t2}
+ catchsql {
+ SELECT * FROM t2;
+ } db2;
+} {0 {21 x 22 y}}
+
+# Making a change to db2 causes test2.ddb to become locked.
+do_test attach-3.6 {
+ execsql {
+ UPDATE t2 SET x=x+1 WHERE x=50;
+ }
+ catchsql {
+ SELECT * FROM t2;
+ } db2;
+} {1 {database is locked}}
+
+do_test attach-3.7 {
+ execsql ROLLBACK
+ execsql {SELECT * FROM t2} db2
+} {21 x 22 y}
+do_test attach-3.8 {
+ execsql BEGIN
+ execsql BEGIN db2
+ catchsql {SELECT * FROM t2}
+} {1 {database is locked}}
+do_test attach-3.9 {
+ catchsql {SELECT * FROM t2} db2
+} {0 {21 x 22 y}}
+do_test attach-3.10 {
+ execsql {SELECT * FROM t1}
+} {1 2 3 4}
+do_test attach-3.11 {
+ catchsql {UPDATE t1 SET a=a+1}
+} {0 {}}
+do_test attach-3.12 {
+ execsql {SELECT * FROM t1}
+} {2 2 4 4}
+do_test attach-3.13 {
+ catchsql {UPDATE t2 SET x=x+1 WHERE x=50}
+} {1 {database is locked}}
+do_test attach-3.14 {
+ # Unable to reinitialize the schema tables because the aux database
+ # is still locked.
+ catchsql {SELECT * FROM t1}
+} {1 {database is locked}}
+do_test attach-3.15 {
+ execsql COMMIT db2
+ execsql {SELECT * FROM t1}
+} {1 2 3 4}
+
+# Ticket #323
+do_test attach-4.1 {
+ execsql {DETACH db2}
+ db2 close
+ sqlite db2 test2.db
+ execsql {
+ CREATE TABLE t3(x,y);
+ CREATE UNIQUE INDEX t3i1 ON t3(x);
+ INSERT INTO t3 VALUES(1,2);
+ SELECT * FROM t3;
+ } db2;
+} {1 2}
+do_test attach-4.2 {
+ execsql {
+ CREATE TABLE t3(a,b);
+ CREATE UNIQUE INDEX t3i1b ON t3(a);
+ INSERT INTO t3 VALUES(9,10);
+ SELECT * FROM t3;
+ }
+} {9 10}
+do_test attach-4.3 {
+ execsql {
+ ATTACH DATABASE 'test2.db' AS db2;
+ SELECT * FROM db2.t3;
+ }
+} {1 2}
+do_test attach-4.4 {
+ execsql {
+ SELECT * FROM main.t3;
+ }
+} {9 10}
+do_test attach-4.5 {
+ execsql {
+ INSERT INTO db2.t3 VALUES(9,10);
+ SELECT * FROM db2.t3;
+ }
+} {1 2 9 10}
+do_test attach-4.6 {
+ execsql {
+ DETACH db2;
+ }
+ execsql {
+ CREATE TABLE t4(x);
+ CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
+ INSERT INTO t4 VALUES('db2.' || NEW.x);
+ END;
+ INSERT INTO t3 VALUES(6,7);
+ SELECT * FROM t4;
+ } db2
+} {db2.6}
+do_test attach-4.7 {
+ execsql {
+ CREATE TABLE t4(y);
+ CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN
+ INSERT INTO t4 VALUES('main.' || NEW.a);
+ END;
+ INSERT INTO main.t3 VALUES(11,12);
+ SELECT * FROM main.t4;
+ }
+} {main.11}
+do_test attach-4.8 {
+ execsql {
+ ATTACH DATABASE 'test2.db' AS db2;
+ INSERT INTO db2.t3 VALUES(13,14);
+ SELECT * FROM db2.t4 UNION ALL SELECT * FROM main.t4;
+ }
+} {db2.6 db2.13 main.11}
+do_test attach-4.9 {
+ execsql {
+ INSERT INTO main.t3 VALUES(15,16);
+ SELECT * FROM db2.t4 UNION ALL SELECT * FROM main.t4;
+ }
+} {db2.6 db2.13 main.11 main.15}
+do_test attach-4.10 {
+ execsql {
+ DETACH DATABASE db2;
+ }
+ execsql {
+ CREATE VIEW v3 AS SELECT x*100+y FROM t3;
+ SELECT * FROM v3;
+ } db2
+} {102 910 607 1314}
+do_test attach-4.11 {
+ execsql {
+ CREATE VIEW v3 AS SELECT a*100+b FROM t3;
+ SELECT * FROM v3;
+ }
+} {910 1112 1516}
+do_test attach-4.12 {
+ execsql {
+ ATTACH DATABASE 'test2.db' AS db2;
+ SELECT * FROM db2.v3;
+ }
+} {102 910 607 1314}
+do_test attach-4.13 {
+ execsql {
+ SELECT * FROM main.v3;
+ }
+} {910 1112 1516}
+
+# Tests for the sqliteFix...() routines in attach.c
+#
+do_test attach-5.1 {
+ db close
+ sqlite db test.db
+ db2 close
+ file delete -force test2.db
+ sqlite db2 test2.db
+ catchsql {
+ ATTACH DATABASE 'test.db' AS orig;
+ CREATE TRIGGER r1 AFTER INSERT ON orig.t1 BEGIN;
+ SELECT 'no-op';
+ END;
+ } db2
+} {1 {triggers may not be added to auxiliary database orig}}
+do_test attach-5.2 {
+ catchsql {
+ CREATE TABLE t5(x,y);
+ CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
+ SELECT 'no-op';
+ END;
+ } db2
+} {0 {}}
+do_test attach-5.3 {
+ catchsql {
+ DROP TRIGGER r5;
+ CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
+ SELECT 'no-op' FROM orig.t1;
+ END;
+ } db2
+} {1 {trigger r5 cannot reference objects in database orig}}
+do_test attach-5.4 {
+ catchsql {
+ CREATE TEMP TABLE t6(p,q,r);
+ CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
+ SELECT 'no-op' FROM temp.t6;
+ END;
+ } db2
+} {1 {trigger r5 cannot reference objects in database temp}}
+do_test attach-5.5 {
+ catchsql {
+ CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
+ SELECT 'no-op' || (SELECT * FROM temp.t6);
+ END;
+ } db2
+} {1 {trigger r5 cannot reference objects in database temp}}
+do_test attach-5.6 {
+ catchsql {
+ CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
+ SELECT 'no-op' FROM t1 WHERE x<(SELECT min(x) FROM temp.t6);
+ END;
+ } db2
+} {1 {trigger r5 cannot reference objects in database temp}}
+do_test attach-5.7 {
+ catchsql {
+ CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
+ SELECT 'no-op' FROM t1 GROUP BY 1 HAVING x<(SELECT min(x) FROM temp.t6);
+ END;
+ } db2
+} {1 {trigger r5 cannot reference objects in database temp}}
+do_test attach-5.7 {
+ catchsql {
+ CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
+ SELECT max(1,x,(SELECT min(x) FROM temp.t6)) FROM t1;
+ END;
+ } db2
+} {1 {trigger r5 cannot reference objects in database temp}}
+do_test attach-5.8 {
+ catchsql {
+ CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
+ INSERT INTO t1 VALUES((SELECT min(x) FROM temp.t6),5);
+ END;
+ } db2
+} {1 {trigger r5 cannot reference objects in database temp}}
+do_test attach-5.9 {
+ catchsql {
+ CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN
+ DELETE FROM t1 WHERE x<(SELECT min(x) FROM temp.t6);
+ END;
+ } db2
+} {1 {trigger r5 cannot reference objects in database temp}}
+
+# Check to make sure we get a sensible error if unable to open
+# the file that we are trying to attach.
+#
+do_test attach-6.1 {
+ catchsql {
+ ATTACH DATABASE 'no-such-file' AS nosuch;
+ }
+} {1 {cannot attach empty database: nosuch}}
+file delete -force no-such-file
+if {$tcl_platform(platform)=="unix"} {
+ do_test attach-6.2 {
+ sqlite dbx cannot-read
+ dbx eval {CREATE TABLE t1(a,b,c)}
+ dbx close
+ file attributes cannot-read -permission 0000
+ catchsql {
+ ATTACH DATABASE 'cannot-read' AS noread;
+ }
+ } {1 {unable to open database: cannot-read}}
+ file delete -force cannot-read
+}
+
+for {set i 2} {$i<=15} {incr i} {
+ catch {db$i close}
+}
+file delete -force test2.db
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/attach2.test b/usr/src/lib/libsqlite/test/attach2.test
new file mode 100644
index 0000000000..2ed427205a
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/attach2.test
@@ -0,0 +1,149 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2003 July 1
+#
+# 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 ATTACH and DETACH commands
+# and related functionality.
+#
+# $Id: attach2.test,v 1.5 2004/02/12 15:31:22 drh Exp $
+#
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Ticket #354
+#
+do_test attach2-1.1 {
+ db eval {
+ CREATE TABLE t1(a,b);
+ CREATE INDEX x1 ON t1(a);
+ }
+ file delete -force test2.db
+ file delete -force test2.db-journal
+ sqlite db2 test2.db
+ db2 eval {
+ CREATE TABLE t1(a,b);
+ CREATE INDEX x1 ON t1(a);
+ }
+ catchsql {
+ ATTACH 'test2.db' AS t2;
+ }
+} {0 {}}
+
+# Ticket #514
+#
+proc db_list {db} {
+ set list {}
+ foreach {idx name file} [execsql {PRAGMA database_list} $db] {
+ lappend list $idx $name
+ }
+ return $list
+}
+db eval {DETACH t2}
+do_test attach2-2.1 {
+ # lock test2.db then try to attach it. Should get an error.
+ db2 eval {BEGIN}
+ catchsql {
+ ATTACH 'test2.db' AS t2;
+ }
+} {1 {database is locked}}
+do_test attach2-2.2 {
+ # make sure test2.db did not get attached.
+ db_list db
+} {0 main 1 temp}
+do_test attach2-2.3 {
+ # unlock test2.db and try to attach again. should work this time.
+ db2 eval {COMMIT}
+ catchsql {
+ ATTACH 'test2.db' AS t2;
+ }
+} {0 {}}
+do_test attach2-2.4 {
+ db_list db
+} {0 main 1 temp 2 t2}
+do_test attach2-2.5 {
+ catchsql {
+ SELECT name FROM t2.sqlite_master;
+ }
+} {0 {t1 x1}}
+do_test attach2-2.6 {
+ # lock test2.db and try to read from it. should get an error.
+ db2 eval BEGIN
+ catchsql {
+ SELECT name FROM t2.sqlite_master;
+ }
+} {1 {database is locked}}
+do_test attach2-2.7 {
+ # but we can still read from test1.db even though test2.db is locked.
+ catchsql {
+ SELECT name FROM main.sqlite_master;
+ }
+} {0 {t1 x1}}
+do_test attach2-2.8 {
+ # start a transaction on test.db even though test2.db is locked.
+ catchsql {
+ BEGIN;
+ INSERT INTO t1 VALUES(8,9);
+ }
+} {0 {}}
+do_test attach2-2.9 {
+ execsql {
+ SELECT * FROM t1
+ }
+} {8 9}
+do_test attach2-2.10 {
+ # now try to write to test2.db. the write should fail
+ catchsql {
+ INSERT INTO t2.t1 VALUES(1,2);
+ }
+} {1 {database is locked}}
+do_test attach2-2.11 {
+ # when the write failed in the previous test, the transaction should
+ # have rolled back.
+ db2 eval ROLLBACK
+ execsql {
+ SELECT * FROM t1
+ }
+} {}
+do_test attach2-2.12 {
+ catchsql {
+ COMMIT
+ }
+} {1 {cannot commit - no transaction is active}}
+
+# Ticket #574: Make sure it works usingi the non-callback API
+#
+do_test attach2-3.1 {
+ db close
+ set DB [sqlite db test.db]
+ set rc [catch {sqlite_compile $DB "ATTACH 'test2.db' AS t2" TAIL} VM]
+ if {$rc} {lappend rc $VM}
+ sqlite_finalize $VM
+ set rc
+} {0}
+do_test attach2-3.2 {
+ set rc [catch {sqlite_compile $DB "DETACH t2" TAIL} VM]
+ if {$rc} {lappend rc $VM}
+ sqlite_finalize $VM
+ set rc
+} {0}
+
+db close
+for {set i 2} {$i<=15} {incr i} {
+ catch {db$i close}
+}
+file delete -force test2.db
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/auth.test b/usr/src/lib/libsqlite/test/auth.test
new file mode 100644
index 0000000000..1719ec7ad1
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/auth.test
@@ -0,0 +1,1895 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2003 April 4
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is testing the ATTACH and DETACH commands
+# and related functionality.
+#
+# $Id: auth.test,v 1.12 2003/12/07 00:24:35 drh Exp $
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# disable this test if the SQLITE_OMIT_AUTHORIZATION macro is
+# defined during compilation.
+
+do_test auth-1.1.1 {
+ db close
+ set ::DB [sqlite db test.db]
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ db authorizer ::auth
+ catchsql {CREATE TABLE t1(a,b,c)}
+} {1 {not authorized}}
+do_test auth-1.1.2 {
+ db errorcode
+} {23}
+do_test auth-1.2 {
+ execsql {SELECT name FROM sqlite_master}
+} {}
+do_test auth-1.3.1 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TABLE"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TABLE t1(a,b,c)}
+} {1 {not authorized}}
+do_test auth-1.3.2 {
+ db errorcode
+} {23}
+do_test auth-1.3.3 {
+ set ::authargs
+} {t1 {} main {}}
+do_test auth-1.4 {
+ execsql {SELECT name FROM sqlite_master}
+} {}
+
+do_test auth-1.5 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TEMP TABLE t1(a,b,c)}
+} {1 {not authorized}}
+do_test auth-1.6 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {}
+do_test auth-1.7.1 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TEMP TABLE t1(a,b,c)}
+} {1 {not authorized}}
+do_test auth-1.7.2 {
+ set ::authargs
+} {t1 {} temp {}}
+do_test auth-1.8 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {}
+
+do_test auth-1.9 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TABLE t1(a,b,c)}
+} {0 {}}
+do_test auth-1.10 {
+ execsql {SELECT name FROM sqlite_master}
+} {}
+do_test auth-1.11 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TABLE"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TABLE t1(a,b,c)}
+} {0 {}}
+do_test auth-1.12 {
+ execsql {SELECT name FROM sqlite_master}
+} {}
+do_test auth-1.13 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TEMP TABLE t1(a,b,c)}
+} {0 {}}
+do_test auth-1.14 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {}
+do_test auth-1.15 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TEMP TABLE t1(a,b,c)}
+} {0 {}}
+do_test auth-1.16 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {}
+
+do_test auth-1.17 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TABLE"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TEMP TABLE t1(a,b,c)}
+} {0 {}}
+do_test auth-1.18 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.19.1 {
+ set ::authargs {}
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_TABLE"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TABLE t2(a,b,c)}
+} {0 {}}
+do_test auth-1.19.2 {
+ set ::authargs
+} {}
+do_test auth-1.20 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+
+do_test auth-1.21.1 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TABLE"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t2}
+} {1 {not authorized}}
+do_test auth-1.21.2 {
+ set ::authargs
+} {t2 {} main {}}
+do_test auth-1.22 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.23.1 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TABLE"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t2}
+} {0 {}}
+do_test auth-1.23.2 {
+ set ::authargs
+} {t2 {} main {}}
+do_test auth-1.24 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+
+do_test auth-1.25 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_TABLE"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t1}
+} {1 {not authorized}}
+do_test auth-1.26 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.27 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_TABLE"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t1}
+} {0 {}}
+do_test auth-1.28 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+
+do_test auth-1.29 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="t2"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {INSERT INTO t2 VALUES(1,2,3)}
+} {1 {not authorized}}
+do_test auth-1.30 {
+ execsql {SELECT * FROM t2}
+} {}
+do_test auth-1.31 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="t2"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {INSERT INTO t2 VALUES(1,2,3)}
+} {0 {}}
+do_test auth-1.32 {
+ execsql {SELECT * FROM t2}
+} {}
+do_test auth-1.33 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="t1"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {INSERT INTO t2 VALUES(1,2,3)}
+} {0 {}}
+do_test auth-1.34 {
+ execsql {SELECT * FROM t2}
+} {1 2 3}
+
+do_test auth-1.35.1 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t2}
+} {1 {access to t2.b is prohibited}}
+do_test auth-1.35.2 {
+ execsql {ATTACH DATABASE 'test.db' AS two}
+ catchsql {SELECT * FROM two.t2}
+} {1 {access to two.t2.b is prohibited}}
+execsql {DETACH DATABASE two}
+do_test auth-1.36 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t2}
+} {0 {1 {} 3}}
+do_test auth-1.37 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t2 WHERE b=2}
+} {0 {}}
+do_test auth-1.38 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="a"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t2 WHERE b=2}
+} {0 {{} 2 3}}
+do_test auth-1.39 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t2 WHERE b IS NULL}
+} {0 {1 {} 3}}
+do_test auth-1.40 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT a,c FROM t2 WHERE b IS NULL}
+} {1 {access to t2.b is prohibited}}
+
+do_test auth-1.41 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_UPDATE" && $arg1=="t2" && $arg2=="b"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {UPDATE t2 SET a=11}
+} {0 {}}
+do_test auth-1.42 {
+ execsql {SELECT * FROM t2}
+} {11 2 3}
+do_test auth-1.43 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_UPDATE" && $arg1=="t2" && $arg2=="b"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {UPDATE t2 SET b=22, c=33}
+} {1 {not authorized}}
+do_test auth-1.44 {
+ execsql {SELECT * FROM t2}
+} {11 2 3}
+do_test auth-1.45 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_UPDATE" && $arg1=="t2" && $arg2=="b"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {UPDATE t2 SET b=22, c=33}
+} {0 {}}
+do_test auth-1.46 {
+ execsql {SELECT * FROM t2}
+} {11 2 33}
+
+do_test auth-1.47 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="t2"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DELETE FROM t2 WHERE a=11}
+} {1 {not authorized}}
+do_test auth-1.48 {
+ execsql {SELECT * FROM t2}
+} {11 2 33}
+do_test auth-1.49 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="t2"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DELETE FROM t2 WHERE a=11}
+} {0 {}}
+do_test auth-1.50 {
+ execsql {SELECT * FROM t2}
+} {11 2 33}
+
+do_test auth-1.51 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_SELECT"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t2}
+} {1 {not authorized}}
+do_test auth-1.52 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_SELECT"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t2}
+} {0 {}}
+do_test auth-1.53 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_SELECT"} {
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t2}
+} {0 {11 2 33}}
+
+set f [open data1.txt w]
+puts $f "7:8:9"
+close $f
+do_test auth-1.54 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_COPY"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {COPY t2 FROM 'data1.txt' USING DELIMITERS ':'}
+} {1 {not authorized}}
+do_test auth-1.55 {
+ set ::authargs
+} {t2 data1.txt main {}}
+do_test auth-1.56 {
+ execsql {SELECT * FROM t2}
+} {11 2 33}
+do_test auth-1.57 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_COPY"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {COPY t2 FROM 'data1.txt' USING DELIMITERS ':'}
+} {0 {}}
+do_test auth-1.58 {
+ set ::authargs
+} {t2 data1.txt main {}}
+do_test auth-1.59 {
+ execsql {SELECT * FROM t2}
+} {11 2 33}
+do_test auth-1.60 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_COPY"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {COPY t2 FROM 'data1.txt' USING DELIMITERS ':'}
+} {0 {}}
+do_test auth-1.61 {
+ set ::authargs
+} {t2 data1.txt main {}}
+do_test auth-1.62 {
+ execsql {SELECT * FROM t2}
+} {11 2 33 7 8 9}
+
+do_test auth-1.63 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t2}
+} {1 {not authorized}}
+do_test auth-1.64 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.65 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="t2"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t2}
+} {1 {not authorized}}
+do_test auth-1.66 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.67 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t1}
+} {1 {not authorized}}
+do_test auth-1.68 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.69 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="t1"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t1}
+} {1 {not authorized}}
+do_test auth-1.70 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+
+do_test auth-1.71 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t2}
+} {0 {}}
+do_test auth-1.72 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.73 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="t2"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t2}
+} {0 {}}
+do_test auth-1.74 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.75 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t1}
+} {0 {}}
+do_test auth-1.76 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.77 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="t1"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TABLE t1}
+} {0 {}}
+do_test auth-1.78 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+
+do_test auth-1.79 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_VIEW"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE VIEW v1 AS SELECT a+1,b+1 FROM t2}
+} {1 {not authorized}}
+do_test auth-1.80 {
+ set ::authargs
+} {v1 {} main {}}
+do_test auth-1.81 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.82 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_VIEW"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE VIEW v1 AS SELECT a+1,b+1 FROM t2}
+} {0 {}}
+do_test auth-1.83 {
+ set ::authargs
+} {v1 {} main {}}
+do_test auth-1.84 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+
+do_test auth-1.85 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_VIEW"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TEMPORARY VIEW v1 AS SELECT a+1,b+1 FROM t2}
+} {1 {not authorized}}
+do_test auth-1.86 {
+ set ::authargs
+} {v1 {} temp {}}
+do_test auth-1.87 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.88 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_VIEW"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TEMPORARY VIEW v1 AS SELECT a+1,b+1 FROM t2}
+} {0 {}}
+do_test auth-1.89 {
+ set ::authargs
+} {v1 {} temp {}}
+do_test auth-1.90 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+
+do_test auth-1.91 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE VIEW v1 AS SELECT a+1,b+1 FROM t2}
+} {1 {not authorized}}
+do_test auth-1.92 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.93 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE VIEW v1 AS SELECT a+1,b+1 FROM t2}
+} {0 {}}
+do_test auth-1.94 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+
+do_test auth-1.95 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TEMPORARY VIEW v1 AS SELECT a+1,b+1 FROM t2}
+} {1 {not authorized}}
+do_test auth-1.96 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.97 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE TEMPORARY VIEW v1 AS SELECT a+1,b+1 FROM t2}
+} {0 {}}
+do_test auth-1.98 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+
+do_test auth-1.99 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE VIEW v2 AS SELECT a+1,b+1 FROM t2;
+ DROP VIEW v2
+ }
+} {1 {not authorized}}
+do_test auth-1.100 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 v2}
+do_test auth-1.101 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_VIEW"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP VIEW v2}
+} {1 {not authorized}}
+do_test auth-1.102 {
+ set ::authargs
+} {v2 {} main {}}
+do_test auth-1.103 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 v2}
+do_test auth-1.104 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP VIEW v2}
+} {0 {}}
+do_test auth-1.105 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 v2}
+do_test auth-1.106 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_VIEW"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP VIEW v2}
+} {0 {}}
+do_test auth-1.107 {
+ set ::authargs
+} {v2 {} main {}}
+do_test auth-1.108 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 v2}
+do_test auth-1.109 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_VIEW"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP VIEW v2}
+} {0 {}}
+do_test auth-1.110 {
+ set ::authargs
+} {v2 {} main {}}
+do_test auth-1.111 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+
+
+do_test auth-1.112 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TEMP VIEW v1 AS SELECT a+1,b+1 FROM t1;
+ DROP VIEW v1
+ }
+} {1 {not authorized}}
+do_test auth-1.113 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 v1}
+do_test auth-1.114 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_VIEW"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP VIEW v1}
+} {1 {not authorized}}
+do_test auth-1.115 {
+ set ::authargs
+} {v1 {} temp {}}
+do_test auth-1.116 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 v1}
+do_test auth-1.117 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP VIEW v1}
+} {0 {}}
+do_test auth-1.118 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 v1}
+do_test auth-1.119 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_VIEW"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP VIEW v1}
+} {0 {}}
+do_test auth-1.120 {
+ set ::authargs
+} {v1 {} temp {}}
+do_test auth-1.121 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 v1}
+do_test auth-1.122 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_VIEW"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP VIEW v1}
+} {0 {}}
+do_test auth-1.123 {
+ set ::authargs
+} {v1 {} temp {}}
+do_test auth-1.124 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+
+do_test auth-1.125 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TRIGGER r2 DELETE on t2 BEGIN
+ SELECT NULL;
+ END;
+ }
+} {1 {not authorized}}
+do_test auth-1.126 {
+ set ::authargs
+} {r2 t2 main {}}
+do_test auth-1.127 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.128 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TRIGGER r2 DELETE on t2 BEGIN
+ SELECT NULL;
+ END;
+ }
+} {1 {not authorized}}
+do_test auth-1.129 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.130 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TRIGGER r2 DELETE on t2 BEGIN
+ SELECT NULL;
+ END;
+ }
+} {0 {}}
+do_test auth-1.131 {
+ set ::authargs
+} {r2 t2 main {}}
+do_test auth-1.132 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.133 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TRIGGER r2 DELETE on t2 BEGIN
+ SELECT NULL;
+ END;
+ }
+} {0 {}}
+do_test auth-1.134 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.135 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TABLE tx(id);
+ CREATE TRIGGER r2 AFTER INSERT ON t2 BEGIN
+ INSERT INTO tx VALUES(NEW.rowid);
+ END;
+ }
+} {0 {}}
+do_test auth-1.136.1 {
+ set ::authargs
+} {r2 t2 main {}}
+do_test auth-1.136.2 {
+ execsql {
+ SELECT name FROM sqlite_master WHERE type='trigger'
+ }
+} {r2}
+do_test auth-1.136.3 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ lappend ::authargs $code $arg1 $arg2 $arg3 $arg4
+ return SQLITE_OK
+ }
+ set ::authargs {}
+ execsql {
+ INSERT INTO t2 VALUES(1,2,3);
+ }
+ set ::authargs
+} {SQLITE_INSERT t2 {} main {} SQLITE_INSERT tx {} main r2 SQLITE_READ t2 ROWID main r2}
+do_test auth-1.136.4 {
+ execsql {
+ SELECT * FROM tx;
+ }
+} {3}
+do_test auth-1.137 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 tx r2}
+do_test auth-1.138 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TRIGGER r1 DELETE on t1 BEGIN
+ SELECT NULL;
+ END;
+ }
+} {1 {not authorized}}
+do_test auth-1.139 {
+ set ::authargs
+} {r1 t1 temp {}}
+do_test auth-1.140 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.141 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TRIGGER r1 DELETE on t1 BEGIN
+ SELECT NULL;
+ END;
+ }
+} {1 {not authorized}}
+do_test auth-1.142 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.143 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TRIGGER r1 DELETE on t1 BEGIN
+ SELECT NULL;
+ END;
+ }
+} {0 {}}
+do_test auth-1.144 {
+ set ::authargs
+} {r1 t1 temp {}}
+do_test auth-1.145 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.146 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TRIGGER r1 DELETE on t1 BEGIN
+ SELECT NULL;
+ END;
+ }
+} {0 {}}
+do_test auth-1.147 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.148 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ CREATE TRIGGER r1 DELETE on t1 BEGIN
+ SELECT NULL;
+ END;
+ }
+} {0 {}}
+do_test auth-1.149 {
+ set ::authargs
+} {r1 t1 temp {}}
+do_test auth-1.150 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 r1}
+
+do_test auth-1.151 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TRIGGER r2}
+} {1 {not authorized}}
+do_test auth-1.152 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 tx r2}
+do_test auth-1.153 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TRIGGER r2}
+} {1 {not authorized}}
+do_test auth-1.154 {
+ set ::authargs
+} {r2 t2 main {}}
+do_test auth-1.155 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 tx r2}
+do_test auth-1.156 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TRIGGER r2}
+} {0 {}}
+do_test auth-1.157 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 tx r2}
+do_test auth-1.158 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TRIGGER r2}
+} {0 {}}
+do_test auth-1.159 {
+ set ::authargs
+} {r2 t2 main {}}
+do_test auth-1.160 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 tx r2}
+do_test auth-1.161 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TRIGGER r2}
+} {0 {}}
+do_test auth-1.162 {
+ set ::authargs
+} {r2 t2 main {}}
+do_test auth-1.163 {
+ execsql {
+ DROP TABLE tx;
+ DELETE FROM t2 WHERE a=1 AND b=2 AND c=3;
+ SELECT name FROM sqlite_master;
+ }
+} {t2}
+
+do_test auth-1.164 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TRIGGER r1}
+} {1 {not authorized}}
+do_test auth-1.165 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 r1}
+do_test auth-1.166 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TRIGGER r1}
+} {1 {not authorized}}
+do_test auth-1.167 {
+ set ::authargs
+} {r1 t1 temp {}}
+do_test auth-1.168 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 r1}
+do_test auth-1.169 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TRIGGER r1}
+} {0 {}}
+do_test auth-1.170 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 r1}
+do_test auth-1.171 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TRIGGER r1}
+} {0 {}}
+do_test auth-1.172 {
+ set ::authargs
+} {r1 t1 temp {}}
+do_test auth-1.173 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 r1}
+do_test auth-1.174 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_TRIGGER"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP TRIGGER r1}
+} {0 {}}
+do_test auth-1.175 {
+ set ::authargs
+} {r1 t1 temp {}}
+do_test auth-1.176 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+
+do_test auth-1.177 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE INDEX i2 ON t2(a)}
+} {1 {not authorized}}
+do_test auth-1.178 {
+ set ::authargs
+} {i2 t2 main {}}
+do_test auth-1.179 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.180 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE INDEX i2 ON t2(a)}
+} {1 {not authorized}}
+do_test auth-1.181 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.182 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE INDEX i2 ON t2(b)}
+} {0 {}}
+do_test auth-1.183 {
+ set ::authargs
+} {i2 t2 main {}}
+do_test auth-1.184 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.185 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE INDEX i2 ON t2(b)}
+} {0 {}}
+do_test auth-1.186 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+do_test auth-1.187 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE INDEX i2 ON t2(a)}
+} {0 {}}
+do_test auth-1.188 {
+ set ::authargs
+} {i2 t2 main {}}
+do_test auth-1.189 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 i2}
+
+do_test auth-1.190 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE INDEX i1 ON t1(a)}
+} {1 {not authorized}}
+do_test auth-1.191 {
+ set ::authargs
+} {i1 t1 temp {}}
+do_test auth-1.192 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.193 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE INDEX i1 ON t1(b)}
+} {1 {not authorized}}
+do_test auth-1.194 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.195 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE INDEX i1 ON t1(b)}
+} {0 {}}
+do_test auth-1.196 {
+ set ::authargs
+} {i1 t1 temp {}}
+do_test auth-1.197 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.198 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_INSERT" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE INDEX i1 ON t1(c)}
+} {0 {}}
+do_test auth-1.199 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+do_test auth-1.200 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_CREATE_TEMP_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {CREATE INDEX i1 ON t1(a)}
+} {0 {}}
+do_test auth-1.201 {
+ set ::authargs
+} {i1 t1 temp {}}
+do_test auth-1.202 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 i1}
+
+do_test auth-1.203 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP INDEX i2}
+} {1 {not authorized}}
+do_test auth-1.204 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 i2}
+do_test auth-1.205 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP INDEX i2}
+} {1 {not authorized}}
+do_test auth-1.206 {
+ set ::authargs
+} {i2 t2 main {}}
+do_test auth-1.207 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 i2}
+do_test auth-1.208 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP INDEX i2}
+} {0 {}}
+do_test auth-1.209 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 i2}
+do_test auth-1.210 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP INDEX i2}
+} {0 {}}
+do_test auth-1.211 {
+ set ::authargs
+} {i2 t2 main {}}
+do_test auth-1.212 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2 i2}
+do_test auth-1.213 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP INDEX i2}
+} {0 {}}
+do_test auth-1.214 {
+ set ::authargs
+} {i2 t2 main {}}
+do_test auth-1.215 {
+ execsql {SELECT name FROM sqlite_master}
+} {t2}
+
+do_test auth-1.216 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP INDEX i1}
+} {1 {not authorized}}
+do_test auth-1.217 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 i1}
+do_test auth-1.218 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP INDEX i1}
+} {1 {not authorized}}
+do_test auth-1.219 {
+ set ::authargs
+} {i1 t1 temp {}}
+do_test auth-1.220 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 i1}
+do_test auth-1.221 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DELETE" && $arg1=="sqlite_temp_master"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP INDEX i1}
+} {0 {}}
+do_test auth-1.222 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 i1}
+do_test auth-1.223 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP INDEX i1}
+} {0 {}}
+do_test auth-1.224 {
+ set ::authargs
+} {i1 t1 temp {}}
+do_test auth-1.225 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1 i1}
+do_test auth-1.226 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DROP_TEMP_INDEX"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {DROP INDEX i1}
+} {0 {}}
+do_test auth-1.227 {
+ set ::authargs
+} {i1 t1 temp {}}
+do_test auth-1.228 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {t1}
+
+do_test auth-1.229 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_PRAGMA"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {PRAGMA full_column_names=on}
+} {1 {not authorized}}
+do_test auth-1.230 {
+ set ::authargs
+} {full_column_names on {} {}}
+do_test auth-1.231 {
+ execsql2 {SELECT a FROM t2}
+} {a 11 a 7}
+do_test auth-1.232 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_PRAGMA"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {PRAGMA full_column_names=on}
+} {0 {}}
+do_test auth-1.233 {
+ set ::authargs
+} {full_column_names on {} {}}
+do_test auth-1.234 {
+ execsql2 {SELECT a FROM t2}
+} {a 11 a 7}
+do_test auth-1.235 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_PRAGMA"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {PRAGMA full_column_names=on}
+} {0 {}}
+do_test auth-1.236 {
+ execsql2 {SELECT a FROM t2}
+} {t2.a 11 t2.a 7}
+do_test auth-1.237 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_PRAGMA"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ catchsql {PRAGMA full_column_names=OFF}
+} {0 {}}
+do_test auth-1.238 {
+ set ::authargs
+} {full_column_names OFF {} {}}
+do_test auth-1.239 {
+ execsql2 {SELECT a FROM t2}
+} {a 11 a 7}
+
+do_test auth-1.240 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_TRANSACTION"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {BEGIN}
+} {1 {not authorized}}
+do_test auth-1.241 {
+ set ::authargs
+} {BEGIN {} {} {}}
+do_test auth-1.242 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_TRANSACTION" && $arg1!="BEGIN"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {BEGIN; INSERT INTO t2 VALUES(44,55,66); COMMIT}
+} {1 {not authorized}}
+do_test auth-1.243 {
+ set ::authargs
+} {COMMIT {} {} {}}
+do_test auth-1.244 {
+ execsql {SELECT * FROM t2}
+} {11 2 33 7 8 9 44 55 66}
+do_test auth-1.245 {
+ catchsql {ROLLBACK}
+} {1 {not authorized}}
+do_test auth-1.246 {
+ set ::authargs
+} {ROLLBACK {} {} {}}
+do_test auth-1.247 {
+ catchsql {END TRANSACTION}
+} {1 {not authorized}}
+do_test auth-1.248 {
+ set ::authargs
+} {COMMIT {} {} {}}
+do_test auth-1.249 {
+ db authorizer {}
+ catchsql {ROLLBACK}
+} {0 {}}
+do_test auth-1.250 {
+ execsql {SELECT * FROM t2}
+} {11 2 33 7 8 9}
+
+# ticket #340 - authorization for ATTACH and DETACH.
+#
+do_test auth-1.251 {
+ db authorizer ::auth
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_ATTACH"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ ATTACH DATABASE ':memory:' AS test1
+ }
+} {0 {}}
+do_test auth-1.252 {
+ set ::authargs
+} {:memory: {} {} {}}
+do_test auth-1.253 {
+ catchsql {DETACH DATABASE test1}
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_ATTACH"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ ATTACH DATABASE ':memory:' AS test1;
+ }
+} {1 {not authorized}}
+do_test auth-1.254 {
+ lindex [execsql {PRAGMA database_list}] 7
+} {}
+do_test auth-1.255 {
+ catchsql {DETACH DATABASE test1}
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_ATTACH"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ ATTACH DATABASE ':memory:' AS test1;
+ }
+} {0 {}}
+do_test auth-1.256 {
+ lindex [execsql {PRAGMA database_list}] 7
+} {}
+do_test auth-1.257 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DETACH"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_OK
+ }
+ return SQLITE_OK
+ }
+ execsql {ATTACH DATABASE ':memory:' AS test1}
+ catchsql {
+ DETACH DATABASE test1;
+ }
+} {0 {}}
+do_test auth-1.258 {
+ lindex [execsql {PRAGMA database_list}] 7
+} {}
+do_test auth-1.259 {
+ execsql {ATTACH DATABASE ':memory:' AS test1}
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DETACH"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ DETACH DATABASE test1;
+ }
+} {0 {}}
+do_test auth-1.260 {
+ lindex [execsql {PRAGMA database_list}] 7
+} {test1}
+do_test auth-1.261 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_DETACH"} {
+ set ::authargs [list $arg1 $arg2 $arg3 $arg4]
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ catchsql {
+ DETACH DATABASE test1;
+ }
+} {1 {not authorized}}
+do_test auth-1.262 {
+ lindex [execsql {PRAGMA database_list}] 7
+} {test1}
+db authorizer {}
+execsql {DETACH DATABASE test1}
+
+
+do_test auth-2.1 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t3" && $arg2=="x"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
+ }
+ db authorizer ::auth
+ execsql {CREATE TABLE t3(x INTEGER PRIMARY KEY, y, z)}
+ catchsql {SELECT * FROM t3}
+} {1 {access to t3.x is prohibited}}
+do_test auth-2.1 {
+ catchsql {SELECT y,z FROM t3}
+} {0 {}}
+do_test auth-2.2 {
+ catchsql {SELECT ROWID,y,z FROM t3}
+} {1 {access to t3.x is prohibited}}
+do_test auth-2.3 {
+ catchsql {SELECT OID,y,z FROM t3}
+} {1 {access to t3.x is prohibited}}
+do_test auth-2.4 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t3" && $arg2=="x"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ execsql {INSERT INTO t3 VALUES(44,55,66)}
+ catchsql {SELECT * FROM t3}
+} {0 {{} 55 66}}
+do_test auth-2.5 {
+ catchsql {SELECT rowid,y,z FROM t3}
+} {0 {{} 55 66}}
+do_test auth-2.6 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t3" && $arg2=="ROWID"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t3}
+} {0 {44 55 66}}
+do_test auth-2.7 {
+ catchsql {SELECT ROWID,y,z FROM t3}
+} {0 {44 55 66}}
+do_test auth-2.8 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="ROWID"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT ROWID,b,c FROM t2}
+} {0 {{} 2 33 {} 8 9}}
+do_test auth-2.9.1 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="ROWID"} {
+ return bogus
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT ROWID,b,c FROM t2}
+} {1 {illegal return value (999) from the authorization function - should be SQLITE_OK, SQLITE_IGNORE, or SQLITE_DENY}}
+do_test auth-2.9.2 {
+ db errorcode
+} {21}
+do_test auth-2.10 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_SELECT"} {
+ return bogus
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT ROWID,b,c FROM t2}
+} {1 {illegal return value (1) from the authorization function - should be SQLITE_OK, SQLITE_IGNORE, or SQLITE_DENY}}
+do_test auth-2.11.1 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg2=="a"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t2, t3}
+} {0 {{} 2 33 44 55 66 {} 8 9 44 55 66}}
+do_test auth-2.11.2 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg2=="x"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ catchsql {SELECT * FROM t2, t3}
+} {0 {11 2 33 {} 55 66 7 8 9 {} 55 66}}
+
+# Make sure the OLD and NEW pseudo-tables of a trigger get authorized.
+#
+do_test auth-3.1 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ return SQLITE_OK
+ }
+ execsql {
+ CREATE TABLE tx(a1,a2,b1,b2,c1,c2);
+ CREATE TRIGGER r1 AFTER UPDATE ON t2 FOR EACH ROW BEGIN
+ INSERT INTO tx VALUES(OLD.a,NEW.a,OLD.b,NEW.b,OLD.c,NEW.c);
+ END;
+ UPDATE t2 SET a=a+1;
+ SELECT * FROM tx;
+ }
+} {11 12 2 2 33 33 7 8 8 8 9 9}
+do_test auth-3.2 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="c"} {
+ return SQLITE_IGNORE
+ }
+ return SQLITE_OK
+ }
+ execsql {
+ DELETE FROM tx;
+ UPDATE t2 SET a=a+100;
+ SELECT * FROM tx;
+ }
+} {12 112 2 2 {} {} 8 108 8 8 {} {}}
+
+# Make sure the names of views and triggers are passed on on arg4.
+#
+do_test auth-4.1 {
+ proc auth {code arg1 arg2 arg3 arg4} {
+ lappend ::authargs $code $arg1 $arg2 $arg3 $arg4
+ return SQLITE_OK
+ }
+ set authargs {}
+ execsql {
+ UPDATE t2 SET a=a+1;
+ }
+ set authargs
+} [list \
+ SQLITE_READ t2 a main {} \
+ SQLITE_UPDATE t2 a main {} \
+ SQLITE_INSERT tx {} main r1 \
+ SQLITE_READ t2 a main r1 \
+ SQLITE_READ t2 a main r1 \
+ SQLITE_READ t2 b main r1 \
+ SQLITE_READ t2 b main r1 \
+ SQLITE_READ t2 c main r1 \
+ SQLITE_READ t2 c main r1]
+do_test auth-4.2 {
+ execsql {
+ CREATE VIEW v1 AS SELECT a+b AS x FROM t2;
+ CREATE TABLE v1chng(x1,x2);
+ CREATE TRIGGER r2 INSTEAD OF UPDATE ON v1 BEGIN
+ INSERT INTO v1chng VALUES(OLD.x,NEW.x);
+ END;
+ SELECT * FROM v1;
+ }
+} {115 117}
+do_test auth-4.3 {
+ set authargs {}
+ execsql {
+ UPDATE v1 SET x=1 WHERE x=117
+ }
+ set authargs
+} [list \
+ SQLITE_UPDATE v1 x main {} \
+ SQLITE_READ v1 x main {} \
+ SQLITE_SELECT {} {} {} v1 \
+ SQLITE_READ t2 a main v1 \
+ SQLITE_READ t2 b main v1 \
+ SQLITE_INSERT v1chng {} main r2 \
+ SQLITE_READ v1 x main r2 \
+ SQLITE_READ v1 x main r2]
+do_test auth-4.4 {
+ execsql {
+ CREATE TRIGGER r3 INSTEAD OF DELETE ON v1 BEGIN
+ INSERT INTO v1chng VALUES(OLD.x,NULL);
+ END;
+ SELECT * FROM v1;
+ }
+} {115 117}
+do_test auth-4.5 {
+ set authargs {}
+ execsql {
+ DELETE FROM v1 WHERE x=117
+ }
+ set authargs
+} [list \
+ SQLITE_DELETE v1 {} main {} \
+ SQLITE_READ v1 x main {} \
+ SQLITE_SELECT {} {} {} v1 \
+ SQLITE_READ t2 a main v1 \
+ SQLITE_READ t2 b main v1 \
+ SQLITE_INSERT v1chng {} main r3 \
+ SQLITE_READ v1 x main r3]
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/bigfile.test b/usr/src/lib/libsqlite/test/bigfile.test
new file mode 100644
index 0000000000..d3d0d21fb9
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/bigfile.test
@@ -0,0 +1,180 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 November 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 regression tests for SQLite library. The
+# focus of this script testing the ability of SQLite to handle database
+# files larger than 4GB.
+#
+# $Id: bigfile.test,v 1.3 2003/12/19 12:31:22 drh Exp $
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# These tests only work for Tcl version 8.4 and later. Prior to 8.4,
+# Tcl was unable to handle large files.
+#
+scan $::tcl_version %f vx
+if {$vx<8.4} return
+
+# This is the md5 checksum of all the data in table t1 as created
+# by the first test. We will use this number to make sure that data
+# never changes.
+#
+set MAGIC_SUM {593f1efcfdbe698c28b4b1b693f7e4cf}
+
+do_test bigfile-1.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES('abcdefghijklmnopqrstuvwxyz');
+ INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
+ INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
+ INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
+ INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
+ INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
+ INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
+ INSERT INTO t1 SELECT rowid || ' ' || x FROM t1;
+ COMMIT;
+ }
+ execsql {
+ SELECT md5sum(x) FROM t1;
+ }
+} $::MAGIC_SUM
+
+# Try to create a large file - a file that is larger than 2^32 bytes.
+# If this fails, it means that the system being tested does not support
+# large files. So skip all of the remaining tests in this file.
+#
+db close
+if {[catch {fake_big_file 4096 test.db}]} {
+ puts "**** Unable to create a file larger than 4096 MB. *****"
+ finish_test
+ return
+}
+
+do_test bigfile-1.2 {
+ sqlite db test.db
+ execsql {
+ SELECT md5sum(x) FROM t1;
+ }
+} $::MAGIC_SUM
+
+# The previous test may fail on some systems because they are unable
+# to handle large files. If that is so, then skip all of the following
+# tests. We will know the above test failed because the "db" command
+# does not exist.
+#
+if {[llength [info command db]]>0} {
+
+do_test bigfile-1.3 {
+ execsql {
+ CREATE TABLE t2 AS SELECT * FROM t1;
+ SELECT md5sum(x) FROM t2;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.4 {
+ db close
+ sqlite db test.db
+ execsql {
+ SELECT md5sum(x) FROM t1;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.5 {
+ execsql {
+ SELECT md5sum(x) FROM t2;
+ }
+} $::MAGIC_SUM
+
+db close
+if {[catch {fake_big_file 8192 test.db}]} {
+ puts "**** Unable to create a file larger than 8192 MB. *****"
+ finish_test
+ return
+}
+
+do_test bigfile-1.6 {
+ sqlite db test.db
+ execsql {
+ SELECT md5sum(x) FROM t1;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.7 {
+ execsql {
+ CREATE TABLE t3 AS SELECT * FROM t1;
+ SELECT md5sum(x) FROM t3;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.8 {
+ db close
+ sqlite db test.db
+ execsql {
+ SELECT md5sum(x) FROM t1;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.9 {
+ execsql {
+ SELECT md5sum(x) FROM t2;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.10 {
+ execsql {
+ SELECT md5sum(x) FROM t3;
+ }
+} $::MAGIC_SUM
+
+db close
+if {[catch {fake_big_file 16384 test.db}]} {
+ puts "**** Unable to create a file larger than 16384 MB. *****"
+ finish_test
+ return
+}
+
+do_test bigfile-1.11 {
+ sqlite db test.db
+ execsql {
+ SELECT md5sum(x) FROM t1;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.12 {
+ execsql {
+ CREATE TABLE t4 AS SELECT * FROM t1;
+ SELECT md5sum(x) FROM t4;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.13 {
+ db close
+ sqlite db test.db
+ execsql {
+ SELECT md5sum(x) FROM t1;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.14 {
+ execsql {
+ SELECT md5sum(x) FROM t2;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.15 {
+ execsql {
+ SELECT md5sum(x) FROM t3;
+ }
+} $::MAGIC_SUM
+do_test bigfile-1.16 {
+ execsql {
+ SELECT md5sum(x) FROM t3;
+ }
+} $::MAGIC_SUM
+
+} ;# End of the "if( db command exists )"
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/bigrow.test b/usr/src/lib/libsqlite/test/bigrow.test
new file mode 100644
index 0000000000..b9aed8e7e1
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/bigrow.test
@@ -0,0 +1,218 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 23
+#
+# 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 stressing the library by putting large amounts
+# of data in a single row of a table.
+#
+# $Id: bigrow.test,v 1.4 2001/11/24 00:31:47 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Make a big string that we can use for test data
+#
+do_test bigrow-1.0 {
+ set ::bigstr {}
+ for {set i 1} {$i<=9999} {incr i} {
+ set sep [string index "abcdefghijklmnopqrstuvwxyz" [expr {$i%26}]]
+ append ::bigstr "$sep [format %04d $i] "
+ }
+ string length $::bigstr
+} {69993}
+
+# Make a table into which we can insert some but records.
+#
+do_test bigrow-1.1 {
+ execsql {
+ CREATE TABLE t1(a text, b text, c text);
+ SELECT name FROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name
+ }
+} {t1}
+
+do_test bigrow-1.2 {
+ set ::big1 [string range $::bigstr 0 65519]
+ set sql "INSERT INTO t1 VALUES('abc',"
+ append sql "'$::big1', 'xyz');"
+ execsql $sql
+ execsql {SELECT a, c FROM t1}
+} {abc xyz}
+do_test bigrow-1.3 {
+ execsql {SELECT b FROM t1}
+} [list $::big1]
+do_test bigrow-1.4 {
+ set ::big2 [string range $::bigstr 0 65520]
+ set sql "INSERT INTO t1 VALUES('abc2',"
+ append sql "'$::big2', 'xyz2');"
+ set r [catch {execsql $sql} msg]
+ lappend r $msg
+} {0 {}}
+do_test bigrow-1.4.1 {
+ execsql {SELECT b FROM t1 ORDER BY c}
+} [list $::big1 $::big2]
+do_test bigrow-1.4.2 {
+ execsql {SELECT c FROM t1 ORDER BY c}
+} {xyz xyz2}
+do_test bigrow-1.4.3 {
+ execsql {DELETE FROM t1 WHERE a='abc2'}
+ execsql {SELECT c FROM t1}
+} {xyz}
+
+do_test bigrow-1.5 {
+ execsql {
+ UPDATE t1 SET a=b, b=a;
+ SELECT b,c FROM t1
+ }
+} {abc xyz}
+do_test bigrow-1.6 {
+ execsql {
+ SELECT * FROM t1
+ }
+} [list $::big1 abc xyz]
+do_test bigrow-1.7 {
+ execsql {
+ INSERT INTO t1 VALUES('1','2','3');
+ INSERT INTO t1 VALUES('A','B','C');
+ SELECT b FROM t1 WHERE a=='1';
+ }
+} {2}
+do_test bigrow-1.8 {
+ execsql "SELECT b FROM t1 WHERE a=='$::big1'"
+} {abc}
+do_test bigrow-1.9 {
+ execsql "SELECT b FROM t1 WHERE a!='$::big1' ORDER BY a"
+} {2 B}
+
+# Try doing some indexing on big columns
+#
+do_test bigrow-2.1 {
+ execsql {
+ CREATE INDEX i1 ON t1(a)
+ }
+ execsql "SELECT b FROM t1 WHERE a=='$::big1'"
+} {abc}
+do_test bigrow-2.2 {
+ execsql {
+ UPDATE t1 SET a=b, b=a
+ }
+ execsql "SELECT b FROM t1 WHERE a=='abc'"
+} [list $::big1]
+do_test bigrow-2.3 {
+ execsql {
+ UPDATE t1 SET a=b, b=a
+ }
+ execsql "SELECT b FROM t1 WHERE a=='$::big1'"
+} {abc}
+catch {unset ::bigstr}
+catch {unset ::big1}
+catch {unset ::big2}
+
+# Mosts of the tests above were created back when rows were limited in
+# size to 64K. Now rows can be much bigger. Test that logic. Also
+# make sure things work correctly at the transition boundries between
+# row sizes of 256 to 257 bytes and from 65536 to 65537 bytes.
+#
+# We begin by testing the 256..257 transition.
+#
+do_test bigrow-3.1 {
+ execsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c) VALUES('one','abcdefghijklmnopqrstuvwxyz0123','hi');
+ }
+ execsql {SELECT a,length(b),c FROM t1}
+} {one 30 hi}
+do_test bigrow-3.2 {
+ execsql {
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ }
+ execsql {SELECT a,length(b),c FROM t1}
+} {one 240 hi}
+for {set i 1} {$i<10} {incr i} {
+ do_test bigrow-3.3.$i {
+ execsql "UPDATE t1 SET b=b||'$i'"
+ execsql {SELECT a,length(b),c FROM t1}
+ } "one [expr {240+$i}] hi"
+}
+
+# Now test the 65536..65537 row-size transition.
+#
+do_test bigrow-4.1 {
+ execsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c) VALUES('one','abcdefghijklmnopqrstuvwxyz0123','hi');
+ }
+ execsql {SELECT a,length(b),c FROM t1}
+} {one 30 hi}
+do_test bigrow-4.2 {
+ execsql {
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ }
+ execsql {SELECT a,length(b),c FROM t1}
+} {one 122880 hi}
+do_test bigrow-4.3 {
+ execsql {
+ UPDATE t1 SET b=substr(b,1,65515)
+ }
+ execsql {SELECT a,length(b),c FROM t1}
+} {one 65515 hi}
+for {set i 1} {$i<10} {incr i} {
+ do_test bigrow-4.4.$i {
+ execsql "UPDATE t1 SET b=b||'$i'"
+ execsql {SELECT a,length(b),c FROM t1}
+ } "one [expr {65515+$i}] hi"
+}
+
+# Check to make sure the library recovers safely if a row contains
+# too much data.
+#
+do_test bigrow-5.1 {
+ execsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c) VALUES('one','abcdefghijklmnopqrstuvwxyz0123','hi');
+ }
+ execsql {SELECT a,length(b),c FROM t1}
+} {one 30 hi}
+set i 1
+for {set sz 60} {$sz<1048560} {incr sz $sz} {
+ do_test bigrow-5.2.$i {
+ execsql {
+ UPDATE t1 SET b=b||b;
+ SELECT a,length(b),c FROM t1;
+ }
+ } "one $sz hi"
+ incr i
+}
+do_test bigrow-5.3 {
+ set r [catch {execsql {UPDATE t1 SET b=b||b}} msg]
+ lappend r $msg
+} {1 {too much data for one table row}}
+do_test bigrow-5.4 {
+ execsql {DROP TABLE t1}
+} {}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/bind.test b/usr/src/lib/libsqlite/test/bind.test
new file mode 100644
index 0000000000..0f87255666
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/bind.test
@@ -0,0 +1,75 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2003 September 6
+#
+# 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 testing the sqlite_bind API.
+#
+# $Id: bind.test,v 1.1 2003/09/06 22:45:21 drh Exp $
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test bind-1.1 {
+ db close
+ set DB [sqlite db test.db]
+ execsql {CREATE TABLE t1(a,b,c)}
+ set VM [sqlite_compile $DB {INSERT INTO t1 VALUES(?,?,?)} TAIL]
+ set TAIL
+} {}
+do_test bind-1.2 {
+ sqlite_step $VM N VALUES COLNAMES
+} {SQLITE_DONE}
+do_test bind-1.3 {
+ execsql {SELECT rowid, * FROM t1}
+} {1 {} {} {}}
+do_test bind-1.4 {
+ sqlite_reset $VM
+ sqlite_bind $VM 1 {test value 1} normal
+ sqlite_step $VM N VALUES COLNAMES
+} SQLITE_DONE
+do_test bind-1.5 {
+ execsql {SELECT rowid, * FROM t1}
+} {1 {} {} {} 2 {test value 1} {} {}}
+do_test bind-1.6 {
+ sqlite_reset $VM
+ sqlite_bind $VM 3 {'test value 2'} normal
+ sqlite_step $VM N VALUES COLNAMES
+} SQLITE_DONE
+do_test bind-1.7 {
+ execsql {SELECT rowid, * FROM t1}
+} {1 {} {} {} 2 {test value 1} {} {} 3 {test value 1} {} {'test value 2'}}
+do_test bind-1.8 {
+ sqlite_reset $VM
+ set sqlite_static_bind_value 123
+ sqlite_bind $VM 1 {} static
+ sqlite_bind $VM 2 {abcdefg} normal
+ sqlite_bind $VM 3 {} null
+ execsql {DELETE FROM t1}
+ sqlite_step $VM N VALUES COLNAMES
+ execsql {SELECT rowid, * FROM t1}
+} {1 123 abcdefg {}}
+do_test bind-1.9 {
+ sqlite_reset $VM
+ sqlite_bind $VM 1 {456} normal
+ sqlite_step $VM N VALUES COLNAMES
+ execsql {SELECT rowid, * FROM t1}
+} {1 123 abcdefg {} 2 456 abcdefg {}}
+
+
+do_test bind-1.99 {
+ sqlite_finalize $VM
+} {}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/btree.test b/usr/src/lib/libsqlite/test/btree.test
new file mode 100644
index 0000000000..9d1c4153d7
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/btree.test
@@ -0,0 +1,1023 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 btree database backend
+#
+# $Id: btree.test,v 1.15 2004/02/10 01:54:28 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+if {[info commands btree_open]!="" && $SQLITE_PAGE_SIZE==1024
+ && $SQLITE_USABLE_SIZE==1024} {
+
+# Basic functionality. Open and close a database.
+#
+do_test btree-1.1 {
+ file delete -force test1.bt
+ file delete -force test1.bt-journal
+ set rc [catch {btree_open test1.bt} ::b1]
+} {0}
+
+# The second element of the list returned by btree_pager_stats is the
+# number of pages currently checked out. We'll be checking this value
+# frequently during this test script, to make sure the btree library
+# is properly releasing the pages it checks out, and thus avoiding
+# page leaks.
+#
+do_test btree-1.1.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {0}
+do_test btree-1.2 {
+ set rc [catch {btree_open test1.bt} ::b2]
+} {0}
+do_test btree-1.3 {
+ set rc [catch {btree_close $::b2} msg]
+ lappend rc $msg
+} {0 {}}
+
+# Do an insert and verify that the database file grows in size.
+#
+do_test btree-1.4 {
+ set rc [catch {btree_begin_transaction $::b1} msg]
+ lappend rc $msg
+} {0 {}}
+do_test btree-1.4.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {1}
+do_test btree-1.5 {
+ set rc [catch {btree_cursor $::b1 2 1} ::c1]
+ if {$rc} {lappend rc $::c1}
+ set rc
+} {0}
+do_test btree-1.6 {
+ set rc [catch {btree_insert $::c1 one 1.00} msg]
+ lappend rc $msg
+} {0 {}}
+do_test btree-1.7 {
+ btree_key $::c1
+} {one}
+do_test btree-1.8 {
+ btree_data $::c1
+} {1.00}
+do_test btree-1.9 {
+ set rc [catch {btree_close_cursor $::c1} msg]
+ lappend rc $msg
+} {0 {}}
+do_test btree-1.10 {
+ set rc [catch {btree_commit $::b1} msg]
+ lappend rc $msg
+} {0 {}}
+do_test btree-1.11 {
+ file size test1.bt
+} {2048}
+do_test btree-1.12 {
+ lindex [btree_pager_stats $::b1] 1
+} {0}
+
+# Reopen the database and attempt to read the record that we wrote.
+#
+do_test btree-2.1 {
+ set rc [catch {btree_cursor $::b1 2 1} ::c1]
+ if {$rc} {lappend rc $::c1}
+ set rc
+} {0}
+do_test btree-2.2 {
+ btree_move_to $::c1 abc
+} {1}
+do_test btree-2.3 {
+ btree_move_to $::c1 xyz
+} {-1}
+do_test btree-2.4 {
+ btree_move_to $::c1 one
+} {0}
+do_test btree-2.5 {
+ btree_key $::c1
+} {one}
+do_test btree-2.6 {
+ btree_data $::c1
+} {1.00}
+do_test btree-2.7 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+
+# Do some additional inserts
+#
+do_test btree-3.1 {
+ btree_begin_transaction $::b1
+ btree_insert $::c1 two 2.00
+ btree_key $::c1
+} {two}
+do_test btree-3.1.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+do_test btree-3.2 {
+ btree_insert $::c1 three 3.00
+ btree_key $::c1
+} {three}
+do_test btree-3.4 {
+ btree_insert $::c1 four 4.00
+ btree_key $::c1
+} {four}
+do_test btree-3.5 {
+ btree_insert $::c1 five 5.00
+ btree_key $::c1
+} {five}
+do_test btree-3.6 {
+ btree_insert $::c1 six 6.00
+ btree_key $::c1
+} {six}
+#btree_page_dump $::b1 2
+do_test btree-3.7 {
+ set rc [btree_move_to $::c1 {}]
+ expr {$rc>0}
+} {1}
+do_test btree-3.8 {
+ btree_key $::c1
+} {five}
+do_test btree-3.9 {
+ btree_data $::c1
+} {5.00}
+do_test btree-3.10 {
+ btree_next $::c1
+ btree_key $::c1
+} {four}
+do_test btree-3.11 {
+ btree_data $::c1
+} {4.00}
+do_test btree-3.12 {
+ btree_next $::c1
+ btree_key $::c1
+} {one}
+do_test btree-3.13 {
+ btree_data $::c1
+} {1.00}
+do_test btree-3.14 {
+ btree_next $::c1
+ btree_key $::c1
+} {six}
+do_test btree-3.15 {
+ btree_data $::c1
+} {6.00}
+do_test btree-3.16 {
+ btree_next $::c1
+ btree_key $::c1
+} {three}
+do_test btree-3.17 {
+ btree_data $::c1
+} {3.00}
+do_test btree-3.18 {
+ btree_next $::c1
+ btree_key $::c1
+} {two}
+do_test btree-3.19 {
+ btree_data $::c1
+} {2.00}
+do_test btree-3.20 {
+ btree_next $::c1
+ btree_key $::c1
+} {}
+do_test btree-3.21 {
+ btree_data $::c1
+} {}
+
+# Commit the changes, reopen and reread the data
+#
+do_test btree-3.22 {
+ set rc [catch {btree_close_cursor $::c1} msg]
+ lappend rc $msg
+} {0 {}}
+do_test btree-3.22.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {1}
+do_test btree-3.23 {
+ set rc [catch {btree_commit $::b1} msg]
+ lappend rc $msg
+} {0 {}}
+do_test btree-3.23.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {0}
+do_test btree-3.24 {
+ file size test1.bt
+} {2048}
+do_test btree-3.25 {
+ set rc [catch {btree_cursor $::b1 2 1} ::c1]
+ if {$rc} {lappend rc $::c1}
+ set rc
+} {0}
+do_test btree-3.25.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+do_test btree-3.26 {
+ set rc [btree_move_to $::c1 {}]
+ expr {$rc>0}
+} {1}
+do_test btree-3.27 {
+ btree_key $::c1
+} {five}
+do_test btree-3.28 {
+ btree_data $::c1
+} {5.00}
+do_test btree-3.29 {
+ btree_next $::c1
+ btree_key $::c1
+} {four}
+do_test btree-3.30 {
+ btree_data $::c1
+} {4.00}
+do_test btree-3.31 {
+ btree_next $::c1
+ btree_key $::c1
+} {one}
+do_test btree-3.32 {
+ btree_data $::c1
+} {1.00}
+do_test btree-3.33 {
+ btree_next $::c1
+ btree_key $::c1
+} {six}
+do_test btree-3.34 {
+ btree_data $::c1
+} {6.00}
+do_test btree-3.35 {
+ btree_next $::c1
+ btree_key $::c1
+} {three}
+do_test btree-3.36 {
+ btree_data $::c1
+} {3.00}
+do_test btree-3.37 {
+ btree_next $::c1
+ btree_key $::c1
+} {two}
+do_test btree-3.38 {
+ btree_data $::c1
+} {2.00}
+do_test btree-3.39 {
+ btree_next $::c1
+ btree_key $::c1
+} {}
+do_test btree-3.40 {
+ btree_data $::c1
+} {}
+do_test btree-3.41 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+
+
+# Now try a delete
+#
+do_test btree-4.1 {
+ btree_begin_transaction $::b1
+ btree_move_to $::c1 one
+ btree_key $::c1
+} {one}
+do_test btree-4.1.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+do_test btree-4.2 {
+ btree_delete $::c1
+} {}
+do_test btree-4.3 {
+ btree_key $::c1
+} {six}
+do_test btree-4.4 {
+ btree_next $::c1
+ btree_key $::c1
+} {six}
+do_test btree-4.5 {
+ btree_next $::c1
+ btree_key $::c1
+} {three}
+do_test btree-4.4 {
+ btree_move_to $::c1 {}
+ set r {}
+ while 1 {
+ set key [btree_key $::c1]
+ if {$key==""} break
+ lappend r $key
+ lappend r [btree_data $::c1]
+ btree_next $::c1
+ }
+ set r
+} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
+
+# Commit and make sure the delete is still there.
+#
+do_test btree-4.5 {
+ btree_commit $::b1
+ btree_move_to $::c1 {}
+ set r {}
+ while 1 {
+ set key [btree_key $::c1]
+ if {$key==""} break
+ lappend r $key
+ lappend r [btree_data $::c1]
+ btree_next $::c1
+ }
+ set r
+} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
+
+# Completely close the database and reopen it. Then check
+# the data again.
+#
+do_test btree-4.6 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+do_test btree-4.7 {
+ btree_close_cursor $::c1
+ lindex [btree_pager_stats $::b1] 1
+} {0}
+do_test btree-4.8 {
+ btree_close $::b1
+ set ::b1 [btree_open test1.bt]
+ set ::c1 [btree_cursor $::b1 2 1]
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+do_test btree-4.9 {
+ set r {}
+ btree_first $::c1
+ while 1 {
+ set key [btree_key $::c1]
+ if {$key==""} break
+ lappend r $key
+ lappend r [btree_data $::c1]
+ btree_next $::c1
+ }
+ set r
+} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
+
+# Try to read and write meta data
+#
+do_test btree-5.1 {
+ btree_get_meta $::b1
+} {0 0 0 0 0 0 0 0 0 0}
+do_test btree-5.2 {
+ set rc [catch {btree_update_meta $::b1 1 2 3 4 5 6 7 8 9 10} msg]
+ lappend rc $msg
+} {1 SQLITE_ERROR}
+do_test btree-5.3 {
+ btree_begin_transaction $::b1
+ set rc [catch {btree_update_meta $::b1 1 2 3 4 5 6 7 8 9 10} msg]
+ lappend rc $msg
+} {0 {}}
+do_test btree-5.4 {
+ btree_get_meta $::b1
+} {0 2 3 4 5 6 7 8 9 10}
+do_test btree-5.5 {
+ btree_close_cursor $::c1
+ btree_rollback $::b1
+ btree_get_meta $::b1
+} {0 0 0 0 0 0 0 0 0 0}
+do_test btree-5.6 {
+ btree_begin_transaction $::b1
+ btree_update_meta $::b1 999 10 20 30 40 50 60 70 80 90
+ btree_commit $::b1
+ btree_get_meta $::b1
+} {0 10 20 30 40 50 60 70 80 90}
+
+proc select_all {cursor} {
+ set r {}
+ btree_move_to $cursor {}
+ while 1 {
+ set key [btree_key $cursor]
+ if {$key==""} break
+ lappend r $key
+ lappend r [btree_data $cursor]
+ btree_next $cursor
+ }
+ return $r
+}
+proc select_keys {cursor} {
+ set r {}
+ btree_move_to $cursor {}
+ while 1 {
+ set key [btree_key $cursor]
+ if {$key==""} break
+ lappend r $key
+ btree_next $cursor
+ }
+ return $r
+}
+
+# Try to create a new table in the database file
+#
+do_test btree-6.1 {
+ set rc [catch {btree_create_table $::b1} msg]
+ lappend rc $msg
+} {1 SQLITE_ERROR}
+do_test btree-6.2 {
+ btree_begin_transaction $::b1
+ set ::t2 [btree_create_table $::b1]
+} {3}
+do_test btree-6.2.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {1}
+do_test btree-6.2.2 {
+ set ::c2 [btree_cursor $::b1 $::t2 1]
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+do_test btree-6.2.3 {
+ btree_insert $::c2 ten 10
+ btree_key $::c2
+} {ten}
+do_test btree-6.3 {
+ btree_commit $::b1
+ set ::c1 [btree_cursor $::b1 2 1]
+ lindex [btree_pager_stats $::b1] 1
+} {3}
+do_test btree-6.3.1 {
+ select_all $::c1
+} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
+#btree_page_dump $::b1 3
+do_test btree-6.4 {
+ select_all $::c2
+} {ten 10}
+
+# Drop the new table, then create it again anew.
+#
+do_test btree-6.5 {
+ btree_begin_transaction $::b1
+} {}
+do_test btree-6.6 {
+ btree_close_cursor $::c2
+} {}
+do_test btree-6.6.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+do_test btree-6.7 {
+ btree_drop_table $::b1 $::t2
+} {}
+do_test btree-6.7.1 {
+ lindex [btree_get_meta $::b1] 0
+} {1}
+do_test btree-6.8 {
+ set ::t2 [btree_create_table $::b1]
+} {3}
+do_test btree-6.8.1 {
+ lindex [btree_get_meta $::b1] 0
+} {0}
+do_test btree-6.9 {
+ set ::c2 [btree_cursor $::b1 $::t2 1]
+ lindex [btree_pager_stats $::b1] 1
+} {3}
+
+do_test btree-6.9.1 {
+ btree_move_to $::c2 {}
+ btree_key $::c2
+} {}
+
+# If we drop table 2 it just clears the table. Table 2 always exists.
+#
+do_test btree-6.10 {
+ btree_close_cursor $::c1
+ btree_drop_table $::b1 2
+ set ::c1 [btree_cursor $::b1 2 1]
+ btree_move_to $::c1 {}
+ btree_key $::c1
+} {}
+do_test btree-6.11 {
+ btree_commit $::b1
+ select_all $::c1
+} {}
+do_test btree-6.12 {
+ select_all $::c2
+} {}
+do_test btree-6.13 {
+ btree_close_cursor $::c2
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+
+# Check to see that pages defragment properly. To do this test we will
+#
+# 1. Fill the first page table 2 with data.
+# 2. Delete every other entry of table 2.
+# 3. Insert a single entry that requires more contiguous
+# space than is available.
+#
+do_test btree-7.1 {
+ btree_begin_transaction $::b1
+} {}
+catch {unset key}
+catch {unset data}
+do_test btree-7.2 {
+ for {set i 0} {$i<36} {incr i} {
+ set key [format %03d $i]
+ set data "*** $key ***"
+ btree_insert $::c1 $key $data
+ }
+ lrange [btree_cursor_dump $::c1] 4 5
+} {8 1}
+do_test btree-7.3 {
+ btree_move_to $::c1 000
+ while {[btree_key $::c1]!=""} {
+ btree_delete $::c1
+ btree_next $::c1
+ btree_next $::c1
+ }
+ lrange [btree_cursor_dump $::c1] 4 5
+} {512 19}
+#btree_page_dump $::b1 2
+do_test btree-7.4 {
+ btree_insert $::c1 018 {*** 018 ***+++}
+ btree_key $::c1
+} {018}
+do_test btree-7.5 {
+ lrange [btree_cursor_dump $::c1] 4 5
+} {480 1}
+#btree_page_dump $::b1 2
+
+# Delete an entry to make a hole of a known size, then immediately recreate
+# that entry. This tests the path into allocateSpace where the hole exactly
+# matches the size of the desired space.
+#
+do_test btree-7.6 {
+ btree_move_to $::c1 007
+ btree_delete $::c1
+ btree_move_to $::c1 011
+ btree_delete $::c1
+} {}
+do_test btree-7.7 {
+ lindex [btree_cursor_dump $::c1] 5
+} {3}
+#btree_page_dump $::b1 2
+do_test btree-7.8 {
+ btree_insert $::c1 007 {*** 007 ***}
+ lindex [btree_cursor_dump $::c1] 5
+} {2}
+#btree_page_dump $::b1 2
+
+# Make sure the freeSpace() routine properly coaleses adjacent memory blocks
+#
+do_test btree-7.9 {
+ btree_move_to $::c1 013
+ btree_delete $::c1
+ lrange [btree_cursor_dump $::c1] 4 5
+} {536 2}
+do_test btree-7.10 {
+ btree_move_to $::c1 009
+ btree_delete $::c1
+ lrange [btree_cursor_dump $::c1] 4 5
+} {564 2}
+do_test btree-7.11 {
+ btree_move_to $::c1 018
+ btree_delete $::c1
+ lrange [btree_cursor_dump $::c1] 4 5
+} {596 2}
+do_test btree-7.13 {
+ btree_move_to $::c1 033
+ btree_delete $::c1
+ lrange [btree_cursor_dump $::c1] 4 5
+} {624 3}
+do_test btree-7.14 {
+ btree_move_to $::c1 035
+ btree_delete $::c1
+ lrange [btree_cursor_dump $::c1] 4 5
+} {652 2}
+#btree_page_dump $::b1 2
+do_test btree-7.15 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+
+# Check to see that data on overflow pages work correctly.
+#
+do_test btree-8.1 {
+ set data "*** This is a very long key "
+ while {[string length $data]<256} {append data $data}
+ set ::data $data
+ btree_insert $::c1 020 $data
+} {}
+#btree_page_dump $::b1 2
+do_test btree-8.1.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+#btree_pager_ref_dump $::b1
+do_test btree-8.2 {
+ string length [btree_data $::c1]
+} [string length $::data]
+do_test btree-8.3 {
+ btree_data $::c1
+} $::data
+do_test btree-8.4 {
+ btree_delete $::c1
+} {}
+do_test btree-8.4.1 {
+ lindex [btree_get_meta $::b1] 0
+} [expr {int(([string length $::data]-238+1019)/1020)}]
+do_test btree-8.5 {
+ set data "*** This is an even longer key"
+ while {[string length $data]<2000} {append data $data}
+ set ::data $data
+ btree_insert $::c1 020 $data
+} {}
+do_test btree-8.6 {
+ string length [btree_data $::c1]
+} [string length $::data]
+do_test btree-8.7 {
+ btree_data $::c1
+} $::data
+do_test btree-8.8 {
+ btree_commit $::b1
+ btree_data $::c1
+} $::data
+do_test btree-8.9 {
+ btree_close_cursor $::c1
+ btree_close $::b1
+ set ::b1 [btree_open test1.bt]
+ set ::c1 [btree_cursor $::b1 2 1]
+ btree_move_to $::c1 020
+ btree_data $::c1
+} $::data
+do_test btree-8.10 {
+ btree_begin_transaction $::b1
+ btree_delete $::c1
+} {}
+do_test btree-8.11 {
+ lindex [btree_get_meta $::b1] 0
+} [expr {int(([string length $::data]-238+1019)/1020)}]
+
+# Now check out keys on overflow pages.
+#
+do_test btree-8.12 {
+ set ::keyprefix "This is a long prefix to a key "
+ while {[string length $::keyprefix]<256} {append ::keyprefix $::keyprefix}
+ btree_close_cursor $::c1
+ btree_drop_table $::b1 2
+ lindex [btree_get_meta $::b1] 0
+} {4}
+do_test btree-8.12.1 {
+ set ::c1 [btree_cursor $::b1 2 1]
+ btree_insert $::c1 ${::keyprefix}1 1
+ btree_data $::c1
+} {1}
+do_test btree-8.13 {
+ btree_key $::c1
+} ${keyprefix}1
+do_test btree-8.14 {
+ btree_insert $::c1 ${::keyprefix}2 2
+ btree_insert $::c1 ${::keyprefix}3 3
+ btree_key $::c1
+} ${keyprefix}3
+do_test btree-8.15 {
+ btree_move_to $::c1 ${::keyprefix}2
+ btree_data $::c1
+} {2}
+do_test btree-8.16 {
+ btree_move_to $::c1 ${::keyprefix}1
+ btree_data $::c1
+} {1}
+do_test btree-8.17 {
+ btree_move_to $::c1 ${::keyprefix}3
+ btree_data $::c1
+} {3}
+do_test btree-8.18 {
+ lindex [btree_get_meta $::b1] 0
+} {1}
+do_test btree-8.19 {
+ btree_move_to $::c1 ${::keyprefix}2
+ btree_key $::c1
+} ${::keyprefix}2
+#btree_page_dump $::b1 2
+do_test btree-8.20 {
+ btree_delete $::c1
+ btree_next $::c1
+ btree_key $::c1
+} ${::keyprefix}3
+#btree_page_dump $::b1 2
+do_test btree-8.21 {
+ lindex [btree_get_meta $::b1] 0
+} {2}
+do_test btree-8.22 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+do_test btree-8.23 {
+ btree_close_cursor $::c1
+ btree_drop_table $::b1 2
+ set ::c1 [btree_cursor $::b1 2 1]
+ lindex [btree_get_meta $::b1] 0
+} {4}
+do_test btree-8.24 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+#btree_pager_ref_dump $::b1
+
+# Check page splitting logic
+#
+do_test btree-9.1 {
+ for {set i 1} {$i<=19} {incr i} {
+ set key [format %03d $i]
+ set data "*** $key *** $key *** $key *** $key ***"
+ btree_insert $::c1 $key $data
+ }
+} {}
+#btree_tree_dump $::b1 2
+#btree_pager_ref_dump $::b1
+#set pager_refinfo_enable 1
+do_test btree-9.2 {
+ btree_insert $::c1 020 {*** 020 *** 020 *** 020 *** 020 ***}
+ select_keys $::c1
+} {001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020}
+#btree_page_dump $::b1 5
+#btree_page_dump $::b1 2
+#btree_page_dump $::b1 7
+#btree_pager_ref_dump $::b1
+#set pager_refinfo_enable 0
+
+# The previous "select_keys" command left the cursor pointing at the root
+# page. So there should only be two pages checked out. 2 (the root) and
+# page 1.
+do_test btree-9.2.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+for {set i 1} {$i<=20} {incr i} {
+ do_test btree-9.3.$i.1 [subst {
+ btree_move_to $::c1 [format %03d $i]
+ btree_key $::c1
+ }] [format %03d $i]
+ do_test btree-9.3.$i.2 [subst {
+ btree_move_to $::c1 [format %03d $i]
+ string range \[btree_data $::c1\] 0 10
+ }] "*** [format %03d $i] ***"
+}
+do_test btree-9.4.1 {
+ lindex [btree_pager_stats $::b1] 1
+} {3}
+
+# Check the page joining logic.
+#
+#btree_page_dump $::b1 2
+#btree_pager_ref_dump $::b1
+do_test btree-9.4.2 {
+ btree_move_to $::c1 005
+ btree_delete $::c1
+} {}
+#btree_page_dump $::b1 2
+for {set i 1} {$i<=19} {incr i} {
+ if {$i==5} continue
+ do_test btree-9.5.$i.1 [subst {
+ btree_move_to $::c1 [format %03d $i]
+ btree_key $::c1
+ }] [format %03d $i]
+ do_test btree-9.5.$i.2 [subst {
+ btree_move_to $::c1 [format %03d $i]
+ string range \[btree_data $::c1\] 0 10
+ }] "*** [format %03d $i] ***"
+}
+#btree_pager_ref_dump $::b1
+do_test btree-9.6 {
+ btree_close_cursor $::c1
+ lindex [btree_pager_stats $::b1] 1
+} {1}
+do_test btree-9.7 {
+ btree_rollback $::b1
+ lindex [btree_pager_stats $::b1] 1
+} {0}
+
+# Create a tree of depth two. That is, there is a single divider entry
+# on the root pages and two leaf pages. Then delete the divider entry
+# see what happens.
+#
+do_test btree-10.1 {
+ btree_begin_transaction $::b1
+ btree_drop_table $::b1 2
+ lindex [btree_pager_stats $::b1] 1
+} {1}
+do_test btree-10.2 {
+ set ::c1 [btree_cursor $::b1 2 1]
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+do_test btree-10.3 {
+ for {set i 1} {$i<=20} {incr i} {
+ set key [format %03d $i]
+ set data "*** $key *** $key *** $key *** $key ***"
+ btree_insert $::c1 $key $data
+ }
+ select_keys $::c1
+} {001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020}
+#btree_page_dump $::b1 7
+#btree_page_dump $::b1 2
+#btree_page_dump $::b1 6
+do_test btree-10.4 {
+ btree_move_to $::c1 011
+ btree_delete $::c1
+ select_keys $::c1
+} {001 002 003 004 005 006 007 008 009 010 012 013 014 015 016 017 018 019 020}
+#btree_tree_dump $::b1 2
+#btree_pager_ref_dump $::b1
+for {set i 1} {$i<=20} {incr i} {
+ do_test btree-10.5.$i {
+ btree_move_to $::c1 [format %03d $i]
+ lindex [btree_pager_stats $::b1] 1
+ } {2}
+ #btree_pager_ref_dump $::b1
+ #btree_tree_dump $::b1 2
+}
+
+# Create a tree with lots more pages
+#
+catch {unset ::data}
+catch {unset ::key}
+for {set i 21} {$i<=1000} {incr i} {
+ do_test btree-11.1.$i.1 {
+ set key [format %03d $i]
+ set ::data "*** $key *** $key *** $key *** $key ***"
+ btree_insert $::c1 $key $data
+ btree_key $::c1
+ } [format %03d $i]
+ do_test btree-11.1.$i.2 {
+ btree_data $::c1
+ } $::data
+ set ::key [format %03d [expr {$i/2}]]
+ if {$::key=="011"} {set ::key 010}
+ do_test btree-11.1.$i.3 {
+ btree_move_to $::c1 $::key
+ btree_key $::c1
+ } $::key
+}
+catch {unset ::data}
+catch {unset ::key}
+
+# Make sure our reference count is still correct.
+#
+do_test btree-11.2 {
+ btree_close_cursor $::c1
+ lindex [btree_pager_stats $::b1] 1
+} {1}
+do_test btree-11.3 {
+ set ::c1 [btree_cursor $::b1 2 1]
+ lindex [btree_pager_stats $::b1] 1
+} {2}
+#btree_page_dump $::b1 2
+
+# Delete the dividers on the root page
+#
+do_test btree-11.4 {
+ btree_move_to $::c1 257
+ btree_delete $::c1
+ btree_next $::c1
+ btree_key $::c1
+} {258}
+do_test btree-11.4.1 {
+ btree_move_to $::c1 256
+ btree_key $::c1
+} {256}
+do_test btree-11.4.2 {
+ btree_move_to $::c1 258
+ btree_key $::c1
+} {258}
+do_test btree-11.4.3 {
+ btree_move_to $::c1 259
+ btree_key $::c1
+} {259}
+do_test btree-11.4.4 {
+ btree_move_to $::c1 257
+ set n [btree_key $::c1]
+ expr {$n==256||$n==258}
+} {1}
+do_test btree-11.5 {
+ btree_move_to $::c1 513
+ btree_delete $::c1
+ btree_next $::c1
+ btree_key $::c1
+} {514}
+do_test btree-11.5.1 {
+ btree_move_to $::c1 512
+ btree_key $::c1
+} {512}
+do_test btree-11.5.2 {
+ btree_move_to $::c1 514
+ btree_key $::c1
+} {514}
+do_test btree-11.5.3 {
+ btree_move_to $::c1 515
+ btree_key $::c1
+} {515}
+do_test btree-11.5.4 {
+ btree_move_to $::c1 513
+ set n [btree_key $::c1]
+ expr {$n==512||$n==514}
+} {1}
+do_test btree-11.6 {
+ btree_move_to $::c1 769
+ btree_delete $::c1
+ btree_next $::c1
+ btree_key $::c1
+} {770}
+do_test btree-11.6.1 {
+ btree_move_to $::c1 768
+ btree_key $::c1
+} {768}
+do_test btree-11.6.2 {
+ btree_move_to $::c1 771
+ btree_key $::c1
+} {771}
+do_test btree-11.6.3 {
+ btree_move_to $::c1 770
+ btree_key $::c1
+} {770}
+do_test btree-11.6.4 {
+ btree_move_to $::c1 769
+ set n [btree_key $::c1]
+ expr {$n==768||$n==770}
+} {1}
+#btree_page_dump $::b1 2
+#btree_page_dump $::b1 25
+
+# Change the data on an intermediate node such that the node becomes overfull
+# and has to split. We happen to know that intermediate nodes exist on
+# 337, 401 and 465 by the btree_page_dumps above
+#
+catch {unset ::data}
+set ::data {This is going to be a very long data segment}
+append ::data $::data
+append ::data $::data
+do_test btree-12.1 {
+ btree_insert $::c1 337 $::data
+ btree_data $::c1
+} $::data
+do_test btree-12.2 {
+ btree_insert $::c1 401 $::data
+ btree_data $::c1
+} $::data
+do_test btree-12.3 {
+ btree_insert $::c1 465 $::data
+ btree_data $::c1
+} $::data
+do_test btree-12.4 {
+ btree_move_to $::c1 337
+ btree_key $::c1
+} {337}
+do_test btree-12.5 {
+ btree_data $::c1
+} $::data
+do_test btree-12.6 {
+ btree_next $::c1
+ btree_key $::c1
+} {338}
+do_test btree-12.7 {
+ btree_move_to $::c1 464
+ btree_key $::c1
+} {464}
+do_test btree-12.8 {
+ btree_next $::c1
+ btree_data $::c1
+} $::data
+do_test btree-12.9 {
+ btree_next $::c1
+ btree_key $::c1
+} {466}
+do_test btree-12.10 {
+ btree_move_to $::c1 400
+ btree_key $::c1
+} {400}
+do_test btree-12.11 {
+ btree_next $::c1
+ btree_data $::c1
+} $::data
+do_test btree-12.12 {
+ btree_next $::c1
+ btree_key $::c1
+} {402}
+do_test btree-13.1 {
+ btree_integrity_check $::b1 2 3
+} {}
+
+# To Do:
+#
+# 1. Do some deletes from the 3-layer tree
+# 2. Commit and reopen the database
+# 3. Read every 15th entry and make sure it works
+# 4. Implement btree_sanity and put it throughout this script
+#
+
+do_test btree-15.98 {
+ btree_close_cursor $::c1
+ lindex [btree_pager_stats $::b1] 1
+} {1}
+do_test btree-15.99 {
+ btree_rollback $::b1
+ lindex [btree_pager_stats $::b1] 1
+} {0}
+btree_pager_ref_dump $::b1
+
+do_test btree-99.1 {
+ btree_close $::b1
+} {}
+catch {unset data}
+catch {unset key}
+
+} ;# end if( not mem: and has pager_open command );
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/btree2.test b/usr/src/lib/libsqlite/test/btree2.test
new file mode 100644
index 0000000000..45c0203a52
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/btree2.test
@@ -0,0 +1,449 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 btree database backend
+#
+# $Id: btree2.test,v 1.10 2002/02/19 13:39:23 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+if {[info commands btree_open]!=""} {
+
+# Create a new database file containing no entries. The database should
+# contain 5 tables:
+#
+# 2 The descriptor table
+# 3 The foreground table
+# 4 The background table
+# 5 The long key table
+# 6 The long data table
+#
+# An explanation for what all these tables are used for is provided below.
+#
+do_test btree2-1.1 {
+ expr srand(1)
+ file delete -force test2.bt
+ file delete -force test2.bt-journal
+ set ::b [btree_open test2.bt]
+ btree_begin_transaction $::b
+ btree_create_table $::b
+} {3}
+do_test btree2-1.2 {
+ btree_create_table $::b
+} {4}
+do_test btree2-1.3 {
+ btree_create_table $::b
+} {5}
+do_test btree2-1.4 {
+ btree_create_table $::b
+} {6}
+do_test btree2-1.5 {
+ set ::c2 [btree_cursor $::b 2 1]
+ btree_insert $::c2 {one} {1}
+ btree_delete $::c2
+ btree_close_cursor $::c2
+ btree_commit $::b
+ btree_integrity_check $::b 2 3 4 5 6
+} {}
+
+# This test module works by making lots of pseudo-random changes to a
+# database while simultaneously maintaining an invariant on that database.
+# Periodically, the script does a sanity check on the database and verifies
+# that the invariant is satisfied.
+#
+# The invariant is as follows:
+#
+# 1. The descriptor table always contains 2 enters. An entry keyed by
+# "N" is the number of elements in the foreground and background tables
+# combined. The entry keyed by "L" is the number of digits in the keys
+# for foreground and background tables.
+#
+# 2. The union of the foreground an background tables consists of N entries
+# where each entry an L-digit key. (Actually, some keys can be longer
+# than L characters, but they always start with L digits.) The keys
+# cover all integers between 1 and N. Whenever an entry is added to
+# the foreground it is removed form the background and vice versa.
+#
+# 3. Some entries in the foreground and background tables have keys that
+# begin with an L-digit number but are followed by additional characters.
+# For each such entry there is a corresponding entry in the long key
+# table. The long key table entry has a key which is just the L-digit
+# number and data which is the length of the key in the foreground and
+# background tables.
+#
+# 4. The data for both foreground and background entries is usually a
+# short string. But some entries have long data strings. For each
+# such entries there is an entry in the long data type. The key to
+# long data table is an L-digit number. (The extension on long keys
+# is omitted.) The data is the number of charaters in the data of the
+# foreground or background entry.
+#
+# The following function builds a database that satisfies all of the above
+# invariants.
+#
+proc build_db {N L} {
+ for {set i 2} {$i<=6} {incr i} {
+ catch {btree_close_cursor [set ::c$i]}
+ btree_clear_table $::b $i
+ set ::c$i [btree_cursor $::b $i 1]
+ }
+ btree_insert $::c2 N $N
+ btree_insert $::c2 L $L
+ set format %0${L}d
+ for {set i 1} {$i<=$N} {incr i} {
+ set key [format $format $i]
+ set data $key
+ btree_insert $::c3 $key $data
+ }
+}
+
+# Given a base key number and a length, construct the full text of the key
+# or data.
+#
+proc make_payload {keynum L len} {
+ set key [format %0${L}d $keynum]
+ set r $key
+ set i 1
+ while {[string length $r]<$len} {
+ append r " ($i) $key"
+ incr i
+ }
+ return [string range $r 0 [expr {$len-1}]]
+}
+
+# Verify the invariants on the database. Return an empty string on
+# success or an error message if something is amiss.
+#
+proc check_invariants {} {
+ set ck [btree_integrity_check $::b 2 3 4 5 6]
+ if {$ck!=""} {
+ puts "\n*** SANITY:\n$ck"
+ exit
+ return $ck
+ }
+ btree_move_to $::c3 {}
+ btree_move_to $::c4 {}
+ btree_move_to $::c2 N
+ set N [btree_data $::c2]
+ btree_move_to $::c2 L
+ set L [btree_data $::c2]
+ set LM1 [expr {$L-1}]
+ for {set i 1} {$i<=$N} {incr i} {
+ set key [btree_key $::c3]
+ if {[scan $key %d k]<1} {set k 0}
+ if {$k!=$i} {
+ set key [btree_key $::c4]
+ if {[scan $key %d k]<1} {set k 0}
+ if {$k!=$i} {
+ # puts "MISSING $i"
+ # puts {Page 3:}; btree_page_dump $::b 3
+ # puts {Page 4:}; btree_page_dump $::b 4
+ # exit
+ return "Key $i is missing from both foreground and background"
+ }
+ set data [btree_data $::c4]
+ btree_next $::c4
+ } else {
+ set data [btree_data $::c3]
+ btree_next $::c3
+ }
+ set skey [string range $key 0 $LM1]
+ if {[btree_move_to $::c5 $skey]==0} {
+ set keylen [btree_data $::c5]
+ } else {
+ set keylen $L
+ }
+ if {[string length $key]!=$keylen} {
+ return "Key $i is the wrong size.\
+ Is \"$key\" but should be \"[make_payload $k $L $keylen]\""
+ }
+ if {[make_payload $k $L $keylen]!=$key} {
+ return "Key $i has an invalid extension"
+ }
+ if {[btree_move_to $::c6 $skey]==0} {
+ set datalen [btree_data $::c6]
+ } else {
+ set datalen $L
+ }
+ if {[string length $data]!=$datalen} {
+ return "Data for $i is the wrong size.\
+ Is [string length $data] but should be $datalen"
+ }
+ if {[make_payload $k $L $datalen]!=$data} {
+ return "Entry $i has an incorrect data"
+ }
+ }
+}
+
+# Make random changes to the database such that each change preserves
+# the invariants. The number of changes is $n*N where N is the parameter
+# from the descriptor table. Each changes begins with a random key.
+# the entry with that key is put in the foreground table with probability
+# $I and it is put in background with probability (1.0-$I). It gets
+# a long key with probability $K and long data with probability $D.
+#
+set chngcnt 0
+proc random_changes {n I K D} {
+ btree_move_to $::c2 N
+ set N [btree_data $::c2]
+ btree_move_to $::c2 L
+ set L [btree_data $::c2]
+ set LM1 [expr {$L-1}]
+ set total [expr {int($N*$n)}]
+ set format %0${L}d
+ for {set i 0} {$i<$total} {incr i} {
+ set k [expr {int(rand()*$N)+1}]
+ set insert [expr {rand()<=$I}]
+ set longkey [expr {rand()<=$K}]
+ set longdata [expr {rand()<=$D}]
+ # incr ::chngcnt
+ # if {$::chngcnt==251} {btree_tree_dump $::b 3}
+ # puts "CHANGE $::chngcnt: $k $insert $longkey $longdata"
+ if {$longkey} {
+ set x [expr {rand()}]
+ set keylen [expr {int($x*$x*$x*$x*3000)+10}]
+ } else {
+ set keylen $L
+ }
+ set key [make_payload $k $L $keylen]
+ if {$longdata} {
+ set x [expr {rand()}]
+ set datalen [expr {int($x*$x*$x*$x*3000)+10}]
+ } else {
+ set datalen $L
+ }
+ set data [make_payload $k $L $datalen]
+ set basekey [format $format $k]
+ if {[set c [btree_move_to $::c3 $basekey]]==0} {
+ btree_delete $::c3
+ } else {
+ if {$c<0} {btree_next $::c3}
+ if {[string match $basekey* [btree_key $::c3]]} {
+ btree_delete $::c3
+ }
+ }
+ if {[set c [btree_move_to $::c4 $basekey]]==0} {
+ btree_delete $::c4
+ } else {
+ if {$c<0} {btree_next $::c4}
+ if {[string match $basekey* [btree_key $::c4]]} {
+ btree_delete $::c4
+ }
+ }
+ if {[scan [btree_key $::c4] %d kx]<1} {set kx -1}
+ if {$kx==$k} {
+ btree_delete $::c4
+ }
+ if {$insert} {
+ btree_insert $::c3 $key $data
+ } else {
+ btree_insert $::c4 $key $data
+ }
+ if {$longkey} {
+ btree_insert $::c5 $basekey $keylen
+ } elseif {[btree_move_to $::c5 $basekey]==0} {
+ btree_delete $::c5
+ }
+ if {$longdata} {
+ btree_insert $::c6 $basekey $datalen
+ } elseif {[btree_move_to $::c6 $basekey]==0} {
+ btree_delete $::c6
+ }
+ # set ck [btree_integrity_check $::b 2 3 4 5 6]
+ # if {$ck!=""} {
+ # puts "\nSANITY CHECK FAILED!\n$ck"
+ # exit
+ # }
+ # puts "PAGE 3:"; btree_page_dump $::b 3
+ # puts "PAGE 4:"; btree_page_dump $::b 4
+ }
+}
+
+# Repeat this test sequence on database of various sizes
+#
+set testno 2
+foreach {N L} {
+ 10 2
+ 50 2
+ 200 3
+ 2000 5
+} {
+ puts "**** N=$N L=$L ****"
+ set hash [md5file test2.bt]
+ do_test btree2-$testno.1 [subst -nocommands {
+ set ::c2 [btree_cursor $::b 2 1]
+ set ::c3 [btree_cursor $::b 3 1]
+ set ::c4 [btree_cursor $::b 4 1]
+ set ::c5 [btree_cursor $::b 5 1]
+ set ::c6 [btree_cursor $::b 6 1]
+ btree_begin_transaction $::b
+ build_db $N $L
+ check_invariants
+ }] {}
+ do_test btree2-$testno.2 {
+ btree_close_cursor $::c2
+ btree_close_cursor $::c3
+ btree_close_cursor $::c4
+ btree_close_cursor $::c5
+ btree_close_cursor $::c6
+ btree_rollback $::b
+ md5file test2.bt
+ } $hash
+ do_test btree2-$testno.3 [subst -nocommands {
+ btree_begin_transaction $::b
+ set ::c2 [btree_cursor $::b 2 1]
+ set ::c3 [btree_cursor $::b 3 1]
+ set ::c4 [btree_cursor $::b 4 1]
+ set ::c5 [btree_cursor $::b 5 1]
+ set ::c6 [btree_cursor $::b 6 1]
+ build_db $N $L
+ check_invariants
+ }] {}
+ do_test btree2-$testno.4 {
+ btree_commit $::b
+ check_invariants
+ } {}
+ do_test btree2-$testno.5 {
+ lindex [btree_pager_stats $::b] 1
+ } {6}
+ do_test btree2-$testno.6 {
+ btree_close_cursor $::c2
+ btree_close_cursor $::c3
+ btree_close_cursor $::c4
+ btree_close_cursor $::c5
+ btree_close_cursor $::c6
+ lindex [btree_pager_stats $::b] 1
+ } {0}
+ do_test btree2-$testno.7 {
+ btree_close $::b
+ } {}
+after 100
+ # For each database size, run various changes tests.
+ #
+ set num2 1
+ foreach {n I K D} {
+ 0.5 0.5 0.1 0.1
+ 1.0 0.2 0.1 0.1
+ 1.0 0.8 0.1 0.1
+ 2.0 0.0 0.1 0.1
+ 2.0 1.0 0.1 0.1
+ 2.0 0.0 0.0 0.0
+ 2.0 1.0 0.0 0.0
+ } {
+ set testid btree2-$testno.8.$num2
+ set hash [md5file test2.bt]
+ do_test $testid.0 {
+ set ::b [btree_open test2.bt]
+ set ::c2 [btree_cursor $::b 2 1]
+ set ::c3 [btree_cursor $::b 3 1]
+ set ::c4 [btree_cursor $::b 4 1]
+ set ::c5 [btree_cursor $::b 5 1]
+ set ::c6 [btree_cursor $::b 6 1]
+ check_invariants
+ } {}
+ set cnt 6
+ for {set i 2} {$i<=6} {incr i} {
+ if {[lindex [btree_cursor_dump [set ::c$i]] 0]!=$i} {incr cnt}
+ }
+ do_test $testid.1 {
+ btree_begin_transaction $::b
+ lindex [btree_pager_stats $::b] 1
+ } $cnt
+ # exec cp test2.bt test2.bt.bu1
+ do_test $testid.2 [subst {
+ random_changes $n $I $K $D
+ }] {}
+ do_test $testid.3 {
+ check_invariants
+ } {}
+ do_test $testid.4 {
+ btree_close_cursor $::c2
+ btree_close_cursor $::c3
+ btree_close_cursor $::c4
+ btree_close_cursor $::c5
+ btree_close_cursor $::c6
+ btree_rollback $::b
+ md5file test2.bt
+ } $hash
+ # exec cp test2.bt test2.bt.bu2
+ btree_begin_transaction $::b
+ set ::c2 [btree_cursor $::b 2 1]
+ set ::c3 [btree_cursor $::b 3 1]
+ set ::c4 [btree_cursor $::b 4 1]
+ set ::c5 [btree_cursor $::b 5 1]
+ set ::c6 [btree_cursor $::b 6 1]
+ do_test $testid.5 [subst {
+ random_changes $n $I $K $D
+ }] {}
+ do_test $testid.6 {
+ check_invariants
+ } {}
+ do_test $testid.7 {
+ btree_commit $::b
+ check_invariants
+ } {}
+ set hash [md5file test2.bt]
+ do_test $testid.8 {
+ btree_close_cursor $::c2
+ btree_close_cursor $::c3
+ btree_close_cursor $::c4
+ btree_close_cursor $::c5
+ btree_close_cursor $::c6
+ lindex [btree_pager_stats $::b] 1
+ } {0}
+ do_test $testid.9 {
+ btree_close $::b
+ set ::b [btree_open test2.bt]
+ set ::c2 [btree_cursor $::b 2 1]
+ set ::c3 [btree_cursor $::b 3 1]
+ set ::c4 [btree_cursor $::b 4 1]
+ set ::c5 [btree_cursor $::b 5 1]
+ set ::c6 [btree_cursor $::b 6 1]
+ check_invariants
+ } {}
+ do_test $testid.10 {
+ btree_close_cursor $::c2
+ btree_close_cursor $::c3
+ btree_close_cursor $::c4
+ btree_close_cursor $::c5
+ btree_close_cursor $::c6
+ lindex [btree_pager_stats $::b] 1
+ } {0}
+ do_test $testid.11 {
+ btree_close $::b
+ } {}
+ incr num2
+ }
+ incr testno
+ set ::b [btree_open test2.bt]
+}
+
+# Testing is complete. Shut everything down.
+#
+do_test btree-999.1 {
+ lindex [btree_pager_stats $::b] 1
+} {0}
+do_test btree-999.2 {
+ btree_close $::b
+} {}
+do_test btree-999.3 {
+ file delete -force test2.bt
+ file exists test2.bt-journal
+} {0}
+
+} ;# end if( not mem: and has pager_open command );
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/btree3.test b/usr/src/lib/libsqlite/test/btree3.test
new file mode 100644
index 0000000000..784759f176
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/btree3.test
@@ -0,0 +1,89 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 November 22
+#
+# 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 btree database backend
+#
+# In particular, this file tests a small part of the Delete logic
+# for the BTree backend. When a row is deleted from a table, the
+# cursor is suppose to be left pointing at either the previous or
+# next entry in that table. If the cursor is left pointing at the
+# next entry, then the next Next operation is ignored. So the
+# sequence of operations (Delete, Next) should always leave the
+# cursor pointing at the first entry past the one that was deleted.
+# This test is designed to verify that behavior.
+#
+# $Id: btree3.test,v 1.2 2002/12/04 13:40:27 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+if {[info commands btree_open]!=""} {
+
+# Open a test database.
+#
+file delete -force test1.bt
+file delete -force test1.bt-journal
+set b1 [btree_open test1.bt]
+btree_begin_transaction $::b1
+
+# Insert a few one records
+#
+set data {abcdefghijklmnopqrstuvwxyz0123456789}
+append data $data
+append data $data
+append data $data
+append data $data
+for {set k 2} {$k<=10} {incr k} {
+ for {set j 1} {$j<=$k} {incr j} {
+ set jkey [format %02d $j]
+ btree_clear_table $::b1 2
+ set ::c1 [btree_cursor $::b1 2 1]
+ for {set i 1} {$i<=$k} {incr i} {
+ set key [format %02d $i]
+ do_test btree3-$k.$j.1.$i {
+ btree_insert $::c1 $::key $::data
+ } {}
+ # btree_tree_dump $::b1 2
+ }
+ do_test btree3-$k.$j.2 {
+ btree_move_to $::c1 $::jkey
+ btree_key $::c1
+ } $::jkey
+ do_test btree3-$k.$j.3 {
+ btree_delete $::c1
+ } {}
+ if {$j<$k} {
+ do_test btree3-$k.$j.4 {
+ btree_next $::c1
+ btree_key $::c1
+ } [format %02d [expr $j+1]]
+ }
+ if {$j>1} {
+ do_test btree3-$k.$j.5 {
+ btree_prev $::c1
+ btree_key $::c1
+ } [format %02d [expr $j-1]]
+ }
+ btree_close_cursor $::c1
+ }
+}
+
+btree_rollback $::b1
+btree_pager_ref_dump $::b1
+btree_close $::b1
+
+} ;# end if( not mem: and has pager_open command );
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/btree3rb.test b/usr/src/lib/libsqlite/test/btree3rb.test
new file mode 100644
index 0000000000..ab249a6ca0
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/btree3rb.test
@@ -0,0 +1,87 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 November 22
+#
+# 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 btree database backend
+#
+# In particular, this file tests a small part of the Delete logic
+# for the BTree backend. When a row is deleted from a table, the
+# cursor is suppose to be left pointing at either the previous or
+# next entry in that table. If the cursor is left pointing at the
+# next entry, then the next Next operation is ignored. So the
+# sequence of operations (Delete, Next) should always leave the
+# cursor pointing at the first entry past the one that was deleted.
+# This test is designed to verify that behavior.
+#
+# $Id: btree3rb.test,v 1.1 2003/04/20 23:45:23 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+if {[info commands btree_open]!=""} {
+
+# Open a test database.
+#
+set b1 [btree_open :memory:]
+btree_begin_transaction $::b1
+
+# Insert a few one records
+#
+set data {abcdefghijklmnopqrstuvwxyz0123456789}
+append data $data
+append data $data
+append data $data
+append data $data
+for {set k 2} {$k<=20} {incr k} {
+ for {set j 1} {$j<=$k} {incr j} {
+ set jkey [format %02d $j]
+ btree_clear_table $::b1 2
+ set ::c1 [btree_cursor $::b1 2 1]
+ for {set i 1} {$i<=$k} {incr i} {
+ set key [format %02d $i]
+ do_test btree3rb-$k.$j.1.$i {
+ btree_insert $::c1 $::key $::data
+ } {}
+ # btree_tree_dump $::b1 2
+ }
+ do_test btree3rb-$k.$j.2 {
+ btree_move_to $::c1 $::jkey
+ btree_key $::c1
+ } $::jkey
+ do_test btree3rb-$k.$j.3 {
+ btree_delete $::c1
+ } {}
+ if {$j<$k} {
+ do_test btree3rb-$k.$j.4 {
+ btree_next $::c1
+ btree_key $::c1
+ } [format %02d [expr $j+1]]
+ }
+ if {$j>1} {
+ do_test btree3rb-$k.$j.5 {
+ btree_prev $::c1
+ btree_key $::c1
+ } [format %02d [expr $j-1]]
+ }
+ btree_close_cursor $::c1
+ }
+}
+
+btree_rollback $::b1
+#btree_pager_ref_dump $::b1
+btree_close $::b1
+
+} ;# end if( not mem: and has pager_open command );
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/btree4.test b/usr/src/lib/libsqlite/test/btree4.test
new file mode 100644
index 0000000000..b18790388a
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/btree4.test
@@ -0,0 +1,101 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 December 03
+#
+# 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 btree database backend
+#
+# This file focuses on testing the sqliteBtreeNext() and
+# sqliteBtreePrevious() procedures and making sure they are able
+# to step through an entire table from either direction.
+#
+# $Id: btree4.test,v 1.1 2002/12/04 13:40:27 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+if {[info commands btree_open]!=""} {
+
+# Open a test database.
+#
+file delete -force test1.bt
+file delete -force test1.bt-journal
+set b1 [btree_open test1.bt]
+btree_begin_transaction $::b1
+
+set data {abcdefghijklmnopqrstuvwxyz0123456789}
+append data $data
+append data $data
+append data $data
+append data $data
+
+foreach N {10 100 1000} {
+ btree_clear_table $::b1 2
+ set ::c1 [btree_cursor $::b1 2 1]
+ do_test btree4-$N.1 {
+ for {set i 1} {$i<=$N} {incr i} {
+ btree_insert $::c1 [format k-%05d $i] $::data-$i
+ }
+ btree_first $::c1
+ btree_key $::c1
+ } {k-00001}
+ do_test btree4-$N.2 {
+ btree_data $::c1
+ } $::data-1
+ for {set i 2} {$i<=$N} {incr i} {
+ do_test btree-$N.3.$i.1 {
+ btree_next $::c1
+ } 0
+ do_test btree-$N.3.$i.2 {
+ btree_key $::c1
+ } [format k-%05d $i]
+ do_test btree-$N.3.$i.3 {
+ btree_data $::c1
+ } $::data-$i
+ }
+ do_test btree4-$N.4 {
+ btree_next $::c1
+ } 1
+ do_test btree4-$N.5 {
+ btree_last $::c1
+ } 0
+ do_test btree4-$N.6 {
+ btree_key $::c1
+ } [format k-%05d $N]
+ do_test btree4-$N.7 {
+ btree_data $::c1
+ } $::data-$N
+ for {set i [expr {$N-1}]} {$i>=1} {incr i -1} {
+ do_test btree4-$N.8.$i.1 {
+ btree_prev $::c1
+ } 0
+ do_test btree4-$N.8.$i.2 {
+ btree_key $::c1
+ } [format k-%05d $i]
+ do_test btree4-$N.8.$i.3 {
+ btree_data $::c1
+ } $::data-$i
+ }
+ do_test btree4-$N.9 {
+ btree_prev $::c1
+ } 1
+ btree_close_cursor $::c1
+}
+
+btree_rollback $::b1
+btree_pager_ref_dump $::b1
+btree_close $::b1
+
+} ;# end if( not mem: and has pager_open command );
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/btree4rb.test b/usr/src/lib/libsqlite/test/btree4rb.test
new file mode 100644
index 0000000000..3be7f1edbc
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/btree4rb.test
@@ -0,0 +1,98 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 December 03
+#
+# 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 btree database backend
+#
+# This file focuses on testing the sqliteBtreeNext() and
+# sqliteBtreePrevious() procedures and making sure they are able
+# to step through an entire table from either direction.
+#
+# $Id: btree4rb.test,v 1.1 2003/04/20 23:45:23 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+if {[info commands btree_open]!=""} {
+
+# Open a test database.
+#
+set b1 [btree_open :memory:]
+btree_begin_transaction $::b1
+
+set data {abcdefghijklmnopqrstuvwxyz0123456789}
+append data $data
+append data $data
+append data $data
+append data $data
+
+foreach N {10 100 1000} {
+ btree_clear_table $::b1 2
+ set ::c1 [btree_cursor $::b1 2 1]
+ do_test btree4rb-$N.1 {
+ for {set i 1} {$i<=$N} {incr i} {
+ btree_insert $::c1 [format k-%05d $i] $::data-$i
+ }
+ btree_first $::c1
+ btree_key $::c1
+ } {k-00001}
+ do_test btree4rb-$N.2 {
+ btree_data $::c1
+ } $::data-1
+ for {set i 2} {$i<=$N} {incr i} {
+ do_test btree-$N.3.$i.1 {
+ btree_next $::c1
+ } 0
+ do_test btree-$N.3.$i.2 {
+ btree_key $::c1
+ } [format k-%05d $i]
+ do_test btree-$N.3.$i.3 {
+ btree_data $::c1
+ } $::data-$i
+ }
+ do_test btree4rb-$N.4 {
+ btree_next $::c1
+ } 1
+ do_test btree4rb-$N.5 {
+ btree_last $::c1
+ } 0
+ do_test btree4rb-$N.6 {
+ btree_key $::c1
+ } [format k-%05d $N]
+ do_test btree4rb-$N.7 {
+ btree_data $::c1
+ } $::data-$N
+ for {set i [expr {$N-1}]} {$i>=1} {incr i -1} {
+ do_test btree4rb-$N.8.$i.1 {
+ btree_prev $::c1
+ } 0
+ do_test btree4rb-$N.8.$i.2 {
+ btree_key $::c1
+ } [format k-%05d $i]
+ do_test btree4rb-$N.8.$i.3 {
+ btree_data $::c1
+ } $::data-$i
+ }
+ do_test btree4rb-$N.9 {
+ btree_prev $::c1
+ } 1
+ btree_close_cursor $::c1
+}
+
+btree_rollback $::b1
+btree_close $::b1
+
+} ;# end if( not mem: and has pager_open command );
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/capi2.test b/usr/src/lib/libsqlite/test/capi2.test
new file mode 100644
index 0000000000..1bb32628a9
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/capi2.test
@@ -0,0 +1,478 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2003 January 29
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script testing the callback-free C/C++ API.
+#
+# $Id: capi2.test,v 1.10 2003/08/05 13:13:38 drh Exp $
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Check basic functionality
+#
+do_test capi2-1.1 {
+ db close
+ set DB [sqlite db test.db]
+ execsql {CREATE TABLE t1(a,b,c)}
+ set VM [sqlite_compile $DB {SELECT name, rowid FROM sqlite_master} TAIL]
+ set TAIL
+} {}
+do_test capi2-1.2 {
+ sqlite_step $VM N VALUES COLNAMES
+} {SQLITE_ROW}
+do_test capi2-1.3 {
+ set N
+} {2}
+do_test capi2-1.4 {
+ set VALUES
+} {t1 1}
+do_test capi2-1.5 {
+ set COLNAMES
+} {name rowid text INTEGER}
+do_test capi2-1.6 {
+ set N x
+ set VALUES y
+ set COLNAMES z
+ sqlite_step $VM N VALUES COLNAMES
+} {SQLITE_DONE}
+do_test capi2-1.7 {
+ list $N $VALUES $COLNAMES
+} {2 {} {name rowid text INTEGER}}
+do_test capi2-1.8 {
+ set N x
+ set VALUES y
+ set COLNAMES z
+ sqlite_step $VM N VALUES COLNAMES
+} {SQLITE_MISUSE}
+do_test capi2-1.9 {
+ list $N $VALUES $COLNAMES
+} {0 {} {}}
+do_test capi2-1.10 {
+ sqlite_finalize $VM
+} {}
+
+# Check to make sure that the "tail" of a multi-statement SQL script
+# is returned by sqlite_compile.
+#
+do_test capi2-2.1 {
+ set SQL {
+ SELECT name, rowid FROM sqlite_master;
+ SELECT name, rowid FROM sqlite_temp_master;
+ -- A comment at the end
+ }
+ set VM [sqlite_compile $DB $SQL SQL]
+ set SQL
+} {
+ SELECT name, rowid FROM sqlite_temp_master;
+ -- A comment at the end
+ }
+do_test capi2-2.2 {
+ set r [sqlite_step $VM n val colname]
+ lappend r $n $val $colname
+} {SQLITE_ROW 2 {t1 1} {name rowid text INTEGER}}
+do_test capi2-2.3 {
+ set r [sqlite_step $VM n val colname]
+ lappend r $n $val $colname
+} {SQLITE_DONE 2 {} {name rowid text INTEGER}}
+do_test capi2-2.4 {
+ sqlite_finalize $VM
+} {}
+do_test capi2-2.5 {
+ set VM [sqlite_compile $DB $SQL SQL]
+ set SQL
+} {
+ -- A comment at the end
+ }
+do_test capi2-2.6 {
+ set r [sqlite_step $VM n val colname]
+ lappend r $n $val $colname
+} {SQLITE_DONE 2 {} {name rowid text INTEGER}}
+do_test capi2-2.7 {
+ sqlite_finalize $VM
+} {}
+do_test capi2-2.8 {
+ set VM [sqlite_compile $DB $SQL SQL]
+ list $SQL $VM
+} {{} {}}
+
+# Check the error handling.
+#
+do_test capi2-3.1 {
+ set rc [catch {
+ sqlite_compile $DB {select bogus from sqlite_master} TAIL
+ } msg]
+ lappend rc $msg $TAIL
+} {1 {(1) no such column: bogus} {}}
+do_test capi2-3.2 {
+ set rc [catch {
+ sqlite_compile $DB {select bogus from } TAIL
+ } msg]
+ lappend rc $msg $TAIL
+} {1 {(1) near " ": syntax error} {}}
+do_test capi2-3.3 {
+ set rc [catch {
+ sqlite_compile $DB {;;;;select bogus from sqlite_master} TAIL
+ } msg]
+ lappend rc $msg $TAIL
+} {1 {(1) no such column: bogus} {}}
+do_test capi2-3.4 {
+ set rc [catch {
+ sqlite_compile $DB {select bogus from sqlite_master;x;} TAIL
+ } msg]
+ lappend rc $msg $TAIL
+} {1 {(1) no such column: bogus} {x;}}
+do_test capi2-3.5 {
+ set rc [catch {
+ sqlite_compile $DB {select bogus from sqlite_master;;;x;} TAIL
+ } msg]
+ lappend rc $msg $TAIL
+} {1 {(1) no such column: bogus} {;;x;}}
+do_test capi2-3.6 {
+ set rc [catch {
+ sqlite_compile $DB {select 5/0} TAIL
+ } VM]
+ lappend rc $TAIL
+} {0 {}}
+do_test capi2-3.7 {
+ set N {}
+ set VALUE {}
+ set COLNAME {}
+ list [sqlite_step $VM N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 {{}} {5/0 NUMERIC}}
+do_test capi2-3.8 {
+ sqlite_finalize $VM
+} {}
+do_test capi2-3.9 {
+ execsql {CREATE UNIQUE INDEX i1 ON t1(a)}
+ set VM [sqlite_compile $DB {INSERT INTO t1 VALUES(1,2,3)} TAIL]
+ set TAIL
+} {}
+do_test capi2-3.9b {db changes} {0}
+do_test capi2-3.10 {
+ set N {}
+ set VALUE {}
+ set COLNAME {}
+ list [sqlite_step $VM N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 0 {} {}}
+do_test capi2-3.10b {db changes} {1}
+do_test capi2-3.11 {
+ sqlite_finalize $VM
+} {}
+do_test capi2-3.11b {db changes} {1}
+do_test capi2-3.12 {
+ list [catch {sqlite_finalize $VM} msg] [set msg]
+} {1 {(21) library routine called out of sequence}}
+do_test capi2-3.13 {
+ set VM [sqlite_compile $DB {INSERT INTO t1 VALUES(1,3,4)} TAIL]
+ list [sqlite_step $VM N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ERROR 0 {} {}}
+do_test capi2-3.13b {db changes} {0}
+do_test capi2-3.14 {
+ list [catch {sqlite_finalize $VM} msg] [set msg]
+} {1 {(19) column a is not unique}}
+do_test capi2-3.15 {
+ set VM [sqlite_compile $DB {CREATE TABLE t2(a NOT NULL, b)} TAIL]
+ set TAIL
+} {}
+do_test capi2-3.16 {
+ list [sqlite_step $VM N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 0 {} {}}
+do_test capi2-3.17 {
+ list [catch {sqlite_finalize $VM} msg] [set msg]
+} {0 {}}
+do_test capi2-3.18 {
+ set VM [sqlite_compile $DB {INSERT INTO t2 VALUES(NULL,2)} TAIL]
+ list [sqlite_step $VM N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ERROR 0 {} {}}
+do_test capi2-3.19 {
+ list [catch {sqlite_finalize $VM} msg] [set msg]
+} {1 {(19) t2.a may not be NULL}}
+
+# Two or more virtual machines exists at the same time.
+#
+do_test capi2-4.1 {
+ set VM1 [sqlite_compile $DB {INSERT INTO t2 VALUES(1,2)} TAIL]
+ set TAIL
+} {}
+do_test capi2-4.2 {
+ set VM2 [sqlite_compile $DB {INSERT INTO t2 VALUES(2,3)} TAIL]
+ set TAIL
+} {}
+do_test capi2-4.3 {
+ set VM3 [sqlite_compile $DB {INSERT INTO t2 VALUES(3,4)} TAIL]
+ set TAIL
+} {}
+do_test capi2-4.4 {
+ list [sqlite_step $VM2 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 0 {} {}}
+do_test capi2-4.5 {
+ execsql {SELECT * FROM t2 ORDER BY a}
+} {2 3}
+do_test capi2-4.6 {
+ list [catch {sqlite_finalize $VM2} msg] [set msg]
+} {0 {}}
+do_test capi2-4.7 {
+ list [sqlite_step $VM3 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 0 {} {}}
+do_test capi2-4.8 {
+ execsql {SELECT * FROM t2 ORDER BY a}
+} {2 3 3 4}
+do_test capi2-4.9 {
+ list [catch {sqlite_finalize $VM3} msg] [set msg]
+} {0 {}}
+do_test capi2-4.10 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 0 {} {}}
+do_test capi2-4.11 {
+ execsql {SELECT * FROM t2 ORDER BY a}
+} {1 2 2 3 3 4}
+do_test capi2-4.12 {
+ list [catch {sqlite_finalize $VM1} msg] [set msg]
+} {0 {}}
+
+# Interleaved SELECTs
+#
+do_test capi2-5.1 {
+ set VM1 [sqlite_compile $DB {SELECT * FROM t2} TAIL]
+ set VM2 [sqlite_compile $DB {SELECT * FROM t2} TAIL]
+ set VM3 [sqlite_compile $DB {SELECT * FROM t2} TAIL]
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {2 3} {a b {} {}}}
+do_test capi2-5.2 {
+ list [sqlite_step $VM2 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {2 3} {a b {} {}}}
+do_test capi2-5.3 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {3 4} {a b {} {}}}
+do_test capi2-5.4 {
+ list [sqlite_step $VM3 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {2 3} {a b {} {}}}
+do_test capi2-5.5 {
+ list [sqlite_step $VM3 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {3 4} {a b {} {}}}
+do_test capi2-5.6 {
+ list [sqlite_step $VM3 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {1 2} {a b {} {}}}
+do_test capi2-5.7 {
+ list [sqlite_step $VM3 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 2 {} {a b {} {}}}
+do_test capi2-5.8 {
+ list [catch {sqlite_finalize $VM3} msg] [set msg]
+} {0 {}}
+do_test capi2-5.9 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {1 2} {a b {} {}}}
+do_test capi2-5.10 {
+ list [catch {sqlite_finalize $VM1} msg] [set msg]
+} {0 {}}
+do_test capi2-5.11 {
+ list [sqlite_step $VM2 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {3 4} {a b {} {}}}
+do_test capi2-5.12 {
+ list [sqlite_step $VM2 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {1 2} {a b {} {}}}
+do_test capi2-5.11 {
+ list [catch {sqlite_finalize $VM2} msg] [set msg]
+} {0 {}}
+
+# Check for proper SQLITE_BUSY returns.
+#
+do_test capi2-6.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t3(x counter);
+ INSERT INTO t3 VALUES(1);
+ INSERT INTO t3 VALUES(2);
+ INSERT INTO t3 SELECT x+2 FROM t3;
+ INSERT INTO t3 SELECT x+4 FROM t3;
+ INSERT INTO t3 SELECT x+8 FROM t3;
+ COMMIT;
+ }
+ set VM1 [sqlite_compile $DB {SELECT * FROM t3} TAIL]
+ sqlite db2 test.db
+ execsql {BEGIN} db2
+} {}
+do_test capi2-6.2 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_BUSY 0 {} {}}
+do_test capi2-6.3 {
+ execsql {COMMIT} db2
+} {}
+do_test capi2-6.4 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 1 {x counter}}
+do_test capi2-6.5 {
+ catchsql {BEGIN} db2
+} {1 {database is locked}}
+do_test capi2-6.6 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 2 {x counter}}
+do_test capi2-6.7 {
+ execsql {SELECT * FROM t2} db2
+} {2 3 3 4 1 2}
+do_test capi2-6.8 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 3 {x counter}}
+do_test capi2-6.9 {
+ execsql {SELECT * FROM t2}
+} {2 3 3 4 1 2}
+do_test capi2-6.10 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 4 {x counter}}
+do_test capi2-6.11 {
+ execsql {BEGIN}
+} {}
+do_test capi2-6.12 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 5 {x counter}}
+# execsql {pragma vdbe_trace=on}
+do_test capi2-6.13 {
+ catchsql {UPDATE t3 SET x=x+1}
+} {1 {database table is locked}}
+do_test capi2-6.14 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 6 {x counter}}
+# puts [list [catch {sqlite_finalize $VM1} msg] [set msg]]; exit
+do_test capi2-6.15 {
+ execsql {SELECT * FROM t1}
+} {1 2 3}
+do_test capi2-6.16 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 7 {x counter}}
+do_test capi2-6.17 {
+ catchsql {UPDATE t1 SET b=b+1}
+} {0 {}}
+do_test capi2-6.18 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 8 {x counter}}
+do_test capi2-6.19 {
+ execsql {SELECT * FROM t1}
+} {1 3 3}
+do_test capi2-6.20 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 9 {x counter}}
+do_test capi2-6.21 {
+ execsql {ROLLBACK; SELECT * FROM t1}
+} {1 2 3}
+do_test capi2-6.22 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 10 {x counter}}
+do_test capi2-6.23 {
+ execsql {BEGIN TRANSACTION ON CONFLICT ROLLBACK;}
+} {}
+do_test capi2-6.24 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 11 {x counter}}
+do_test capi2-6.25 {
+ execsql {
+ INSERT INTO t1 VALUES(2,3,4);
+ SELECT * FROM t1;
+ }
+} {1 2 3 2 3 4}
+do_test capi2-6.26 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 12 {x counter}}
+do_test capi2-6.27 {
+ catchsql {
+ INSERT INTO t1 VALUES(2,4,5);
+ SELECT * FROM t1;
+ }
+} {1 {column a is not unique}}
+do_test capi2-6.28 {
+ list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 13 {x counter}}
+do_test capi2-6.99 {
+ list [catch {sqlite_finalize $VM1} msg] [set msg]
+} {0 {}}
+catchsql {ROLLBACK}
+
+do_test capi2-7.1 {
+ stepsql $DB {
+ SELECT * FROM t1
+ }
+} {0 1 2 3}
+do_test capi2-7.2 {
+ stepsql $DB {
+ PRAGMA count_changes=on
+ }
+} {0}
+do_test capi2-7.3 {
+ stepsql $DB {
+ UPDATE t1 SET a=a+10;
+ }
+} {0 1}
+do_test capi2-7.4 {
+ stepsql $DB {
+ INSERT INTO t1 SELECT a+1,b+1,c+1 FROM t1;
+ }
+} {0 1}
+do_test capi2-7.4b {db changes} {1}
+do_test capi2-7.5 {
+ stepsql $DB {
+ UPDATE t1 SET a=a+10;
+ }
+} {0 2}
+do_test capi2-7.5b {db changes} {2}
+do_test capi2-7.6 {
+ stepsql $DB {
+ SELECT * FROM t1;
+ }
+} {0 21 2 3 22 3 4}
+do_test capi2-7.7 {
+ stepsql $DB {
+ INSERT INTO t1 SELECT a+2,b+2,c+2 FROM t1;
+ }
+} {0 2}
+do_test capi2-7.8 {
+ db changes
+} {2}
+do_test capi2-7.9 {
+ stepsql $DB {
+ SELECT * FROM t1;
+ }
+} {0 21 2 3 22 3 4 23 4 5 24 5 6}
+do_test capi2-7.10 {
+ stepsql $DB {
+ UPDATE t1 SET a=a-20;
+ SELECT * FROM t1;
+ }
+} {0 4 1 2 3 2 3 4 3 4 5 4 5 6}
+do_test capi2-7.11 {
+ db changes
+} {0}
+do_test capi2-7.12 {
+ set x [stepsql $DB {EXPLAIN SELECT * FROM t1}]
+ lindex $x 0
+} {0}
+
+# Ticket #261 - make sure we can finalize before the end of a query.
+#
+do_test capi2-8.1 {
+ set VM1 [sqlite_compile $DB {SELECT * FROM t2} TAIL]
+ sqlite_finalize $VM1
+} {}
+
+# Tickets #384 and #385 - make sure the TAIL argument to sqlite_compile
+# and all of the return pointers in sqlite_step can be null.
+#
+do_test capi2-9.1 {
+ set VM1 [sqlite_compile $DB {SELECT * FROM t2}]
+ sqlite_step $VM1
+ sqlite_finalize $VM1
+} {}
+
+db2 close
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/conflict.test b/usr/src/lib/libsqlite/test/conflict.test
new file mode 100644
index 0000000000..dfb1c88f42
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/conflict.test
@@ -0,0 +1,697 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 January 29
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+# This file implements tests for the conflict resolution extension
+# to SQLite.
+#
+# $Id: conflict.test,v 1.19 2003/08/05 13:13:39 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create tables for the first group of tests.
+#
+do_test conflict-1.0 {
+ execsql {
+ CREATE TABLE t1(a, b, c, UNIQUE(a,b));
+ CREATE TABLE t2(x);
+ SELECT c FROM t1 ORDER BY c;
+ }
+} {}
+
+# Six columns of configuration data as follows:
+#
+# i The reference number of the test
+# conf The conflict resolution algorithm on the BEGIN statement
+# cmd An INSERT or REPLACE command to execute against table t1
+# t0 True if there is an error from $cmd
+# t1 Content of "c" column of t1 assuming no error in $cmd
+# t2 Content of "x" column of t2
+#
+foreach {i conf cmd t0 t1 t2} {
+ 1 {} INSERT 1 {} 1
+ 2 {} {INSERT OR IGNORE} 0 3 1
+ 3 {} {INSERT OR REPLACE} 0 4 1
+ 4 {} REPLACE 0 4 1
+ 5 {} {INSERT OR FAIL} 1 {} 1
+ 6 {} {INSERT OR ABORT} 1 {} 1
+ 7 {} {INSERT OR ROLLBACK} 1 {} {}
+ 8 IGNORE INSERT 0 3 1
+ 9 IGNORE {INSERT OR IGNORE} 0 3 1
+ 10 IGNORE {INSERT OR REPLACE} 0 4 1
+ 11 IGNORE REPLACE 0 4 1
+ 12 IGNORE {INSERT OR FAIL} 1 {} 1
+ 13 IGNORE {INSERT OR ABORT} 1 {} 1
+ 14 IGNORE {INSERT OR ROLLBACK} 1 {} {}
+ 15 REPLACE INSERT 0 4 1
+ 16 FAIL INSERT 1 {} 1
+ 17 ABORT INSERT 1 {} 1
+ 18 ROLLBACK INSERT 1 {} {}
+} {
+ do_test conflict-1.$i {
+ if {$conf!=""} {set conf "ON CONFLICT $conf"}
+ set r0 [catch {execsql [subst {
+ DELETE FROM t1;
+ DELETE FROM t2;
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN $conf;
+ INSERT INTO t2 VALUES(1);
+ $cmd INTO t1 VALUES(1,2,4);
+ }]} r1]
+ catch {execsql {COMMIT}}
+ if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
+ set r2 [execsql {SELECT x FROM t2}]
+ list $r0 $r1 $r2
+ } [list $t0 $t1 $t2]
+}
+
+# Create tables for the first group of tests.
+#
+do_test conflict-2.0 {
+ execsql {
+ DROP TABLE t1;
+ DROP TABLE t2;
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(a,b));
+ CREATE TABLE t2(x);
+ SELECT c FROM t1 ORDER BY c;
+ }
+} {}
+
+# Six columns of configuration data as follows:
+#
+# i The reference number of the test
+# conf The conflict resolution algorithm on the BEGIN statement
+# cmd An INSERT or REPLACE command to execute against table t1
+# t0 True if there is an error from $cmd
+# t1 Content of "c" column of t1 assuming no error in $cmd
+# t2 Content of "x" column of t2
+#
+foreach {i conf cmd t0 t1 t2} {
+ 1 {} INSERT 1 {} 1
+ 2 {} {INSERT OR IGNORE} 0 3 1
+ 3 {} {INSERT OR REPLACE} 0 4 1
+ 4 {} REPLACE 0 4 1
+ 5 {} {INSERT OR FAIL} 1 {} 1
+ 6 {} {INSERT OR ABORT} 1 {} 1
+ 7 {} {INSERT OR ROLLBACK} 1 {} {}
+ 8 IGNORE INSERT 0 3 1
+ 9 IGNORE {INSERT OR IGNORE} 0 3 1
+ 10 IGNORE {INSERT OR REPLACE} 0 4 1
+ 11 IGNORE REPLACE 0 4 1
+ 12 IGNORE {INSERT OR FAIL} 1 {} 1
+ 13 IGNORE {INSERT OR ABORT} 1 {} 1
+ 14 IGNORE {INSERT OR ROLLBACK} 1 {} {}
+ 15 REPLACE INSERT 0 4 1
+ 16 FAIL INSERT 1 {} 1
+ 17 ABORT INSERT 1 {} 1
+ 18 ROLLBACK INSERT 1 {} {}
+} {
+ do_test conflict-2.$i {
+ if {$conf!=""} {set conf "ON CONFLICT $conf"}
+ set r0 [catch {execsql [subst {
+ DELETE FROM t1;
+ DELETE FROM t2;
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN $conf;
+ INSERT INTO t2 VALUES(1);
+ $cmd INTO t1 VALUES(1,2,4);
+ }]} r1]
+ catch {execsql {COMMIT}}
+ if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
+ set r2 [execsql {SELECT x FROM t2}]
+ list $r0 $r1 $r2
+ } [list $t0 $t1 $t2]
+}
+
+# Create tables for the first group of tests.
+#
+do_test conflict-3.0 {
+ execsql {
+ DROP TABLE t1;
+ DROP TABLE t2;
+ CREATE TABLE t1(a, b, c INTEGER, PRIMARY KEY(c), UNIQUE(a,b));
+ CREATE TABLE t2(x);
+ SELECT c FROM t1 ORDER BY c;
+ }
+} {}
+
+# Six columns of configuration data as follows:
+#
+# i The reference number of the test
+# conf The conflict resolution algorithm on the BEGIN statement
+# cmd An INSERT or REPLACE command to execute against table t1
+# t0 True if there is an error from $cmd
+# t1 Content of "c" column of t1 assuming no error in $cmd
+# t2 Content of "x" column of t2
+#
+foreach {i conf cmd t0 t1 t2} {
+ 1 {} INSERT 1 {} 1
+ 2 {} {INSERT OR IGNORE} 0 3 1
+ 3 {} {INSERT OR REPLACE} 0 4 1
+ 4 {} REPLACE 0 4 1
+ 5 {} {INSERT OR FAIL} 1 {} 1
+ 6 {} {INSERT OR ABORT} 1 {} 1
+ 7 {} {INSERT OR ROLLBACK} 1 {} {}
+ 8 IGNORE INSERT 0 3 1
+ 9 IGNORE {INSERT OR IGNORE} 0 3 1
+ 10 IGNORE {INSERT OR REPLACE} 0 4 1
+ 11 IGNORE REPLACE 0 4 1
+ 12 IGNORE {INSERT OR FAIL} 1 {} 1
+ 13 IGNORE {INSERT OR ABORT} 1 {} 1
+ 14 IGNORE {INSERT OR ROLLBACK} 1 {} {}
+ 15 REPLACE INSERT 0 4 1
+ 16 FAIL INSERT 1 {} 1
+ 17 ABORT INSERT 1 {} 1
+ 18 ROLLBACK INSERT 1 {} {}
+} {
+ do_test conflict-3.$i {
+ if {$conf!=""} {set conf "ON CONFLICT $conf"}
+ set r0 [catch {execsql [subst {
+ DELETE FROM t1;
+ DELETE FROM t2;
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN $conf;
+ INSERT INTO t2 VALUES(1);
+ $cmd INTO t1 VALUES(1,2,4);
+ }]} r1]
+ catch {execsql {COMMIT}}
+ if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
+ set r2 [execsql {SELECT x FROM t2}]
+ list $r0 $r1 $r2
+ } [list $t0 $t1 $t2]
+}
+
+do_test conflict-4.0 {
+ execsql {
+ DROP TABLE t2;
+ CREATE TABLE t2(x);
+ SELECT x FROM t2;
+ }
+} {}
+
+# Six columns of configuration data as follows:
+#
+# i The reference number of the test
+# conf1 The conflict resolution algorithm on the UNIQUE constraint
+# conf2 The conflict resolution algorithm on the BEGIN statement
+# cmd An INSERT or REPLACE command to execute against table t1
+# t0 True if there is an error from $cmd
+# t1 Content of "c" column of t1 assuming no error in $cmd
+# t2 Content of "x" column of t2
+#
+foreach {i conf1 conf2 cmd t0 t1 t2} {
+ 1 {} {} INSERT 1 {} 1
+ 2 REPLACE {} INSERT 0 4 1
+ 3 IGNORE {} INSERT 0 3 1
+ 4 FAIL {} INSERT 1 {} 1
+ 5 ABORT {} INSERT 1 {} 1
+ 6 ROLLBACK {} INSERT 1 {} {}
+ 7 REPLACE {} {INSERT OR IGNORE} 0 3 1
+ 8 IGNORE {} {INSERT OR REPLACE} 0 4 1
+ 9 FAIL {} {INSERT OR IGNORE} 0 3 1
+ 10 ABORT {} {INSERT OR REPLACE} 0 4 1
+ 11 ROLLBACK {} {INSERT OR IGNORE } 0 3 1
+ 12 REPLACE IGNORE INSERT 0 3 1
+ 13 IGNORE REPLACE INSERT 0 4 1
+ 14 FAIL IGNORE INSERT 0 3 1
+ 15 ABORT REPLACE INSERT 0 4 1
+ 16 ROLLBACK IGNORE INSERT 0 3 1
+ 12 IGNORE REPLACE INSERT 0 4 1
+ 13 IGNORE FAIL INSERT 1 {} 1
+ 14 IGNORE ABORT INSERT 1 {} 1
+ 15 IGNORE ROLLBACK INSERT 1 {} {}
+} {
+ do_test conflict-4.$i {
+ if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
+ if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
+ set r0 [catch {execsql [subst {
+ DROP TABLE t1;
+ CREATE TABLE t1(a,b,c,UNIQUE(a,b) $conf1);
+ DELETE FROM t2;
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN $conf2;
+ INSERT INTO t2 VALUES(1);
+ $cmd INTO t1 VALUES(1,2,4);
+ }]} r1]
+ catch {execsql {COMMIT}}
+ if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
+ set r2 [execsql {SELECT x FROM t2}]
+ list $r0 $r1 $r2
+ } [list $t0 $t1 $t2]
+}
+
+do_test conflict-5.0 {
+ execsql {
+ DROP TABLE t2;
+ CREATE TABLE t2(x);
+ SELECT x FROM t2;
+ }
+} {}
+
+# Six columns of configuration data as follows:
+#
+# i The reference number of the test
+# conf1 The conflict resolution algorithm on the NOT NULL constraint
+# conf2 The conflict resolution algorithm on the BEGIN statement
+# cmd An INSERT or REPLACE command to execute against table t1
+# t0 True if there is an error from $cmd
+# t1 Content of "c" column of t1 assuming no error in $cmd
+# t2 Content of "x" column of t2
+#
+foreach {i conf1 conf2 cmd t0 t1 t2} {
+ 1 {} {} INSERT 1 {} 1
+ 2 REPLACE {} INSERT 0 5 1
+ 3 IGNORE {} INSERT 0 {} 1
+ 4 FAIL {} INSERT 1 {} 1
+ 5 ABORT {} INSERT 1 {} 1
+ 6 ROLLBACK {} INSERT 1 {} {}
+ 7 REPLACE {} {INSERT OR IGNORE} 0 {} 1
+ 8 IGNORE {} {INSERT OR REPLACE} 0 5 1
+ 9 FAIL {} {INSERT OR IGNORE} 0 {} 1
+ 10 ABORT {} {INSERT OR REPLACE} 0 5 1
+ 11 ROLLBACK {} {INSERT OR IGNORE} 0 {} 1
+ 12 {} {} {INSERT OR IGNORE} 0 {} 1
+ 13 {} {} {INSERT OR REPLACE} 0 5 1
+ 14 {} {} {INSERT OR FAIL} 1 {} 1
+ 15 {} {} {INSERT OR ABORT} 1 {} 1
+ 16 {} {} {INSERT OR ROLLBACK} 1 {} {}
+ 17 {} IGNORE INSERT 0 {} 1
+ 18 {} REPLACE INSERT 0 5 1
+ 19 {} FAIL INSERT 1 {} 1
+ 20 {} ABORT INSERT 1 {} 1
+ 21 {} ROLLBACK INSERT 1 {} {}
+ 22 REPLACE FAIL INSERT 1 {} 1
+ 23 IGNORE ROLLBACK INSERT 1 {} {}
+} {
+ if {$t0} {set t1 {t1.c may not be NULL}}
+ do_test conflict-5.$i {
+ if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
+ if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
+ set r0 [catch {execsql [subst {
+ DROP TABLE t1;
+ CREATE TABLE t1(a,b,c NOT NULL $conf1 DEFAULT 5);
+ DELETE FROM t2;
+ BEGIN $conf2;
+ INSERT INTO t2 VALUES(1);
+ $cmd INTO t1 VALUES(1,2,NULL);
+ }]} r1]
+ catch {execsql {COMMIT}}
+ if {!$r0} {set r1 [execsql {SELECT c FROM t1}]}
+ set r2 [execsql {SELECT x FROM t2}]
+ list $r0 $r1 $r2
+ } [list $t0 $t1 $t2]
+}
+
+do_test conflict-6.0 {
+ execsql {
+ DROP TABLE t2;
+ CREATE TABLE t2(a,b,c);
+ INSERT INTO t2 VALUES(1,2,1);
+ INSERT INTO t2 VALUES(2,3,2);
+ INSERT INTO t2 VALUES(3,4,1);
+ INSERT INTO t2 VALUES(4,5,4);
+ SELECT c FROM t2 ORDER BY b;
+ CREATE TABLE t3(x);
+ INSERT INTO t3 VALUES(1);
+ }
+} {1 2 1 4}
+
+# Six columns of configuration data as follows:
+#
+# i The reference number of the test
+# conf1 The conflict resolution algorithm on the UNIQUE constraint
+# conf2 The conflict resolution algorithm on the BEGIN statement
+# cmd An UPDATE command to execute against table t1
+# t0 True if there is an error from $cmd
+# t1 Content of "b" column of t1 assuming no error in $cmd
+# t2 Content of "x" column of t3
+#
+foreach {i conf1 conf2 cmd t0 t1 t2} {
+ 1 {} {} UPDATE 1 {6 7 8 9} 1
+ 2 REPLACE {} UPDATE 0 {7 6 9} 1
+ 3 IGNORE {} UPDATE 0 {6 7 3 9} 1
+ 4 FAIL {} UPDATE 1 {6 7 3 4} 1
+ 5 ABORT {} UPDATE 1 {1 2 3 4} 1
+ 6 ROLLBACK {} UPDATE 1 {1 2 3 4} 0
+ 7 REPLACE {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
+ 8 IGNORE {} {UPDATE OR REPLACE} 0 {7 6 9} 1
+ 9 FAIL {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
+ 10 ABORT {} {UPDATE OR REPLACE} 0 {7 6 9} 1
+ 11 ROLLBACK {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
+ 12 {} {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
+ 13 {} {} {UPDATE OR REPLACE} 0 {7 6 9} 1
+ 14 {} {} {UPDATE OR FAIL} 1 {6 7 3 4} 1
+ 15 {} {} {UPDATE OR ABORT} 1 {1 2 3 4} 1
+ 16 {} {} {UPDATE OR ROLLBACK} 1 {1 2 3 4} 0
+ 17 {} IGNORE UPDATE 0 {6 7 3 9} 1
+ 18 {} REPLACE UPDATE 0 {7 6 9} 1
+ 19 {} FAIL UPDATE 1 {6 7 3 4} 1
+ 20 {} ABORT UPDATE 1 {1 2 3 4} 1
+ 21 {} ROLLBACK UPDATE 1 {1 2 3 4} 0
+ 22 REPLACE IGNORE UPDATE 0 {6 7 3 9} 1
+ 23 IGNORE REPLACE UPDATE 0 {7 6 9} 1
+ 24 REPLACE FAIL UPDATE 1 {6 7 3 4} 1
+ 25 IGNORE ABORT UPDATE 1 {1 2 3 4} 1
+ 26 REPLACE ROLLBACK UPDATE 1 {1 2 3 4} 0
+} {
+ if {$t0} {set t1 {column a is not unique}}
+ do_test conflict-6.$i {
+ if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
+ if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
+ set r0 [catch {execsql [subst {
+ DROP TABLE t1;
+ CREATE TABLE t1(a,b,c, UNIQUE(a) $conf1);
+ INSERT INTO t1 SELECT * FROM t2;
+ UPDATE t3 SET x=0;
+ BEGIN $conf2;
+ $cmd t3 SET x=1;
+ $cmd t1 SET b=b*2;
+ $cmd t1 SET a=c+5;
+ }]} r1]
+ catch {execsql {COMMIT}}
+ if {!$r0} {set r1 [execsql {SELECT a FROM t1 ORDER BY b}]}
+ set r2 [execsql {SELECT x FROM t3}]
+ list $r0 $r1 $r2
+ } [list $t0 $t1 $t2]
+}
+
+# Test to make sure a lot of IGNOREs don't cause a stack overflow
+#
+do_test conflict-7.1 {
+ execsql {
+ DROP TABLE t1;
+ DROP TABLE t2;
+ DROP TABLE t3;
+ CREATE TABLE t1(a unique, b);
+ }
+ for {set i 1} {$i<=50} {incr i} {
+ execsql "INSERT into t1 values($i,[expr {$i+1}]);"
+ }
+ execsql {
+ SELECT count(*), min(a), max(b) FROM t1;
+ }
+} {50 1 51}
+do_test conflict-7.2 {
+ execsql {
+ PRAGMA count_changes=on;
+ UPDATE OR IGNORE t1 SET a=1000;
+ }
+} {1}
+do_test conflict-7.2.1 {
+ db changes
+} {1}
+do_test conflict-7.3 {
+ execsql {
+ SELECT b FROM t1 WHERE a=1000;
+ }
+} {2}
+do_test conflict-7.4 {
+ execsql {
+ SELECT count(*) FROM t1;
+ }
+} {50}
+do_test conflict-7.5 {
+ execsql {
+ PRAGMA count_changes=on;
+ UPDATE OR REPLACE t1 SET a=1001;
+ }
+} {50}
+do_test conflict-7.5.1 {
+ db changes
+} {50}
+do_test conflict-7.6 {
+ execsql {
+ SELECT b FROM t1 WHERE a=1001;
+ }
+} {51}
+do_test conflict-7.7 {
+ execsql {
+ SELECT count(*) FROM t1;
+ }
+} {1}
+do_test conflict-7.7.1 {
+ db changes
+} {0}
+
+# Make sure the row count is right for rows that are ignored on
+# an insert.
+#
+do_test conflict-8.1 {
+ execsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2);
+ }
+ execsql {
+ INSERT OR IGNORE INTO t1 VALUES(2,3);
+ }
+} {1}
+do_test conflict-8.1.1 {
+ db changes
+} {1}
+do_test conflict-8.2 {
+ execsql {
+ INSERT OR IGNORE INTO t1 VALUES(2,4);
+ }
+} {0}
+do_test conflict-8.2.1 {
+ db changes
+} {0}
+do_test conflict-8.3 {
+ execsql {
+ INSERT OR REPLACE INTO t1 VALUES(2,4);
+ }
+} {1}
+do_test conflict-8.3.1 {
+ db changes
+} {1}
+do_test conflict-8.4 {
+ execsql {
+ INSERT OR IGNORE INTO t1 SELECT * FROM t1;
+ }
+} {0}
+do_test conflict-8.4.1 {
+ db changes
+} {0}
+do_test conflict-8.5 {
+ execsql {
+ INSERT OR IGNORE INTO t1 SELECT a+2,b+2 FROM t1;
+ }
+} {2}
+do_test conflict-8.5.1 {
+ db changes
+} {2}
+do_test conflict-8.6 {
+ execsql {
+ INSERT OR IGNORE INTO t1 SELECT a+3,b+3 FROM t1;
+ }
+} {3}
+do_test conflict-8.6.1 {
+ db changes
+} {3}
+
+integrity_check conflict-8.99
+
+do_test conflict-9.1 {
+ execsql {
+ PRAGMA count_changes=0;
+ CREATE TABLE t2(
+ a INTEGER UNIQUE ON CONFLICT IGNORE,
+ b INTEGER UNIQUE ON CONFLICT FAIL,
+ c INTEGER UNIQUE ON CONFLICT REPLACE,
+ d INTEGER UNIQUE ON CONFLICT ABORT,
+ e INTEGER UNIQUE ON CONFLICT ROLLBACK
+ );
+ CREATE TABLE t3(x);
+ INSERT INTO t3 VALUES(1);
+ SELECT * FROM t3;
+ }
+} {1}
+do_test conflict-9.2 {
+ catchsql {
+ INSERT INTO t2 VALUES(1,1,1,1,1);
+ INSERT INTO t2 VALUES(2,2,2,2,2);
+ SELECT * FROM t2;
+ }
+} {0 {1 1 1 1 1 2 2 2 2 2}}
+do_test conflict-9.3 {
+ catchsql {
+ INSERT INTO t2 VALUES(1,3,3,3,3);
+ SELECT * FROM t2;
+ }
+} {0 {1 1 1 1 1 2 2 2 2 2}}
+do_test conflict-9.4 {
+ catchsql {
+ UPDATE t2 SET a=a+1 WHERE a=1;
+ SELECT * FROM t2;
+ }
+} {0 {1 1 1 1 1 2 2 2 2 2}}
+do_test conflict-9.5 {
+ catchsql {
+ INSERT INTO t2 VALUES(3,1,3,3,3);
+ SELECT * FROM t2;
+ }
+} {1 {column b is not unique}}
+do_test conflict-9.6 {
+ catchsql {
+ UPDATE t2 SET b=b+1 WHERE b=1;
+ SELECT * FROM t2;
+ }
+} {1 {column b is not unique}}
+do_test conflict-9.7 {
+ catchsql {
+ BEGIN;
+ UPDATE t3 SET x=x+1;
+ INSERT INTO t2 VALUES(3,1,3,3,3);
+ SELECT * FROM t2;
+ }
+} {1 {column b is not unique}}
+do_test conflict-9.8 {
+ execsql {COMMIT}
+ execsql {SELECT * FROM t3}
+} {2}
+do_test conflict-9.9 {
+ catchsql {
+ BEGIN;
+ UPDATE t3 SET x=x+1;
+ UPDATE t2 SET b=b+1 WHERE b=1;
+ SELECT * FROM t2;
+ }
+} {1 {column b is not unique}}
+do_test conflict-9.10 {
+ execsql {COMMIT}
+ execsql {SELECT * FROM t3}
+} {3}
+do_test conflict-9.11 {
+ catchsql {
+ INSERT INTO t2 VALUES(3,3,3,1,3);
+ SELECT * FROM t2;
+ }
+} {1 {column d is not unique}}
+do_test conflict-9.12 {
+ catchsql {
+ UPDATE t2 SET d=d+1 WHERE d=1;
+ SELECT * FROM t2;
+ }
+} {1 {column d is not unique}}
+do_test conflict-9.13 {
+ catchsql {
+ BEGIN;
+ UPDATE t3 SET x=x+1;
+ INSERT INTO t2 VALUES(3,3,3,1,3);
+ SELECT * FROM t2;
+ }
+} {1 {column d is not unique}}
+do_test conflict-9.14 {
+ execsql {COMMIT}
+ execsql {SELECT * FROM t3}
+} {4}
+do_test conflict-9.15 {
+ catchsql {
+ BEGIN;
+ UPDATE t3 SET x=x+1;
+ UPDATE t2 SET d=d+1 WHERE d=1;
+ SELECT * FROM t2;
+ }
+} {1 {column d is not unique}}
+do_test conflict-9.16 {
+ execsql {COMMIT}
+ execsql {SELECT * FROM t3}
+} {5}
+do_test conflict-9.17 {
+ catchsql {
+ INSERT INTO t2 VALUES(3,3,3,3,1);
+ SELECT * FROM t2;
+ }
+} {1 {column e is not unique}}
+do_test conflict-9.18 {
+ catchsql {
+ UPDATE t2 SET e=e+1 WHERE e=1;
+ SELECT * FROM t2;
+ }
+} {1 {column e is not unique}}
+do_test conflict-9.19 {
+ catchsql {
+ BEGIN;
+ UPDATE t3 SET x=x+1;
+ INSERT INTO t2 VALUES(3,3,3,3,1);
+ SELECT * FROM t2;
+ }
+} {1 {column e is not unique}}
+do_test conflict-9.20 {
+ catch {execsql {COMMIT}}
+ execsql {SELECT * FROM t3}
+} {5}
+do_test conflict-9.21 {
+ catchsql {
+ BEGIN;
+ UPDATE t3 SET x=x+1;
+ UPDATE t2 SET e=e+1 WHERE e=1;
+ SELECT * FROM t2;
+ }
+} {1 {column e is not unique}}
+do_test conflict-9.22 {
+ catch {execsql {COMMIT}}
+ execsql {SELECT * FROM t3}
+} {5}
+do_test conflict-9.23 {
+ catchsql {
+ INSERT INTO t2 VALUES(3,3,1,3,3);
+ SELECT * FROM t2;
+ }
+} {0 {2 2 2 2 2 3 3 1 3 3}}
+do_test conflict-9.24 {
+ catchsql {
+ UPDATE t2 SET c=c-1 WHERE c=2;
+ SELECT * FROM t2;
+ }
+} {0 {2 2 1 2 2}}
+do_test conflict-9.25 {
+ catchsql {
+ BEGIN;
+ UPDATE t3 SET x=x+1;
+ INSERT INTO t2 VALUES(3,3,1,3,3);
+ SELECT * FROM t2;
+ }
+} {0 {3 3 1 3 3}}
+do_test conflict-9.26 {
+ catch {execsql {COMMIT}}
+ execsql {SELECT * FROM t3}
+} {6}
+
+do_test conflict-10.1 {
+ catchsql {
+ DELETE FROM t1;
+ BEGIN ON CONFLICT ROLLBACK;
+ INSERT INTO t1 VALUES(1,2);
+ INSERT INTO t1 VALUES(1,3);
+ COMMIT;
+ }
+ execsql {SELECT * FROM t1}
+} {}
+do_test conflict-10.2 {
+ catchsql {
+ CREATE TABLE t4(x);
+ CREATE UNIQUE INDEX t4x ON t4(x);
+ BEGIN ON CONFLICT ROLLBACK;
+ INSERT INTO t4 VALUES(1);
+ INSERT INTO t4 VALUES(1);
+ COMMIT;
+ }
+ execsql {SELECT * FROM t4}
+} {}
+
+integrity_check conflict-99.0
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/copy.test b/usr/src/lib/libsqlite/test/copy.test
new file mode 100644
index 0000000000..68fa7f8fd2
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/copy.test
@@ -0,0 +1,268 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 COPY statement.
+#
+# $Id: copy.test,v 1.17 2004/02/17 18:26:57 dougcurrie Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a file of data from which to copy.
+#
+set f [open data1.txt w]
+puts $f "11\t22\t33"
+puts $f "22\t33\t11"
+close $f
+set f [open data2.txt w]
+puts $f "11\t22\t33"
+puts $f "\\."
+puts $f "22\t33\t11"
+close $f
+set f [open data3.txt w]
+puts $f "11\t22\t33\t44"
+puts $f "22\t33\t11"
+close $f
+set f [open data4.txt w]
+puts $f "11 | 22 | 33"
+puts $f "22 | 33 | 11"
+close $f
+set f [open data5.txt w]
+puts $f "11|22|33"
+puts $f "22|33|11"
+close $f
+set f [open dataX.txt w]
+fconfigure $f -translation binary
+puts -nonewline $f "11|22|33\r"
+puts -nonewline $f "22|33|44\r\n"
+puts -nonewline $f "33|44|55\n"
+puts -nonewline $f "44|55|66\r"
+puts -nonewline $f "55|66|77\r\n"
+puts -nonewline $f "66|77|88\n"
+close $f
+
+# Try to COPY into a non-existant table.
+#
+do_test copy-1.1 {
+ set v [catch {execsql {COPY test1 FROM 'data1.txt'}} msg]
+ lappend v $msg
+} {1 {no such table: test1}}
+
+# Try to insert into sqlite_master
+#
+do_test copy-1.2 {
+ set v [catch {execsql {COPY sqlite_master FROM 'data2.txt'}} msg]
+ lappend v $msg
+} {1 {table sqlite_master may not be modified}}
+
+# Do some actual inserts
+#
+do_test copy-1.3 {
+ execsql {CREATE TABLE test1(one int, two int, three int)}
+ execsql {COPY test1 FROM 'data1.txt'}
+ execsql {SELECT * FROM test1 ORDER BY one}
+} {11 22 33 22 33 11}
+
+# Make sure input terminates at \.
+#
+do_test copy-1.4 {
+ execsql {DELETE FROM test1}
+ execsql {COPY test1 FROM 'data2.txt'}
+ execsql {SELECT * FROM test1 ORDER BY one}
+} {11 22 33}
+
+# Test out the USING DELIMITERS clause
+#
+do_test copy-1.5 {
+ execsql {DELETE FROM test1}
+ execsql {COPY test1 FROM 'data4.txt' USING DELIMITERS ' | '}
+ execsql {SELECT * FROM test1 ORDER BY one}
+} {11 22 33 22 33 11}
+do_test copy-1.6 {
+ execsql {DELETE FROM test1}
+ execsql {COPY test1 FROM 'data5.txt' USING DELIMITERS '|'}
+ execsql {SELECT * FROM test1 ORDER BY one}
+} {11 22 33 22 33 11}
+do_test copy-1.7 {
+ execsql {DELETE FROM test1}
+ execsql {COPY test1 FROM 'data4.txt' USING DELIMITERS '|'}
+ execsql {SELECT * FROM test1 ORDER BY one}
+} {{11 } { 22 } { 33} {22 } { 33 } { 11}}
+
+# Try copying into a table that has one or more indices.
+#
+do_test copy-1.8 {
+ execsql {DELETE FROM test1}
+ execsql {CREATE INDEX index1 ON test1(one)}
+ execsql {CREATE INDEX index2 ON test1(two)}
+ execsql {CREATE INDEX index3 ON test1(three)}
+ execsql {COPY test1 from 'data1.txt'}
+ execsql {SELECT * FROM test1 WHERE one=11}
+} {11 22 33}
+do_test copy-1.8b {
+ execsql {SELECT * FROM test1 WHERE one=22}
+} {22 33 11}
+do_test copy-1.8c {
+ execsql {SELECT * FROM test1 WHERE two=22}
+} {11 22 33}
+do_test copy-1.8d {
+ execsql {SELECT * FROM test1 WHERE three=11}
+} {22 33 11}
+
+
+# Try inserting really long data
+#
+set x {}
+for {set i 0} {$i<100} {incr i} {
+ append x "($i)-abcdefghijklmnopqrstyvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-"
+}
+do_test copy-2.1 {
+ execsql {CREATE TABLE test2(a int, x text)}
+ set f [open data21.txt w]
+ puts $f "123\t$x"
+ close $f
+ execsql {COPY test2 FROM 'data21.txt'}
+ execsql {SELECT x from test2}
+} $x
+file delete -force data21.txt
+
+# Test the escape character mechanism
+#
+do_test copy-3.1 {
+ set fd [open data6.txt w]
+ puts $fd "hello\\\tworld\t1"
+ puts $fd "hello\tworld\\\t2"
+ close $fd
+ execsql {
+ CREATE TABLE t1(a text, b text);
+ COPY t1 FROM 'data6.txt';
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {hello {world 2} {hello world} 1}
+do_test copy-3.2 {
+ set fd [open data6.txt w]
+ puts $fd "1\thello\\\nworld"
+ puts $fd "2\thello world"
+ close $fd
+ execsql {
+ DELETE FROM t1;
+ COPY t1 FROM 'data6.txt';
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {hello
+world} 2 {hello world}}
+do_test copy-3.3 {
+ set fd [open data6.txt w]
+ puts $fd "1:hello\\b\\f\\n\\r\\t\\vworld"
+ puts $fd "2:hello world"
+ close $fd
+ execsql {
+ DELETE FROM t1;
+ COPY t1 FROM 'data6.txt' USING DELIMITERS ':';
+ SELECT * FROM t1 ORDER BY a;
+ }
+} [list 1 "hello\b\f\n\r\t\vworld" 2 "hello world"]
+
+# Test the embedded NULL logic.
+#
+do_test copy-4.1 {
+ set fd [open data6.txt w]
+ puts $fd "1\t\\N"
+ puts $fd "\\N\thello world"
+ close $fd
+ execsql {
+ DELETE FROM t1;
+ COPY t1 FROM 'data6.txt';
+ SELECT * FROM t1 WHERE a IS NULL;
+ }
+} {{} {hello world}}
+do_test copy-4.2 {
+ execsql {
+ SELECT * FROM t1 WHERE b IS NULL;
+ }
+} {1 {}}
+
+# Test the conflict resolution logic for COPY
+#
+do_test copy-5.1 {
+ execsql {
+ DROP TABLE t1;
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE, c);
+ COPY t1 FROM 'data5.txt' USING DELIMITERS '|';
+ SELECT * FROM t1;
+ }
+} {11 22 33 22 33 11}
+do_test copy-5.2 {
+ set fd [open data6.txt w]
+ puts $fd "33|22|44"
+ close $fd
+ catchsql {
+ COPY t1 FROM 'data6.txt' USING DELIMITERS '|';
+ SELECT * FROM t1;
+ }
+} {1 {column b is not unique}}
+do_test copy-5.3 {
+ set fd [open data6.txt w]
+ puts $fd "33|22|44"
+ close $fd
+ catchsql {
+ COPY OR IGNORE t1 FROM 'data6.txt' USING DELIMITERS '|';
+ SELECT * FROM t1;
+ }
+} {0 {11 22 33 22 33 11}}
+do_test copy-5.4 {
+ set fd [open data6.txt w]
+ puts $fd "33|22|44"
+ close $fd
+ catchsql {
+ COPY OR REPLACE t1 FROM 'data6.txt' USING DELIMITERS '|';
+ SELECT * FROM t1;
+ }
+} {0 {22 33 11 33 22 44}}
+
+do_test copy-5.5 {
+ execsql {
+ DELETE FROM t1;
+ PRAGMA count_changes=on;
+ COPY t1 FROM 'data5.txt' USING DELIMITERS '|';
+ }
+} {2}
+do_test copy-5.6 {
+ execsql {
+ COPY OR REPLACE t1 FROM 'data5.txt' USING DELIMITERS '|';
+ }
+} {2}
+do_test copy-5.7 {
+ execsql {
+ COPY OR IGNORE t1 FROM 'data5.txt' USING DELIMITERS '|';
+ }
+} {0}
+
+do_test copy-6.1 {
+ execsql {
+ PRAGMA count_changes=off;
+ CREATE TABLE t2(a,b,c);
+ COPY t2 FROM 'dataX.txt' USING DELIMITERS '|';
+ SELECT * FROM t2;
+ }
+} {11 22 33 22 33 44 33 44 55 44 55 66 55 66 77 66 77 88}
+
+integrity_check copy-7.1
+
+# Cleanup
+#
+#file delete -force data1.txt data2.txt data3.txt data4.txt data5.txt \
+ data6.txt dataX.txt
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/crashme2.off b/usr/src/lib/libsqlite/test/crashme2.off
new file mode 100644
index 0000000000..a6a4e77353
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/crashme2.off
@@ -0,0 +1,52 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+db close
+set DB [sqlite db test.db]
+
+execsql {
+ CREATE TABLE t1(a);
+ INSERT INTO t1 VALUES(1);
+ INSERT INTO t1 VALUES(2);
+ INSERT INTO t1 VALUES(3);
+ INSERT INTO t1 VALUES(4);
+}
+
+do_test capi3-13.1 {
+ execsql {
+ CREATE TABLE t3(a unique on conflict rollback);
+ INSERT INTO t3 SELECT a FROM t1;
+ BEGIN;
+ INSERT INTO t1 SELECT * FROM t1;
+ }
+} {}
+do_test capi3-13.2 {
+ set STMT [sqlite_compile $DB "SELECT a FROM t1" TAIL]
+ sqlite_step $STMT
+ sqlite_step $STMT
+ sqlite_step $STMT
+ sqlite_step $STMT
+ sqlite_step $STMT
+} {SQLITE_ROW}
+do_test capi3-13.3 {
+# This causes a ROLLBACK, which deletes the table out from underneath the
+# SELECT statement. Causes a crash.
+ catchsql {
+ INSERT INTO t3 SELECT a FROM t1;
+ }
+} {1 {column a is not unique}}
+do_test capi3-13.4 {
+ sqlite_step $STMT
+ sqlite_step $STMT
+ sqlite_step $STMT
+ sqlite_step $STMT
+} {SQLITE_DONE}
+do_test capi3-13.5 {
+ sqlite_finalize $STMT
+} {SQLITE_OK}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/crashtest1.c b/usr/src/lib/libsqlite/test/crashtest1.c
new file mode 100644
index 0000000000..ed82867dd8
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/crashtest1.c
@@ -0,0 +1,99 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+** This program tests the ability of SQLite database to recover from a crash.
+** This program runs under Unix only, but the results are applicable to all
+** systems.
+**
+** The main process first constructs a test database, then starts creating
+** subprocesses that write to that database. Each subprocess is killed off,
+** without a chance to clean up its database connection, after a random
+** delay. This killing of the subprocesses simulates a crash or power
+** failure. The next subprocess to open the database should rollback
+** whatever operation was in process at the time of the simulated crash.
+**
+** If any problems are encountered, an error is reported and the test stops.
+** If no problems are seen after a large number of tests, we assume that
+** the rollback mechanism is working.
+*/
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sched.h>
+#include "sqlite.h"
+
+static void do_some_sql(int parent){
+ char *zErr;
+ int rc = SQLITE_OK;
+ sqlite *db;
+ int cnt = 0;
+ static char zBig[] =
+ "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ if( access("./test.db-journal",0)==0 ){
+ /*printf("pid %d: journal exists. rollback will be required\n",getpid());*/ unlink("test.db-saved");
+ system("cp test.db test.db-saved");
+ unlink("test.db-journal-saved");
+ system("cp test.db-journal test.db-journal-saved");
+ }
+ db = sqlite_open("./test.db", 0, &zErr);
+ if( db==0 ){
+ printf("ERROR: %s\n", zErr);
+ if( strcmp(zErr,"database disk image is malformed")==0 ){
+ kill(parent, SIGKILL);
+ }
+ exit(1);
+ }
+ srand(getpid());
+ while( rc==SQLITE_OK ){
+ cnt++;
+ rc = sqlite_exec_printf(db,
+ "INSERT INTO t1 VALUES(%d,'%d%s')", 0, 0, &zErr,
+ rand(), rand(), zBig);
+ }
+ if( rc!=SQLITE_OK ){
+ printf("ERROR #%d: %s\n", rc, zErr);
+ if( rc==SQLITE_CORRUPT ){
+ kill(parent, SIGKILL);
+ }
+ }
+ printf("pid %d: cnt=%d\n", getpid(), cnt);
+}
+
+
+int main(int argc, char **argv){
+ int i;
+ sqlite *db;
+ char *zErr;
+ int status;
+ int parent = getpid();
+
+ unlink("test.db");
+ unlink("test.db-journal");
+ db = sqlite_open("test.db", 0, &zErr);
+ if( db==0 ){
+ printf("Cannot initialize: %s\n", zErr);
+ return 1;
+ }
+ sqlite_exec(db, "CREATE TABLE t1(a,b)", 0, 0, 0);
+ sqlite_close(db);
+ for(i=0; i<10000; i++){
+ int pid = fork();
+ if( pid==0 ){
+ sched_yield();
+ do_some_sql(parent);
+ return 0;
+ }
+ printf("test %d, pid=%d\n", i, pid);
+ usleep(rand()%10000 + 1000);
+ kill(pid, SIGKILL);
+ waitpid(pid, &status, 0);
+ }
+ return 0;
+}
diff --git a/usr/src/lib/libsqlite/test/date.test b/usr/src/lib/libsqlite/test/date.test
new file mode 100644
index 0000000000..b145e3cadd
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/date.test
@@ -0,0 +1,260 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2003 October 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.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing date and time functions.
+#
+# $Id: date.test,v 1.7.2.1 2004/07/18 22:25:16 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+proc datetest {tnum expr result} {
+ do_test date-$tnum [subst {
+ execsql "SELECT coalesce($expr,'NULL')"
+ }] [list $result]
+}
+
+datetest 1.1 julianday('2000-01-01') 2451544.5
+datetest 1.2 julianday('1970-01-01') 2440587.5
+datetest 1.3 julianday('1910-04-20') 2418781.5
+datetest 1.4 julianday('1986-02-09') 2446470.5
+datetest 1.5 julianday('12:00:00') 2451545
+datetest 1.6 {julianday('2000-01-01 12:00:00')} 2451545
+datetest 1.7 {julianday('2000-01-01 12:00')} 2451545
+datetest 1.8 julianday('bogus') NULL
+datetest 1.9 julianday('1999-12-31') 2451543.5
+datetest 1.10 julianday('1999-12-32') NULL
+datetest 1.11 julianday('1999-13-01') NULL
+datetest 1.12 julianday('2003-02-31') 2452701.5
+datetest 1.13 julianday('2003-03-03') 2452701.5
+datetest 1.14 julianday('+2000-01-01') NULL
+datetest 1.15 julianday('200-01-01') NULL
+datetest 1.16 julianday('2000-1-01') NULL
+datetest 1.17 julianday('2000-01-1') NULL
+datetest 1.18 {julianday('2000-01-01 12:00:00')} 2451545
+datetest 1.19 {julianday('2000-01-01 12:00:00.1')} 2451545.00000116
+datetest 1.20 {julianday('2000-01-01 12:00:00.01')} 2451545.00000012
+datetest 1.21 {julianday('2000-01-01 12:00:00.001')} 2451545.00000001
+datetest 1.22 {julianday('2000-01-01 12:00:00.')} NULL
+datetest 1.23 julianday(12345.6) 12345.6
+datetest 1.24 {julianday('2001-01-01 12:00:00 bogus')} NULL
+datetest 1.25 {julianday('2001-01-01 bogus')} NULL
+
+datetest 2.1 datetime(0,'unixepoch') {1970-01-01 00:00:00}
+datetest 2.2 datetime(946684800,'unixepoch') {2000-01-01 00:00:00}
+datetest 2.3 {date('2003-10-22','weekday 0')} 2003-10-26
+datetest 2.4 {date('2003-10-22','weekday 1')} 2003-10-27
+datetest 2.5 {date('2003-10-22','weekday 2')} 2003-10-28
+datetest 2.6 {date('2003-10-22','weekday 3')} 2003-10-22
+datetest 2.7 {date('2003-10-22','weekday 4')} 2003-10-23
+datetest 2.8 {date('2003-10-22','weekday 5')} 2003-10-24
+datetest 2.9 {date('2003-10-22','weekday 6')} 2003-10-25
+datetest 2.10 {date('2003-10-22','weekday 7')} NULL
+datetest 2.11 {date('2003-10-22','weekday 5.5')} NULL
+datetest 2.12 {datetime('2003-10-22 12:34','weekday 0')} {2003-10-26 12:34:00}
+datetest 2.13 {datetime('2003-10-22 12:34','start of month')} \
+ {2003-10-01 00:00:00}
+datetest 2.14 {datetime('2003-10-22 12:34','start of year')} \
+ {2003-01-01 00:00:00}
+datetest 2.15 {datetime('2003-10-22 12:34','start of day')} \
+ {2003-10-22 00:00:00}
+datetest 2.16 time('12:34:56.43') 12:34:56
+datetest 2.17 {datetime('2003-10-22 12:34','1 day')} {2003-10-23 12:34:00}
+datetest 2.18 {datetime('2003-10-22 12:34','+1 day')} {2003-10-23 12:34:00}
+datetest 2.19 {datetime('2003-10-22 12:34','+1.25 day')} {2003-10-23 18:34:00}
+datetest 2.20 {datetime('2003-10-22 12:34','-1.0 day')} {2003-10-21 12:34:00}
+datetest 2.21 {datetime('2003-10-22 12:34','1 month')} {2003-11-22 12:34:00}
+datetest 2.22 {datetime('2003-10-22 12:34','11 month')} {2004-09-22 12:34:00}
+datetest 2.23 {datetime('2003-10-22 12:34','-13 month')} {2002-09-22 12:34:00}
+datetest 2.24 {datetime('2003-10-22 12:34','1.5 months')} {2003-12-07 12:34:00}
+datetest 2.25 {datetime('2003-10-22 12:34','-5 years')} {1998-10-22 12:34:00}
+datetest 2.26 {datetime('2003-10-22 12:34','+10.5 minutes')} \
+ {2003-10-22 12:44:30}
+datetest 2.27 {datetime('2003-10-22 12:34','-1.25 hours')} \
+ {2003-10-22 11:19:00}
+datetest 2.28 {datetime('2003-10-22 12:34','11.25 seconds')} \
+ {2003-10-22 12:34:11}
+datetest 2.29 {datetime('2003-10-22 12:24','+5 bogus')} NULL
+
+
+datetest 3.1 {strftime('%d','2003-10-31 12:34:56.432')} 31
+datetest 3.2 {strftime('%f','2003-10-31 12:34:56.432')} 56.432
+datetest 3.3 {strftime('%H','2003-10-31 12:34:56.432')} 12
+datetest 3.4 {strftime('%j','2003-10-31 12:34:56.432')} 304
+datetest 3.5 {strftime('%J','2003-10-31 12:34:56.432')} 2452944.024264259
+datetest 3.6 {strftime('%m','2003-10-31 12:34:56.432')} 10
+datetest 3.7 {strftime('%M','2003-10-31 12:34:56.432')} 34
+datetest 3.8 {strftime('%s','2003-10-31 12:34:56.432')} 1067603696
+datetest 3.9 {strftime('%S','2003-10-31 12:34:56.432')} 56
+datetest 3.10 {strftime('%w','2003-10-31 12:34:56.432')} 5
+datetest 3.11.1 {strftime('%W','2003-10-31 12:34:56.432')} 43
+datetest 3.11.2 {strftime('%W','2004-01-01')} 00
+datetest 3.11.3 {strftime('%W','2004-01-02')} 00
+datetest 3.11.4 {strftime('%W','2004-01-03')} 00
+datetest 3.11.5 {strftime('%W','2004-01-04')} 00
+datetest 3.11.6 {strftime('%W','2004-01-05')} 01
+datetest 3.11.7 {strftime('%W','2004-01-06')} 01
+datetest 3.11.8 {strftime('%W','2004-01-07')} 01
+datetest 3.11.9 {strftime('%W','2004-01-08')} 01
+datetest 3.11.10 {strftime('%W','2004-01-09')} 01
+datetest 3.11.11 {strftime('%W','2004-07-18')} 28
+datetest 3.11.12 {strftime('%W','2004-12-31')} 52
+datetest 3.11.13 {strftime('%W','2007-12-31')} 53
+datetest 3.11.14 {strftime('%W','2007-01-01')} 01
+datetest 3.12 {strftime('%Y','2003-10-31 12:34:56.432')} 2003
+datetest 3.13 {strftime('%%','2003-10-31 12:34:56.432')} %
+datetest 3.14 {strftime('%_','2003-10-31 12:34:56.432')} NULL
+datetest 3.15 {strftime('%Y-%m-%d','2003-10-31')} 2003-10-31
+proc repeat {n txt} {
+ set x {}
+ while {$n>0} {
+ append x $txt
+ incr n -1
+ }
+ return $x
+}
+datetest 3.16 "strftime('[repeat 200 %Y]','2003-10-31')" [repeat 200 2003]
+datetest 3.17 "strftime('[repeat 200 abc%m123]','2003-10-31')" \
+ [repeat 200 abc10123]
+
+set now [clock format [clock seconds] -format "%Y-%m-%d" -gmt 1]
+datetest 4.1 {date('now')} $now
+
+datetest 5.1 {datetime('1994-04-16 14:00:00 -05:00')} {1994-04-16 09:00:00}
+datetest 5.2 {datetime('1994-04-16 14:00:00 +05:15')} {1994-04-16 19:15:00}
+datetest 5.3 {datetime('1994-04-16 05:00:00 -08:30')} {1994-04-15 20:30:00}
+datetest 5.4 {datetime('1994-04-16 14:00:00 +11:55')} {1994-04-17 01:55:00}
+
+# localtime->utc and utc->localtime conversions. These tests only work
+# if the localtime is in the US Eastern Time (the time in Charlotte, NC
+# and in New York.)
+#
+if {[clock scan [clock format 0 -format {%b %d, %Y %H:%M:%S}] -gmt 1]==-18000} {
+ datetest 6.1 {datetime('2000-10-29 05:59:00','localtime')}\
+ {2000-10-29 01:59:00}
+ datetest 6.2 {datetime('2000-10-29 06:00:00','localtime')}\
+ {2000-10-29 01:00:00}
+ datetest 6.3 {datetime('2000-04-02 06:59:00','localtime')}\
+ {2000-04-02 01:59:00}
+ datetest 6.4 {datetime('2000-04-02 07:00:00','localtime')}\
+ {2000-04-02 03:00:00}
+ datetest 6.5 {datetime('2000-10-29 01:59:00','utc')} {2000-10-29 05:59:00}
+ datetest 6.6 {datetime('2000-10-29 02:00:00','utc')} {2000-10-29 07:00:00}
+ datetest 6.7 {datetime('2000-04-02 01:59:00','utc')} {2000-04-02 06:59:00}
+ datetest 6.8 {datetime('2000-04-02 02:00:00','utc')} {2000-04-02 06:00:00}
+
+ datetest 6.10 {datetime('2000-01-01 12:00:00','localtime')} \
+ {2000-01-01 07:00:00}
+ datetest 6.11 {datetime('1969-01-01 12:00:00','localtime')} \
+ {1969-01-01 07:00:00}
+ datetest 6.12 {datetime('2039-01-01 12:00:00','localtime')} \
+ {2039-01-01 07:00:00}
+ datetest 6.13 {datetime('2000-07-01 12:00:00','localtime')} \
+ {2000-07-01 08:00:00}
+ datetest 6.14 {datetime('1969-07-01 12:00:00','localtime')} \
+ {1969-07-01 07:00:00}
+ datetest 6.15 {datetime('2039-07-01 12:00:00','localtime')} \
+ {2039-07-01 07:00:00}
+ set sqlite_current_time \
+ [db eval {SELECT strftime('%s','2000-07-01 12:34:56')}]
+ datetest 6.16 {datetime('now','localtime')} {2000-07-01 08:34:56}
+ set sqlite_current_time 0
+}
+
+# Date-time functions that contain NULL arguments return a NULL
+# result.
+#
+datetest 7.1 {datetime(null)} NULL
+datetest 7.2 {datetime('now',null)} NULL
+datetest 7.3 {datetime('now','localtime',null)} NULL
+datetest 7.4 {time(null)} NULL
+datetest 7.5 {time('now',null)} NULL
+datetest 7.6 {time('now','localtime',null)} NULL
+datetest 7.7 {date(null)} NULL
+datetest 7.8 {date('now',null)} NULL
+datetest 7.9 {date('now','localtime',null)} NULL
+datetest 7.10 {julianday(null)} NULL
+datetest 7.11 {julianday('now',null)} NULL
+datetest 7.12 {julianday('now','localtime',null)} NULL
+datetest 7.13 {strftime(null,'now')} NULL
+datetest 7.14 {strftime('%s',null)} NULL
+datetest 7.15 {strftime('%s','now',null)} NULL
+datetest 7.16 {strftime('%s','now','localtime',null)} NULL
+
+# Test modifiers when the date begins as a julian day number - to
+# make sure the HH:MM:SS is preserved. Ticket #551.
+#
+set sqlite_current_time [db eval {SELECT strftime('%s','2003-10-22 12:34:00')}]
+datetest 8.1 {datetime('now','weekday 0')} {2003-10-26 12:34:00}
+datetest 8.2 {datetime('now','weekday 1')} {2003-10-27 12:34:00}
+datetest 8.3 {datetime('now','weekday 2')} {2003-10-28 12:34:00}
+datetest 8.4 {datetime('now','weekday 3')} {2003-10-22 12:34:00}
+datetest 8.5 {datetime('now','start of month')} {2003-10-01 00:00:00}
+datetest 8.6 {datetime('now','start of year')} {2003-01-01 00:00:00}
+datetest 8.7 {datetime('now','start of day')} {2003-10-22 00:00:00}
+datetest 8.8 {datetime('now','1 day')} {2003-10-23 12:34:00}
+datetest 8.9 {datetime('now','+1 day')} {2003-10-23 12:34:00}
+datetest 8.10 {datetime('now','+1.25 day')} {2003-10-23 18:34:00}
+datetest 8.11 {datetime('now','-1.0 day')} {2003-10-21 12:34:00}
+datetest 8.12 {datetime('now','1 month')} {2003-11-22 12:34:00}
+datetest 8.13 {datetime('now','11 month')} {2004-09-22 12:34:00}
+datetest 8.14 {datetime('now','-13 month')} {2002-09-22 12:34:00}
+datetest 8.15 {datetime('now','1.5 months')} {2003-12-07 12:34:00}
+datetest 8.16 {datetime('now','-5 years')} {1998-10-22 12:34:00}
+datetest 8.17 {datetime('now','+10.5 minutes')} {2003-10-22 12:44:30}
+datetest 8.18 {datetime('now','-1.25 hours')} {2003-10-22 11:19:00}
+datetest 8.19 {datetime('now','11.25 seconds')} {2003-10-22 12:34:11}
+set sqlite_current_time 0
+
+# Negative years work. Example: '-4713-11-26' is JD 1.5.
+#
+datetest 9.1 {julianday('-4713-11-24 12:00:00')} {0}
+datetest 9.2 {julianday(datetime(5))} {5}
+datetest 9.3 {julianday(datetime(10))} {10}
+datetest 9.4 {julianday(datetime(100))} {100}
+datetest 9.5 {julianday(datetime(1000))} {1000}
+datetest 9.6 {julianday(datetime(10000))} {10000}
+datetest 9.7 {julianday(datetime(100000))} {100000}
+
+# datetime() with just an HH:MM:SS correctly inserts the date 2000-01-01.
+#
+datetest 10.1 {datetime('01:02:03')} {2000-01-01 01:02:03}
+datetest 10.2 {date('01:02:03')} {2000-01-01}
+datetest 10.3 {strftime('%Y-%m-%d %H:%M','01:02:03')} {2000-01-01 01:02}
+
+# Test the new HH:MM:SS modifier
+#
+datetest 11.1 {datetime('2004-02-28 20:00:00', '-01:20:30')} \
+ {2004-02-28 18:39:30}
+datetest 11.2 {datetime('2004-02-28 20:00:00', '+12:30:00')} \
+ {2004-02-29 08:30:00}
+datetest 11.3 {datetime('2004-02-28 20:00:00', '+12:30')} \
+ {2004-02-29 08:30:00}
+datetest 11.4 {datetime('2004-02-28 20:00:00', '12:30')} \
+ {2004-02-29 08:30:00}
+datetest 11.5 {datetime('2004-02-28 20:00:00', '-12:00')} \
+ {2004-02-28 08:00:00}
+datetest 11.6 {datetime('2004-02-28 20:00:00', '-12:01')} \
+ {2004-02-28 07:59:00}
+datetest 11.7 {datetime('2004-02-28 20:00:00', '-11:59')} \
+ {2004-02-28 08:01:00}
+datetest 11.8 {datetime('2004-02-28 20:00:00', '11:59')} \
+ {2004-02-29 07:59:00}
+datetest 11.9 {datetime('2004-02-28 20:00:00', '12:01')} \
+ {2004-02-29 08:01:00}
+
+
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/delete.test b/usr/src/lib/libsqlite/test/delete.test
new file mode 100644
index 0000000000..1676323507
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/delete.test
@@ -0,0 +1,294 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 DELETE FROM statement.
+#
+# $Id: delete.test,v 1.13 2003/06/15 23:42:25 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Try to delete from a non-existant table.
+#
+do_test delete-1.1 {
+ set v [catch {execsql {DELETE FROM test1}} msg]
+ lappend v $msg
+} {1 {no such table: test1}}
+
+# Try to delete from sqlite_master
+#
+do_test delete-2.1 {
+ set v [catch {execsql {DELETE FROM sqlite_master}} msg]
+ lappend v $msg
+} {1 {table sqlite_master may not be modified}}
+
+# Delete selected entries from a table with and without an index.
+#
+do_test delete-3.1.1 {
+ execsql {CREATE TABLE table1(f1 int, f2 int)}
+ execsql {INSERT INTO table1 VALUES(1,2)}
+ execsql {INSERT INTO table1 VALUES(2,4)}
+ execsql {INSERT INTO table1 VALUES(3,8)}
+ execsql {INSERT INTO table1 VALUES(4,16)}
+ execsql {SELECT * FROM table1 ORDER BY f1}
+} {1 2 2 4 3 8 4 16}
+do_test delete-3.1.2 {
+ execsql {DELETE FROM table1 WHERE f1=3}
+} {}
+do_test delete-3.1.3 {
+ execsql {SELECT * FROM table1 ORDER BY f1}
+} {1 2 2 4 4 16}
+do_test delete-3.1.4 {
+ execsql {CREATE INDEX index1 ON table1(f1)}
+ execsql {PRAGMA count_changes=on}
+ execsql {DELETE FROM 'table1' WHERE f1=3}
+} {0}
+do_test delete-3.1.5 {
+ execsql {SELECT * FROM table1 ORDER BY f1}
+} {1 2 2 4 4 16}
+do_test delete-3.1.6 {
+ execsql {DELETE FROM table1 WHERE f1=2}
+} {1}
+do_test delete-3.1.7 {
+ execsql {SELECT * FROM table1 ORDER BY f1}
+} {1 2 4 16}
+integrity_check delete-3.2
+
+
+# Semantic errors in the WHERE clause
+#
+do_test delete-4.1 {
+ execsql {CREATE TABLE table2(f1 int, f2 int)}
+ set v [catch {execsql {DELETE FROM table2 WHERE f3=5}} msg]
+ lappend v $msg
+} {1 {no such column: f3}}
+
+do_test delete-4.2 {
+ set v [catch {execsql {DELETE FROM table2 WHERE xyzzy(f1+4)}} msg]
+ lappend v $msg
+} {1 {no such function: xyzzy}}
+integrity_check delete-4.3
+
+# Lots of deletes
+#
+do_test delete-5.1.1 {
+ execsql {DELETE FROM table1}
+} {2}
+do_test delete-5.1.2 {
+ execsql {SELECT count(*) FROM table1}
+} {0}
+do_test delete-5.2.1 {
+ execsql {BEGIN TRANSACTION}
+ for {set i 1} {$i<=200} {incr i} {
+ execsql "INSERT INTO table1 VALUES($i,[expr {$i*$i}])"
+ }
+ execsql {COMMIT}
+ execsql {SELECT count(*) FROM table1}
+} {200}
+do_test delete-5.2.2 {
+ execsql {DELETE FROM table1}
+} {200}
+do_test delete-5.2.3 {
+ execsql {BEGIN TRANSACTION}
+ for {set i 1} {$i<=200} {incr i} {
+ execsql "INSERT INTO table1 VALUES($i,[expr {$i*$i}])"
+ }
+ execsql {COMMIT}
+ execsql {SELECT count(*) FROM table1}
+} {200}
+do_test delete-5.2.4 {
+ execsql {PRAGMA count_changes=off}
+ execsql {DELETE FROM table1}
+} {}
+do_test delete-5.2.5 {
+ execsql {SELECT count(*) FROM table1}
+} {0}
+do_test delete-5.2.6 {
+ execsql {BEGIN TRANSACTION}
+ for {set i 1} {$i<=200} {incr i} {
+ execsql "INSERT INTO table1 VALUES($i,[expr {$i*$i}])"
+ }
+ execsql {COMMIT}
+ execsql {SELECT count(*) FROM table1}
+} {200}
+do_test delete-5.3 {
+ for {set i 1} {$i<=200} {incr i 4} {
+ execsql "DELETE FROM table1 WHERE f1==$i"
+ }
+ execsql {SELECT count(*) FROM table1}
+} {150}
+do_test delete-5.4 {
+ execsql "DELETE FROM table1 WHERE f1>50"
+ execsql {SELECT count(*) FROM table1}
+} {37}
+do_test delete-5.5 {
+ for {set i 1} {$i<=70} {incr i 3} {
+ execsql "DELETE FROM table1 WHERE f1==$i"
+ }
+ execsql {SELECT f1 FROM table1 ORDER BY f1}
+} {2 3 6 8 11 12 14 15 18 20 23 24 26 27 30 32 35 36 38 39 42 44 47 48 50}
+do_test delete-5.6 {
+ for {set i 1} {$i<40} {incr i} {
+ execsql "DELETE FROM table1 WHERE f1==$i"
+ }
+ execsql {SELECT f1 FROM table1 ORDER BY f1}
+} {42 44 47 48 50}
+do_test delete-5.7 {
+ execsql "DELETE FROM table1 WHERE f1!=48"
+ execsql {SELECT f1 FROM table1 ORDER BY f1}
+} {48}
+integrity_check delete-5.8
+
+
+# Delete large quantities of data. We want to test the List overflow
+# mechanism in the vdbe.
+#
+do_test delete-6.1 {
+ set fd [open data1.txt w]
+ for {set i 1} {$i<=3000} {incr i} {
+ puts $fd "[expr {$i}]\t[expr {$i*$i}]"
+ }
+ close $fd
+ execsql {DELETE FROM table1}
+ execsql {COPY table1 FROM 'data1.txt'}
+ execsql {DELETE FROM table2}
+ execsql {COPY table2 FROM 'data1.txt'}
+ file delete data1.txt
+ execsql {SELECT count(*) FROM table1}
+} {3000}
+do_test delete-6.2 {
+ execsql {SELECT count(*) FROM table2}
+} {3000}
+do_test delete-6.3 {
+ execsql {SELECT f1 FROM table1 WHERE f1<10 ORDER BY f1}
+} {1 2 3 4 5 6 7 8 9}
+do_test delete-6.4 {
+ execsql {SELECT f1 FROM table2 WHERE f1<10 ORDER BY f1}
+} {1 2 3 4 5 6 7 8 9}
+do_test delete-6.5 {
+ execsql {DELETE FROM table1 WHERE f1>7}
+ execsql {SELECT f1 FROM table1 ORDER BY f1}
+} {1 2 3 4 5 6 7}
+do_test delete-6.6 {
+ execsql {DELETE FROM table2 WHERE f1>7}
+ execsql {SELECT f1 FROM table2 ORDER BY f1}
+} {1 2 3 4 5 6 7}
+do_test delete-6.7 {
+ execsql {DELETE FROM table1}
+ execsql {SELECT f1 FROM table1}
+} {}
+do_test delete-6.8 {
+ execsql {INSERT INTO table1 VALUES(2,3)}
+ execsql {SELECT f1 FROM table1}
+} {2}
+do_test delete-6.9 {
+ execsql {DELETE FROM table2}
+ execsql {SELECT f1 FROM table2}
+} {}
+do_test delete-6.10 {
+ execsql {INSERT INTO table2 VALUES(2,3)}
+ execsql {SELECT f1 FROM table2}
+} {2}
+integrity_check delete-6.11
+
+do_test delete-7.1 {
+ execsql {
+ CREATE TABLE t3(a);
+ INSERT INTO t3 VALUES(1);
+ INSERT INTO t3 SELECT a+1 FROM t3;
+ INSERT INTO t3 SELECT a+2 FROM t3;
+ SELECT * FROM t3;
+ }
+} {1 2 3 4}
+do_test delete-7.2 {
+ execsql {
+ CREATE TABLE cnt(del);
+ INSERT INTO cnt VALUES(0);
+ CREATE TRIGGER r1 AFTER DELETE ON t3 FOR EACH ROW BEGIN
+ UPDATE cnt SET del=del+1;
+ END;
+ DELETE FROM t3 WHERE a<2;
+ SELECT * FROM t3;
+ }
+} {2 3 4}
+do_test delete-7.3 {
+ execsql {
+ SELECT * FROM cnt;
+ }
+} {1}
+do_test delete-7.4 {
+ execsql {
+ DELETE FROM t3;
+ SELECT * FROM t3;
+ }
+} {}
+do_test delete-7.5 {
+ execsql {
+ SELECT * FROM cnt;
+ }
+} {4}
+do_test delete-7.6 {
+ execsql {
+ INSERT INTO t3 VALUES(1);
+ INSERT INTO t3 SELECT a+1 FROM t3;
+ INSERT INTO t3 SELECT a+2 FROM t3;
+ CREATE TABLE t4 AS SELECT * FROM t3;
+ PRAGMA count_changes=ON;
+ DELETE FROM t3;
+ DELETE FROM t4;
+ }
+} {4 4}
+integrity_check delete-7.7
+
+# Make sure error messages are consistent when attempting to delete
+# from a read-only database. Ticket #304.
+#
+do_test delete-8.0 {
+ execsql {
+ PRAGMA count_changes=OFF;
+ INSERT INTO t3 VALUES(123);
+ SELECT * FROM t3;
+ }
+} {123}
+db close
+catch {file attributes test.db -permissions 0444}
+catch {file attributes test.db -readonly 1}
+sqlite db test.db
+do_test delete-8.1 {
+ catchsql {
+ DELETE FROM t3;
+ }
+} {1 {attempt to write a readonly database}}
+do_test delete-8.2 {
+ execsql {SELECT * FROM t3}
+} {123}
+do_test delete-8.3 {
+ catchsql {
+ DELETE FROM t3 WHERE 1;
+ }
+} {1 {attempt to write a readonly database}}
+do_test delete-8.4 {
+ execsql {SELECT * FROM t3}
+} {123}
+do_test delete-8.5 {
+ catchsql {
+ DELETE FROM t3 WHERE a<100;
+ }
+} {0 {}}
+do_test delete-8.6 {
+ execsql {SELECT * FROM t3}
+} {123}
+integrity_check delete-8.7
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/expr.test b/usr/src/lib/libsqlite/test/expr.test
new file mode 100644
index 0000000000..2f4fb26924
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/expr.test
@@ -0,0 +1,522 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 expressions.
+#
+# $Id: expr.test,v 1.31 2004/03/03 01:51:25 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a table to work with.
+#
+execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}
+execsql {INSERT INTO test1 VALUES(1,2,1.1,2.2,'hello','world')}
+proc test_expr {name settings expr result} {
+ do_test $name [format {
+ execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
+ } $settings $expr] $result
+}
+
+test_expr expr-1.1 {i1=10, i2=20} {i1+i2} 30
+test_expr expr-1.2 {i1=10, i2=20} {i1-i2} -10
+test_expr expr-1.3 {i1=10, i2=20} {i1*i2} 200
+test_expr expr-1.4 {i1=10, i2=20} {i1/i2} 0.5
+test_expr expr-1.5 {i1=10, i2=20} {i2/i1} 2
+test_expr expr-1.6 {i1=10, i2=20} {i2<i1} 0
+test_expr expr-1.7 {i1=10, i2=20} {i2<=i1} 0
+test_expr expr-1.8 {i1=10, i2=20} {i2>i1} 1
+test_expr expr-1.9 {i1=10, i2=20} {i2>=i1} 1
+test_expr expr-1.10 {i1=10, i2=20} {i2!=i1} 1
+test_expr expr-1.11 {i1=10, i2=20} {i2=i1} 0
+test_expr expr-1.12 {i1=10, i2=20} {i2<>i1} 1
+test_expr expr-1.13 {i1=10, i2=20} {i2==i1} 0
+test_expr expr-1.14 {i1=20, i2=20} {i2<i1} 0
+test_expr expr-1.15 {i1=20, i2=20} {i2<=i1} 1
+test_expr expr-1.16 {i1=20, i2=20} {i2>i1} 0
+test_expr expr-1.17 {i1=20, i2=20} {i2>=i1} 1
+test_expr expr-1.18 {i1=20, i2=20} {i2!=i1} 0
+test_expr expr-1.19 {i1=20, i2=20} {i2=i1} 1
+test_expr expr-1.20 {i1=20, i2=20} {i2<>i1} 0
+test_expr expr-1.21 {i1=20, i2=20} {i2==i1} 1
+test_expr expr-1.22 {i1=1, i2=2, r1=3.0} {i1+i2*r1} {7}
+test_expr expr-1.23 {i1=1, i2=2, r1=3.0} {(i1+i2)*r1} {9}
+test_expr expr-1.24 {i1=1, i2=2} {min(i1,i2,i1+i2,i1-i2)} {-1}
+test_expr expr-1.25 {i1=1, i2=2} {max(i1,i2,i1+i2,i1-i2)} {3}
+test_expr expr-1.26 {i1=1, i2=2} {max(i1,i2,i1+i2,i1-i2)} {3}
+test_expr expr-1.27 {i1=1, i2=2} {i1==1 AND i2=2} {1}
+test_expr expr-1.28 {i1=1, i2=2} {i1=2 AND i2=1} {0}
+test_expr expr-1.29 {i1=1, i2=2} {i1=1 AND i2=1} {0}
+test_expr expr-1.30 {i1=1, i2=2} {i1=2 AND i2=2} {0}
+test_expr expr-1.31 {i1=1, i2=2} {i1==1 OR i2=2} {1}
+test_expr expr-1.32 {i1=1, i2=2} {i1=2 OR i2=1} {0}
+test_expr expr-1.33 {i1=1, i2=2} {i1=1 OR i2=1} {1}
+test_expr expr-1.34 {i1=1, i2=2} {i1=2 OR i2=2} {1}
+test_expr expr-1.35 {i1=1, i2=2} {i1-i2=-1} {1}
+test_expr expr-1.36 {i1=1, i2=0} {not i1} {0}
+test_expr expr-1.37 {i1=1, i2=0} {not i2} {1}
+test_expr expr-1.38 {i1=1} {-i1} {-1}
+test_expr expr-1.39 {i1=1} {+i1} {1}
+test_expr expr-1.40 {i1=1, i2=2} {+(i2+i1)} {3}
+test_expr expr-1.41 {i1=1, i2=2} {-(i2+i1)} {-3}
+test_expr expr-1.42 {i1=1, i2=2} {i1|i2} {3}
+test_expr expr-1.42b {i1=1, i2=2} {4|2} {6}
+test_expr expr-1.43 {i1=1, i2=2} {i1&i2} {0}
+test_expr expr-1.43b {i1=1, i2=2} {4&5} {4}
+test_expr expr-1.44 {i1=1} {~i1} {-2}
+test_expr expr-1.45 {i1=1, i2=3} {i1<<i2} {8}
+test_expr expr-1.46 {i1=32, i2=3} {i1>>i2} {4}
+test_expr expr-1.47 {i1=9999999999, i2=8888888888} {i1<i2} 0
+test_expr expr-1.48 {i1=9999999999, i2=8888888888} {i1=i2} 0
+test_expr expr-1.49 {i1=9999999999, i2=8888888888} {i1>i2} 1
+test_expr expr-1.50 {i1=99999999999, i2=99999999998} {i1<i2} 0
+test_expr expr-1.51 {i1=99999999999, i2=99999999998} {i1=i2} 0
+test_expr expr-1.52 {i1=99999999999, i2=99999999998} {i1>i2} 1
+test_expr expr-1.53 {i1=099999999999, i2=99999999999} {i1<i2} 0
+test_expr expr-1.54 {i1=099999999999, i2=99999999999} {i1=i2} 1
+test_expr expr-1.55 {i1=099999999999, i2=99999999999} {i1>i2} 0
+test_expr expr-1.56 {i1=25, i2=11} {i1%i2} 3
+test_expr expr-1.58 {i1=NULL, i2=1} {coalesce(i1+i2,99)} 99
+test_expr expr-1.59 {i1=1, i2=NULL} {coalesce(i1+i2,99)} 99
+test_expr expr-1.60 {i1=NULL, i2=NULL} {coalesce(i1+i2,99)} 99
+test_expr expr-1.61 {i1=NULL, i2=1} {coalesce(i1-i2,99)} 99
+test_expr expr-1.62 {i1=1, i2=NULL} {coalesce(i1-i2,99)} 99
+test_expr expr-1.63 {i1=NULL, i2=NULL} {coalesce(i1-i2,99)} 99
+test_expr expr-1.64 {i1=NULL, i2=1} {coalesce(i1*i2,99)} 99
+test_expr expr-1.65 {i1=1, i2=NULL} {coalesce(i1*i2,99)} 99
+test_expr expr-1.66 {i1=NULL, i2=NULL} {coalesce(i1*i2,99)} 99
+test_expr expr-1.67 {i1=NULL, i2=1} {coalesce(i1/i2,99)} 99
+test_expr expr-1.68 {i1=1, i2=NULL} {coalesce(i1/i2,99)} 99
+test_expr expr-1.69 {i1=NULL, i2=NULL} {coalesce(i1/i2,99)} 99
+test_expr expr-1.70 {i1=NULL, i2=1} {coalesce(i1<i2,99)} 99
+test_expr expr-1.71 {i1=1, i2=NULL} {coalesce(i1>i2,99)} 99
+test_expr expr-1.72 {i1=NULL, i2=NULL} {coalesce(i1<=i2,99)} 99
+test_expr expr-1.73 {i1=NULL, i2=1} {coalesce(i1>=i2,99)} 99
+test_expr expr-1.74 {i1=1, i2=NULL} {coalesce(i1!=i2,99)} 99
+test_expr expr-1.75 {i1=NULL, i2=NULL} {coalesce(i1==i2,99)} 99
+test_expr expr-1.76 {i1=NULL, i2=NULL} {coalesce(not i1,99)} 99
+test_expr expr-1.77 {i1=NULL, i2=NULL} {coalesce(-i1,99)} 99
+test_expr expr-1.78 {i1=NULL, i2=NULL} {coalesce(i1 IS NULL AND i2=5,99)} 99
+test_expr expr-1.79 {i1=NULL, i2=NULL} {coalesce(i1 IS NULL OR i2=5,99)} 1
+test_expr expr-1.80 {i1=NULL, i2=NULL} {coalesce(i1=5 AND i2 IS NULL,99)} 99
+test_expr expr-1.81 {i1=NULL, i2=NULL} {coalesce(i1=5 OR i2 IS NULL,99)} 1
+test_expr expr-1.82 {i1=NULL, i2=3} {coalesce(min(i1,i2,1),99)} 99
+test_expr expr-1.83 {i1=NULL, i2=3} {coalesce(max(i1,i2,1),99)} 99
+test_expr expr-1.84 {i1=3, i2=NULL} {coalesce(min(i1,i2,1),99)} 99
+test_expr expr-1.85 {i1=3, i2=NULL} {coalesce(max(i1,i2,1),99)} 99
+test_expr expr-1.86 {i1=3, i2=8} {5 between i1 and i2} 1
+test_expr expr-1.87 {i1=3, i2=8} {5 not between i1 and i2} 0
+test_expr expr-1.88 {i1=3, i2=8} {55 between i1 and i2} 0
+test_expr expr-1.89 {i1=3, i2=8} {55 not between i1 and i2} 1
+test_expr expr-1.90 {i1=3, i2=NULL} {5 between i1 and i2} {{}}
+test_expr expr-1.91 {i1=3, i2=NULL} {5 not between i1 and i2} {{}}
+test_expr expr-1.92 {i1=3, i2=NULL} {2 between i1 and i2} 0
+test_expr expr-1.93 {i1=3, i2=NULL} {2 not between i1 and i2} 1
+test_expr expr-1.94 {i1=NULL, i2=8} {2 between i1 and i2} {{}}
+test_expr expr-1.95 {i1=NULL, i2=8} {2 not between i1 and i2} {{}}
+test_expr expr-1.94 {i1=NULL, i2=8} {55 between i1 and i2} 0
+test_expr expr-1.95 {i1=NULL, i2=8} {55 not between i1 and i2} 1
+test_expr expr-1.96 {i1=NULL, i2=3} {coalesce(i1<<i2,99)} 99
+test_expr expr-1.97 {i1=32, i2=NULL} {coalesce(i1>>i2,99)} 99
+test_expr expr-1.98 {i1=NULL, i2=NULL} {coalesce(i1|i2,99)} 99
+test_expr expr-1.99 {i1=32, i2=NULL} {coalesce(i1&i2,99)} 99
+test_expr expr-1.100 {i1=1, i2=''} {i1=i2} 0
+test_expr expr-1.101 {i1=0, i2=''} {i1=i2} 0
+
+test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
+test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
+test_expr expr-2.3 {r1=1.23, r2=2.34} {r1*r2} 2.8782
+test_expr expr-2.4 {r1=1.23, r2=2.34} {r1/r2} 0.525641025641026
+test_expr expr-2.5 {r1=1.23, r2=2.34} {r2/r1} 1.90243902439024
+test_expr expr-2.6 {r1=1.23, r2=2.34} {r2<r1} 0
+test_expr expr-2.7 {r1=1.23, r2=2.34} {r2<=r1} 0
+test_expr expr-2.8 {r1=1.23, r2=2.34} {r2>r1} 1
+test_expr expr-2.9 {r1=1.23, r2=2.34} {r2>=r1} 1
+test_expr expr-2.10 {r1=1.23, r2=2.34} {r2!=r1} 1
+test_expr expr-2.11 {r1=1.23, r2=2.34} {r2=r1} 0
+test_expr expr-2.12 {r1=1.23, r2=2.34} {r2<>r1} 1
+test_expr expr-2.13 {r1=1.23, r2=2.34} {r2==r1} 0
+test_expr expr-2.14 {r1=2.34, r2=2.34} {r2<r1} 0
+test_expr expr-2.15 {r1=2.34, r2=2.34} {r2<=r1} 1
+test_expr expr-2.16 {r1=2.34, r2=2.34} {r2>r1} 0
+test_expr expr-2.17 {r1=2.34, r2=2.34} {r2>=r1} 1
+test_expr expr-2.18 {r1=2.34, r2=2.34} {r2!=r1} 0
+test_expr expr-2.19 {r1=2.34, r2=2.34} {r2=r1} 1
+test_expr expr-2.20 {r1=2.34, r2=2.34} {r2<>r1} 0
+test_expr expr-2.21 {r1=2.34, r2=2.34} {r2==r1} 1
+test_expr expr-2.22 {r1=1.23, r2=2.34} {min(r1,r2,r1+r2,r1-r2)} {-1.11}
+test_expr expr-2.23 {r1=1.23, r2=2.34} {max(r1,r2,r1+r2,r1-r2)} {3.57}
+test_expr expr-2.24 {r1=25.0, r2=11.0} {r1%r2} 3
+test_expr expr-2.25 {r1=1.23, r2=NULL} {coalesce(r1+r2,99.0)} 99.0
+
+test_expr expr-3.1 {t1='abc', t2='xyz'} {t1<t2} 1
+test_expr expr-3.2 {t1='xyz', t2='abc'} {t1<t2} 0
+test_expr expr-3.3 {t1='abc', t2='abc'} {t1<t2} 0
+test_expr expr-3.4 {t1='abc', t2='xyz'} {t1<=t2} 1
+test_expr expr-3.5 {t1='xyz', t2='abc'} {t1<=t2} 0
+test_expr expr-3.6 {t1='abc', t2='abc'} {t1<=t2} 1
+test_expr expr-3.7 {t1='abc', t2='xyz'} {t1>t2} 0
+test_expr expr-3.8 {t1='xyz', t2='abc'} {t1>t2} 1
+test_expr expr-3.9 {t1='abc', t2='abc'} {t1>t2} 0
+test_expr expr-3.10 {t1='abc', t2='xyz'} {t1>=t2} 0
+test_expr expr-3.11 {t1='xyz', t2='abc'} {t1>=t2} 1
+test_expr expr-3.12 {t1='abc', t2='abc'} {t1>=t2} 1
+test_expr expr-3.13 {t1='abc', t2='xyz'} {t1=t2} 0
+test_expr expr-3.14 {t1='xyz', t2='abc'} {t1=t2} 0
+test_expr expr-3.15 {t1='abc', t2='abc'} {t1=t2} 1
+test_expr expr-3.16 {t1='abc', t2='xyz'} {t1==t2} 0
+test_expr expr-3.17 {t1='xyz', t2='abc'} {t1==t2} 0
+test_expr expr-3.18 {t1='abc', t2='abc'} {t1==t2} 1
+test_expr expr-3.19 {t1='abc', t2='xyz'} {t1<>t2} 1
+test_expr expr-3.20 {t1='xyz', t2='abc'} {t1<>t2} 1
+test_expr expr-3.21 {t1='abc', t2='abc'} {t1<>t2} 0
+test_expr expr-3.22 {t1='abc', t2='xyz'} {t1!=t2} 1
+test_expr expr-3.23 {t1='xyz', t2='abc'} {t1!=t2} 1
+test_expr expr-3.24 {t1='abc', t2='abc'} {t1!=t2} 0
+test_expr expr-3.25 {t1=NULL, t2='hi'} {t1 isnull} 1
+test_expr expr-3.25b {t1=NULL, t2='hi'} {t1 is null} 1
+test_expr expr-3.26 {t1=NULL, t2='hi'} {t2 isnull} 0
+test_expr expr-3.27 {t1=NULL, t2='hi'} {t1 notnull} 0
+test_expr expr-3.28 {t1=NULL, t2='hi'} {t2 notnull} 1
+test_expr expr-3.28b {t1=NULL, t2='hi'} {t2 is not null} 1
+test_expr expr-3.29 {t1='xyz', t2='abc'} {t1||t2} {xyzabc}
+test_expr expr-3.30 {t1=NULL, t2='abc'} {t1||t2} {{}}
+test_expr expr-3.31 {t1='xyz', t2=NULL} {t1||t2} {{}}
+test_expr expr-3.32 {t1='xyz', t2='abc'} {t1||' hi '||t2} {{xyz hi abc}}
+test_expr epxr-3.33 {t1='abc', t2=NULL} {coalesce(t1<t2,99)} 99
+test_expr epxr-3.34 {t1='abc', t2=NULL} {coalesce(t2<t1,99)} 99
+test_expr epxr-3.35 {t1='abc', t2=NULL} {coalesce(t1>t2,99)} 99
+test_expr epxr-3.36 {t1='abc', t2=NULL} {coalesce(t2>t1,99)} 99
+test_expr epxr-3.37 {t1='abc', t2=NULL} {coalesce(t1<=t2,99)} 99
+test_expr epxr-3.38 {t1='abc', t2=NULL} {coalesce(t2<=t1,99)} 99
+test_expr epxr-3.39 {t1='abc', t2=NULL} {coalesce(t1>=t2,99)} 99
+test_expr epxr-3.40 {t1='abc', t2=NULL} {coalesce(t2>=t1,99)} 99
+test_expr epxr-3.41 {t1='abc', t2=NULL} {coalesce(t1==t2,99)} 99
+test_expr epxr-3.42 {t1='abc', t2=NULL} {coalesce(t2==t1,99)} 99
+test_expr epxr-3.43 {t1='abc', t2=NULL} {coalesce(t1!=t2,99)} 99
+test_expr epxr-3.44 {t1='abc', t2=NULL} {coalesce(t2!=t1,99)} 99
+
+
+test_expr expr-4.1 {t1='abc', t2='Abc'} {t1<t2} 0
+test_expr expr-4.2 {t1='abc', t2='Abc'} {t1>t2} 1
+test_expr expr-4.3 {t1='abc', t2='Bbc'} {t1<t2} 0
+test_expr expr-4.4 {t1='abc', t2='Bbc'} {t1>t2} 1
+test_expr expr-4.5 {t1='0', t2='0.0'} {t1==t2} 0
+test_expr expr-4.6 {t1='0.000', t2='0.0'} {t1==t2} 0
+test_expr expr-4.7 {t1=' 0.000', t2=' 0.0'} {t1==t2} 0
+test_expr expr-4.8 {t1='0.0', t2='abc'} {t1<t2} 1
+test_expr expr-4.9 {t1='0.0', t2='abc'} {t1==t2} 0
+test_expr expr-4.10 {r1='0.0', r2='abc'} {r1>r2} 0
+test_expr expr-4.11 {r1='abc', r2='Abc'} {r1<r2} 0
+test_expr expr-4.12 {r1='abc', r2='Abc'} {r1>r2} 1
+test_expr expr-4.13 {r1='abc', r2='Bbc'} {r1<r2} 0
+test_expr expr-4.14 {r1='abc', r2='Bbc'} {r1>r2} 1
+test_expr expr-4.15 {r1='0', r2='0.0'} {r1==r2} 1
+test_expr expr-4.16 {r1='0.000', r2='0.0'} {r1==r2} 1
+test_expr expr-4.17 {r1=' 0.000', r2=' 0.0'} {r1==r2} 0
+test_expr expr-4.18 {r1='0.0', r2='abc'} {r1<r2} 1
+test_expr expr-4.19 {r1='0.0', r2='abc'} {r1==r2} 0
+test_expr expr-4.20 {r1='0.0', r2='abc'} {r1>r2} 0
+
+test_expr expr-5.1 {t1='abc', t2='xyz'} {t1 LIKE t2} 0
+test_expr expr-5.2 {t1='abc', t2='ABC'} {t1 LIKE t2} 1
+test_expr expr-5.3 {t1='abc', t2='A_C'} {t1 LIKE t2} 1
+test_expr expr-5.4 {t1='abc', t2='abc_'} {t1 LIKE t2} 0
+test_expr expr-5.5 {t1='abc', t2='A%C'} {t1 LIKE t2} 1
+test_expr expr-5.5b {t1='ac', t2='A%C'} {t1 LIKE t2} 1
+test_expr expr-5.6 {t1='abxyzzyc', t2='A%C'} {t1 LIKE t2} 1
+test_expr expr-5.7 {t1='abxyzzy', t2='A%C'} {t1 LIKE t2} 0
+test_expr expr-5.8 {t1='abxyzzycx', t2='A%C'} {t1 LIKE t2} 0
+test_expr expr-5.8b {t1='abxyzzycy', t2='A%CX'} {t1 LIKE t2} 0
+test_expr expr-5.9 {t1='abc', t2='A%_C'} {t1 LIKE t2} 1
+test_expr expr-5.9b {t1='ac', t2='A%_C'} {t1 LIKE t2} 0
+test_expr expr-5.10 {t1='abxyzzyc', t2='A%_C'} {t1 LIKE t2} 1
+test_expr expr-5.11 {t1='abc', t2='xyz'} {t1 NOT LIKE t2} 1
+test_expr expr-5.12 {t1='abc', t2='ABC'} {t1 NOT LIKE t2} 0
+
+# The following tests only work on versions of TCL that support
+# Unicode and SQLite configured for UTF-8 support.
+#
+if {"\u1234"!="u1234" && [sqlite -encoding]=="UTF-8"} {
+ test_expr expr-5.13 "t1='a\u0080c', t2='A_C'" {t1 LIKE t2} 1
+ test_expr expr-5.14 "t1='a\u07FFc', t2='A_C'" {t1 LIKE t2} 1
+ test_expr expr-5.15 "t1='a\u0800c', t2='A_C'" {t1 LIKE t2} 1
+ test_expr expr-5.16 "t1='a\uFFFFc', t2='A_C'" {t1 LIKE t2} 1
+ test_expr expr-5.17 "t1='a\u0080', t2='A__'" {t1 LIKE t2} 0
+ test_expr expr-5.18 "t1='a\u07FF', t2='A__'" {t1 LIKE t2} 0
+ test_expr expr-5.19 "t1='a\u0800', t2='A__'" {t1 LIKE t2} 0
+ test_expr expr-5.20 "t1='a\uFFFF', t2='A__'" {t1 LIKE t2} 0
+ test_expr expr-5.21 "t1='ax\uABCD', t2='A_\uABCD'" {t1 LIKE t2} 1
+ test_expr expr-5.22 "t1='ax\u1234', t2='A%\u1234'" {t1 LIKE t2} 1
+ test_expr expr-5.23 "t1='ax\uFEDC', t2='A_%'" {t1 LIKE t2} 1
+ test_expr expr-5.24 "t1='ax\uFEDCy\uFEDC', t2='A%\uFEDC'" {t1 LIKE t2} 1
+}
+
+# Theses tests are for when SQLite assumes iso8859 characters.
+#
+if {[sqlite -encoding]=="iso8859"} {
+ set go 1
+ if {[info command encoding]!=""} {
+ if {[catch {encoding system iso8859-1} msg]} {
+ puts "skipping tests of LIKE operator: $msg"
+ set go 0
+ }
+ }
+ if {$go} {
+ test_expr expr-5.50 "t1='a\266c', t2='A_C'" {t1 LIKE t2} 1
+ test_expr expr-5.51 "t1='a\347', t2='A_'" {t1 LIKE t2} 1
+ test_expr expr-5.52 "t1='ax\351', t2='A_\351'" {t1 LIKE t2} 1
+ test_expr expr-5.53 "t1='ax\241', t2='A_%'" {t1 LIKE t2} 1
+ }
+}
+test_expr expr-5.54 {t1='abc', t2=NULL} {t1 LIKE t2} {{}}
+test_expr expr-5.55 {t1='abc', t2=NULL} {t1 NOT LIKE t2} {{}}
+test_expr expr-5.56 {t1='abc', t2=NULL} {t2 LIKE t1} {{}}
+test_expr expr-5.57 {t1='abc', t2=NULL} {t2 NOT LIKE t1} {{}}
+
+
+test_expr expr-6.1 {t1='abc', t2='xyz'} {t1 GLOB t2} 0
+test_expr expr-6.2 {t1='abc', t2='ABC'} {t1 GLOB t2} 0
+test_expr expr-6.3 {t1='abc', t2='A?C'} {t1 GLOB t2} 0
+test_expr expr-6.4 {t1='abc', t2='a?c'} {t1 GLOB t2} 1
+test_expr expr-6.5 {t1='abc', t2='abc?'} {t1 GLOB t2} 0
+test_expr expr-6.6 {t1='abc', t2='A*C'} {t1 GLOB t2} 0
+test_expr expr-6.7 {t1='abc', t2='a*c'} {t1 GLOB t2} 1
+test_expr expr-6.8 {t1='abxyzzyc', t2='a*c'} {t1 GLOB t2} 1
+test_expr expr-6.9 {t1='abxyzzy', t2='a*c'} {t1 GLOB t2} 0
+test_expr expr-6.10 {t1='abxyzzycx', t2='a*c'} {t1 GLOB t2} 0
+test_expr expr-6.11 {t1='abc', t2='xyz'} {t1 NOT GLOB t2} 1
+test_expr expr-6.12 {t1='abc', t2='abc'} {t1 NOT GLOB t2} 0
+test_expr expr-6.13 {t1='abc', t2='a[bx]c'} {t1 GLOB t2} 1
+test_expr expr-6.14 {t1='abc', t2='a[cx]c'} {t1 GLOB t2} 0
+test_expr expr-6.15 {t1='abc', t2='a[a-d]c'} {t1 GLOB t2} 1
+test_expr expr-6.16 {t1='abc', t2='a[^a-d]c'} {t1 GLOB t2} 0
+test_expr expr-6.17 {t1='abc', t2='a[A-Dc]c'} {t1 GLOB t2} 0
+test_expr expr-6.18 {t1='abc', t2='a[^A-Dc]c'} {t1 GLOB t2} 1
+test_expr expr-6.19 {t1='abc', t2='a[]b]c'} {t1 GLOB t2} 1
+test_expr expr-6.20 {t1='abc', t2='a[^]b]c'} {t1 GLOB t2} 0
+test_expr expr-6.21a {t1='abcdefg', t2='a*[de]g'} {t1 GLOB t2} 0
+test_expr expr-6.21b {t1='abcdefg', t2='a*[df]g'} {t1 GLOB t2} 1
+test_expr expr-6.21c {t1='abcdefg', t2='a*[d-h]g'} {t1 GLOB t2} 1
+test_expr expr-6.21d {t1='abcdefg', t2='a*[b-e]g'} {t1 GLOB t2} 0
+test_expr expr-6.22a {t1='abcdefg', t2='a*[^de]g'} {t1 GLOB t2} 1
+test_expr expr-6.22b {t1='abcdefg', t2='a*[^def]g'} {t1 GLOB t2} 0
+test_expr expr-6.23 {t1='abcdefg', t2='a*?g'} {t1 GLOB t2} 1
+test_expr expr-6.24 {t1='ac', t2='a*c'} {t1 GLOB t2} 1
+test_expr expr-6.25 {t1='ac', t2='a*?c'} {t1 GLOB t2} 0
+
+
+# These tests only work on versions of TCL that support Unicode
+#
+if {"\u1234"!="u1234" && [sqlite -encoding]=="UTF-8"} {
+ test_expr expr-6.26 "t1='a\u0080c', t2='a?c'" {t1 GLOB t2} 1
+ test_expr expr-6.27 "t1='a\u07ffc', t2='a?c'" {t1 GLOB t2} 1
+ test_expr expr-6.28 "t1='a\u0800c', t2='a?c'" {t1 GLOB t2} 1
+ test_expr expr-6.29 "t1='a\uffffc', t2='a?c'" {t1 GLOB t2} 1
+ test_expr expr-6.30 "t1='a\u1234', t2='a?'" {t1 GLOB t2} 1
+ test_expr expr-6.31 "t1='a\u1234', t2='a??'" {t1 GLOB t2} 0
+ test_expr expr-6.32 "t1='ax\u1234', t2='a?\u1234'" {t1 GLOB t2} 1
+ test_expr expr-6.33 "t1='ax\u1234', t2='a*\u1234'" {t1 GLOB t2} 1
+ test_expr expr-6.34 "t1='ax\u1234y\u1234', t2='a*\u1234'" {t1 GLOB t2} 1
+ test_expr expr-6.35 "t1='a\u1234b', t2='a\[x\u1234y\]b'" {t1 GLOB t2} 1
+ test_expr expr-6.36 "t1='a\u1234b', t2='a\[\u1233-\u1235\]b'" {t1 GLOB t2} 1
+ test_expr expr-6.37 "t1='a\u1234b', t2='a\[\u1234-\u124f\]b'" {t1 GLOB t2} 1
+ test_expr expr-6.38 "t1='a\u1234b', t2='a\[\u1235-\u124f\]b'" {t1 GLOB t2} 0
+ test_expr expr-6.39 "t1='a\u1234b', t2='a\[a-\u1235\]b'" {t1 GLOB t2} 1
+ test_expr expr-6.40 "t1='a\u1234b', t2='a\[a-\u1234\]b'" {t1 GLOB t2} 1
+ test_expr expr-6.41 "t1='a\u1234b', t2='a\[a-\u1233\]b'" {t1 GLOB t2} 0
+}
+
+test_expr expr-6.51 {t1='ABC', t2='xyz'} {t1 GLOB t2} 0
+test_expr expr-6.52 {t1='ABC', t2='abc'} {t1 GLOB t2} 0
+test_expr expr-6.53 {t1='ABC', t2='a?c'} {t1 GLOB t2} 0
+test_expr expr-6.54 {t1='ABC', t2='A?C'} {t1 GLOB t2} 1
+test_expr expr-6.55 {t1='ABC', t2='abc?'} {t1 GLOB t2} 0
+test_expr expr-6.56 {t1='ABC', t2='a*c'} {t1 GLOB t2} 0
+test_expr expr-6.57 {t1='ABC', t2='A*C'} {t1 GLOB t2} 1
+test_expr expr-6.58 {t1='ABxyzzyC', t2='A*C'} {t1 GLOB t2} 1
+test_expr expr-6.59 {t1='ABxyzzy', t2='A*C'} {t1 GLOB t2} 0
+test_expr expr-6.60 {t1='ABxyzzyCx', t2='A*C'} {t1 GLOB t2} 0
+test_expr expr-6.61 {t1='ABC', t2='xyz'} {t1 NOT GLOB t2} 1
+test_expr expr-6.62 {t1='ABC', t2='ABC'} {t1 NOT GLOB t2} 0
+test_expr expr-6.63 {t1='ABC', t2='A[Bx]C'} {t1 GLOB t2} 1
+test_expr expr-6.64 {t1='ABC', t2='A[Cx]C'} {t1 GLOB t2} 0
+test_expr expr-6.65 {t1='ABC', t2='A[A-D]C'} {t1 GLOB t2} 1
+test_expr expr-6.66 {t1='ABC', t2='A[^A-D]C'} {t1 GLOB t2} 0
+test_expr expr-6.67 {t1='ABC', t2='A[a-dC]C'} {t1 GLOB t2} 0
+test_expr expr-6.68 {t1='ABC', t2='A[^a-dC]C'} {t1 GLOB t2} 1
+test_expr expr-6.69a {t1='ABC', t2='A[]B]C'} {t1 GLOB t2} 1
+test_expr expr-6.69b {t1='A]C', t2='A[]B]C'} {t1 GLOB t2} 1
+test_expr expr-6.70a {t1='ABC', t2='A[^]B]C'} {t1 GLOB t2} 0
+test_expr expr-6.70b {t1='AxC', t2='A[^]B]C'} {t1 GLOB t2} 1
+test_expr expr-6.70c {t1='A]C', t2='A[^]B]C'} {t1 GLOB t2} 0
+test_expr expr-6.71 {t1='ABCDEFG', t2='A*[DE]G'} {t1 GLOB t2} 0
+test_expr expr-6.72 {t1='ABCDEFG', t2='A*[^DE]G'} {t1 GLOB t2} 1
+test_expr expr-6.73 {t1='ABCDEFG', t2='A*?G'} {t1 GLOB t2} 1
+test_expr expr-6.74 {t1='AC', t2='A*C'} {t1 GLOB t2} 1
+test_expr expr-6.75 {t1='AC', t2='A*?C'} {t1 GLOB t2} 0
+
+# Theses tests are for when SQLite assumes iso8859 characters.
+#
+if {[sqlite -encoding]=="iso8859"} {
+ set go 1
+ if {[info command encoding]!=""} {
+ if {[catch {encoding system iso8859-1} msg]} {
+ puts "skipping tests of GLOB operator: $msg"
+ set go 0
+ }
+ }
+ if {$go} {
+ test_expr expr-6.50 "t1='a\266c', t2='a?c'" {t1 GLOB t2} 1
+ test_expr expr-6.51 "t1='a\266', t2='a?'" {t1 GLOB t2} 1
+ test_expr expr-6.52 "t1='a\266', t2='a??'" {t1 GLOB t2} 0
+ test_expr expr-6.53 "t1='ax\266', t2='a??'" {t1 GLOB t2} 1
+ test_expr expr-6.54 "t1='ax\266', t2='a?\266'" {t1 GLOB t2} 1
+ test_expr expr-6.55 "t1='ax\266y\266', t2='a*\266'" {t1 GLOB t2} 1
+ test_expr expr-6.56 "t1='a\266b', t2='a\[x\266y\]b'" {t1 GLOB t2} 1
+ test_expr expr-6.57 "t1='a\266b', t2='a\[\260-\270\]b'" {t1 GLOB t2} 1
+ test_expr expr-6.58 "t1='a\266b', t2='a\[\266-\270\]b'" {t1 GLOB t2} 1
+ test_expr expr-6.59 "t1='a\266b', t2='a\[\267-\270\]b'" {t1 GLOB t2} 0
+ test_expr expr-6.60 "t1='a\266b', t2='a\[x-\267\]b'" {t1 GLOB t2} 1
+ test_expr expr-6.61 "t1='a\266b', t2='a\[x-\266\]b'" {t1 GLOB t2} 1
+ test_expr expr-6.62 "t1='a\266b', t2='a\[x-\265\]b'" {t1 GLOB t2} 0
+ }
+}
+test_expr expr-6.63 {t1=NULL, t2='a*?c'} {t1 GLOB t2} {{}}
+test_expr expr-6.64 {t1='ac', t2=NULL} {t1 GLOB t2} {{}}
+test_expr expr-6.65 {t1=NULL, t2='a*?c'} {t1 NOT GLOB t2} {{}}
+test_expr expr-6.66 {t1='ac', t2=NULL} {t1 NOT GLOB t2} {{}}
+
+test_expr expr-case.1 {i1=1, i2=2} \
+ {CASE WHEN i1 = i2 THEN 'eq' ELSE 'ne' END} ne
+test_expr expr-case.2 {i1=2, i2=2} \
+ {CASE WHEN i1 = i2 THEN 'eq' ELSE 'ne' END} eq
+test_expr expr-case.3 {i1=NULL, i2=2} \
+ {CASE WHEN i1 = i2 THEN 'eq' ELSE 'ne' END} ne
+test_expr expr-case.4 {i1=2, i2=NULL} \
+ {CASE WHEN i1 = i2 THEN 'eq' ELSE 'ne' END} ne
+test_expr expr-case.5 {i1=2} \
+ {CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'error' END} two
+test_expr expr-case.6 {i1=1} \
+ {CASE i1 WHEN 1 THEN 'one' WHEN NULL THEN 'two' ELSE 'error' END} one
+test_expr expr-case.7 {i1=2} \
+ {CASE i1 WHEN 1 THEN 'one' WHEN NULL THEN 'two' ELSE 'error' END} error
+test_expr expr-case.8 {i1=3} \
+ {CASE i1 WHEN 1 THEN 'one' WHEN NULL THEN 'two' ELSE 'error' END} error
+test_expr expr-case.9 {i1=3} \
+ {CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'error' END} error
+test_expr expr-case.10 {i1=3} \
+ {CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' END} {{}}
+test_expr expr-case.11 {i1=null} \
+ {CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 3 END} 3
+test_expr expr-case.12 {i1=1} \
+ {CASE i1 WHEN 1 THEN null WHEN 2 THEN 'two' ELSE 3 END} {{}}
+test_expr expr-case.13 {i1=7} \
+ { CASE WHEN i1 < 5 THEN 'low'
+ WHEN i1 < 10 THEN 'medium'
+ WHEN i1 < 15 THEN 'high' ELSE 'error' END} medium
+
+
+# The sqliteExprIfFalse and sqliteExprIfTrue routines are only
+# executed as part of a WHERE clause. Create a table suitable
+# for testing these functions.
+#
+execsql {DROP TABLE test1}
+execsql {CREATE TABLE test1(a int, b int);}
+for {set i 1} {$i<=20} {incr i} {
+ execsql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
+}
+execsql "INSERT INTO test1 VALUES(NULL,0)"
+do_test expr-7.1 {
+ execsql {SELECT * FROM test1 ORDER BY a}
+} {{} 0 1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024 11 2048 12 4096 13 8192 14 16384 15 32768 16 65536 17 131072 18 262144 19 524288 20 1048576}
+
+proc test_expr2 {name expr result} {
+ do_test $name [format {
+ execsql {SELECT a FROM test1 WHERE %s ORDER BY a}
+ } $expr] $result
+}
+
+test_expr2 expr-7.2 {a<10 AND a>8} {9}
+test_expr2 expr-7.3 {a<=10 AND a>=8} {8 9 10}
+test_expr2 expr-7.4 {a>=8 AND a<=10} {8 9 10}
+test_expr2 expr-7.5 {a>=20 OR a<=1} {1 20}
+test_expr2 expr-7.6 {b!=4 AND a<=3} {1 3}
+test_expr2 expr-7.7 {b==8 OR b==16 OR b==32} {3 4 5}
+test_expr2 expr-7.8 {NOT b<>8 OR b==1024} {3 10}
+test_expr2 expr-7.9 {b LIKE '10%'} {10 20}
+test_expr2 expr-7.10 {b LIKE '_4'} {6}
+test_expr2 expr-7.11 {a GLOB '1?'} {10 11 12 13 14 15 16 17 18 19}
+test_expr2 expr-7.12 {b GLOB '1*4'} {10 14}
+test_expr2 expr-7.13 {b GLOB '*1[456]'} {4}
+test_expr2 expr-7.14 {a ISNULL} {{}}
+test_expr2 expr-7.15 {a NOTNULL AND a<3} {1 2}
+test_expr2 expr-7.16 {a AND a<3} {1 2}
+test_expr2 expr-7.17 {NOT a} {}
+test_expr2 expr-7.18 {a==11 OR (b>1000 AND b<2000)} {10 11}
+test_expr2 expr-7.19 {a<=1 OR a>=20} {1 20}
+test_expr2 expr-7.20 {a<1 OR a>20} {}
+test_expr2 expr-7.21 {a>19 OR a<1} {20}
+test_expr2 expr-7.22 {a!=1 OR a=100} \
+ {2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
+test_expr2 expr-7.23 {(a notnull AND a<4) OR a==8} {1 2 3 8}
+test_expr2 expr-7.24 {a LIKE '2_' OR a==8} {8 20}
+test_expr2 expr-7.25 {a GLOB '2?' OR a==8} {8 20}
+test_expr2 expr-7.26 {a isnull OR a=8} {{} 8}
+test_expr2 expr-7.27 {a notnull OR a=8} \
+ {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
+test_expr2 expr-7.28 {a<0 OR b=0} {{}}
+test_expr2 expr-7.29 {b=0 OR a<0} {{}}
+test_expr2 expr-7.30 {a<0 AND b=0} {}
+test_expr2 expr-7.31 {b=0 AND a<0} {}
+test_expr2 expr-7.32 {a IS NULL AND (a<0 OR b=0)} {{}}
+test_expr2 expr-7.33 {a IS NULL AND (b=0 OR a<0)} {{}}
+test_expr2 expr-7.34 {a IS NULL AND (a<0 AND b=0)} {}
+test_expr2 expr-7.35 {a IS NULL AND (b=0 AND a<0)} {}
+test_expr2 expr-7.32 {(a<0 OR b=0) AND a IS NULL} {{}}
+test_expr2 expr-7.33 {(b=0 OR a<0) AND a IS NULL} {{}}
+test_expr2 expr-7.34 {(a<0 AND b=0) AND a IS NULL} {}
+test_expr2 expr-7.35 {(b=0 AND a<0) AND a IS NULL} {}
+test_expr2 expr-7.36 {a<2 OR (a<0 OR b=0)} {{} 1}
+test_expr2 expr-7.37 {a<2 OR (b=0 OR a<0)} {{} 1}
+test_expr2 expr-7.38 {a<2 OR (a<0 AND b=0)} {1}
+test_expr2 expr-7.39 {a<2 OR (b=0 AND a<0)} {1}
+test_expr2 expr-7.40 {((a<2 OR a IS NULL) AND b<3) OR b>1e10} {{} 1}
+test_expr2 expr-7.41 {a BETWEEN -1 AND 1} {1}
+test_expr2 expr-7.42 {a NOT BETWEEN 2 AND 100} {1}
+test_expr2 expr-7.43 {(b+1234)||'this is a string that is at least 32 characters long' BETWEEN 1 AND 2} {}
+test_expr2 expr-7.44 {123||'xabcdefghijklmnopqrstuvwyxz01234567890'||a BETWEEN '123a' AND '123b'} {}
+test_expr2 expr-7.45 {((123||'xabcdefghijklmnopqrstuvwyxz01234567890'||a) BETWEEN '123a' AND '123b')<0} {}
+test_expr2 expr-7.46 {((123||'xabcdefghijklmnopqrstuvwyxz01234567890'||a) BETWEEN '123a' AND '123z')>0} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
+
+test_expr2 expr-7.50 {((a between 1 and 2 OR 0) AND 1) OR 0} {1 2}
+test_expr2 expr-7.51 {((a not between 3 and 100 OR 0) AND 1) OR 0} {1 2}
+test_expr2 expr-7.52 {((a in (1,2) OR 0) AND 1) OR 0} {1 2}
+test_expr2 expr-7.53 {((a not in (3,4,5,6,7,8,9,10) OR 0) AND a<11) OR 0} {1 2}
+test_expr2 expr-7.54 {((a>0 OR 0) AND a<3) OR 0} {1 2}
+test_expr2 expr-7.55 {((a in (1,2) OR 0) IS NULL AND 1) OR 0} {{}}
+test_expr2 expr-7.56 {((a not in (3,4,5,6,7,8,9,10) IS NULL OR 0) AND 1) OR 0} \
+ {{}}
+test_expr2 expr-7.57 {((a>0 IS NULL OR 0) AND 1) OR 0} {{}}
+
+test_expr2 expr-7.58 {(a||'')<='1'} {1}
+
+test_expr2 expr-7.59 {LIKE('10%',b)} {10 20}
+test_expr2 expr-7.60 {LIKE('_4',b)} {6}
+test_expr2 expr-7.61 {GLOB('1?',a)} {10 11 12 13 14 15 16 17 18 19}
+test_expr2 expr-7.62 {GLOB('1*4',b)} {10 14}
+test_expr2 expr-7.63 {GLOB('*1[456]',b)} {4}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/fkey1.test b/usr/src/lib/libsqlite/test/fkey1.test
new file mode 100644
index 0000000000..4e0b4d6400
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/fkey1.test
@@ -0,0 +1,56 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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.
+#
+# This file implements tests for foreign keys.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a table and some data to work with.
+#
+do_test fkey1-1.0 {
+ execsql {
+ CREATE TABLE t1(
+ a INTEGER PRIMARY KEY,
+ b INTEGER
+ REFERENCES t1 ON DELETE CASCADE
+ REFERENCES t2,
+ c TEXT,
+ FOREIGN KEY (b,c) REFERENCES t2(x,y) ON UPDATE CASCADE
+ );
+ }
+} {}
+do_test fkey1-1.1 {
+ execsql {
+ CREATE TABLE t2(
+ x INTEGER PRIMARY KEY,
+ y TEXT
+ );
+ }
+} {}
+do_test fkey1-1.2 {
+ execsql {
+ CREATE TABLE t3(
+ a INTEGER REFERENCES t2,
+ b INTEGER REFERENCES t1,
+ FOREIGN KEY (a,b) REFERENCES t2(x,y)
+ );
+ }
+} {}
+
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/format3.test b/usr/src/lib/libsqlite/test/format3.test
new file mode 100644
index 0000000000..bcad7d957e
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/format3.test
@@ -0,0 +1,741 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 the library is able to correctly
+# handle file-format 3 (version 2.6.x) databases.
+#
+# $Id: format3.test,v 1.4 2003/12/23 02:17:35 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a bunch of data to sort against
+#
+do_test format3-1.0 {
+ set fd [open data.txt w]
+ puts $fd "1\tone\t0\tI\t3.141592653"
+ puts $fd "2\ttwo\t1\tII\t2.15"
+ puts $fd "3\tthree\t1\tIII\t4221.0"
+ puts $fd "4\tfour\t2\tIV\t-0.0013442"
+ puts $fd "5\tfive\t2\tV\t-11"
+ puts $fd "6\tsix\t2\tVI\t0.123"
+ puts $fd "7\tseven\t2\tVII\t123.0"
+ puts $fd "8\teight\t3\tVIII\t-1.6"
+ close $fd
+ execsql {
+ CREATE TABLE t1(
+ n int,
+ v varchar(10),
+ log int,
+ roman varchar(10),
+ flt real
+ );
+ COPY t1 FROM 'data.txt'
+ }
+ file delete data.txt
+ db close
+ set ::bt [btree_open test.db]
+ btree_begin_transaction $::bt
+ set m [btree_get_meta $::bt]
+ set m [lreplace $m 2 2 3]
+ eval btree_update_meta $::bt $m
+ btree_commit $::bt
+ btree_close $::bt
+ sqlite db test.db
+ execsql {SELECT count(*) FROM t1}
+} {8}
+
+do_test format3-1.1 {
+ execsql {SELECT n FROM t1 ORDER BY n}
+} {1 2 3 4 5 6 7 8}
+do_test format3-1.1.1 {
+ execsql {SELECT n FROM t1 ORDER BY n ASC}
+} {1 2 3 4 5 6 7 8}
+do_test format3-1.1.1 {
+ execsql {SELECT ALL n FROM t1 ORDER BY n ASC}
+} {1 2 3 4 5 6 7 8}
+do_test format3-1.2 {
+ execsql {SELECT n FROM t1 ORDER BY n DESC}
+} {8 7 6 5 4 3 2 1}
+do_test format3-1.3a {
+ execsql {SELECT v FROM t1 ORDER BY v}
+} {eight five four one seven six three two}
+do_test format3-1.3b {
+ execsql {SELECT n FROM t1 ORDER BY v}
+} {8 5 4 1 7 6 3 2}
+do_test format3-1.4 {
+ execsql {SELECT n FROM t1 ORDER BY v DESC}
+} {2 3 6 7 1 4 5 8}
+do_test format3-1.5 {
+ execsql {SELECT flt FROM t1 ORDER BY flt}
+} {-11 -1.6 -0.0013442 0.123 2.15 3.141592653 123.0 4221.0}
+do_test format3-1.6 {
+ execsql {SELECT flt FROM t1 ORDER BY flt DESC}
+} {4221.0 123.0 3.141592653 2.15 0.123 -0.0013442 -1.6 -11}
+do_test format3-1.7 {
+ execsql {SELECT roman FROM t1 ORDER BY roman}
+} {I II III IV V VI VII VIII}
+do_test format3-1.8 {
+ execsql {SELECT n FROM t1 ORDER BY log, flt}
+} {1 2 3 5 4 6 7 8}
+do_test format3-1.8.1 {
+ execsql {SELECT n FROM t1 ORDER BY log asc, flt}
+} {1 2 3 5 4 6 7 8}
+do_test format3-1.8.2 {
+ execsql {SELECT n FROM t1 ORDER BY log, flt ASC}
+} {1 2 3 5 4 6 7 8}
+do_test format3-1.8.3 {
+ execsql {SELECT n FROM t1 ORDER BY log ASC, flt asc}
+} {1 2 3 5 4 6 7 8}
+do_test format3-1.9 {
+ execsql {SELECT n FROM t1 ORDER BY log, flt DESC}
+} {1 3 2 7 6 4 5 8}
+do_test format3-1.9.1 {
+ execsql {SELECT n FROM t1 ORDER BY log ASC, flt DESC}
+} {1 3 2 7 6 4 5 8}
+do_test format3-1.10 {
+ execsql {SELECT n FROM t1 ORDER BY log DESC, flt}
+} {8 5 4 6 7 2 3 1}
+do_test format3-1.11 {
+ execsql {SELECT n FROM t1 ORDER BY log DESC, flt DESC}
+} {8 7 6 4 5 3 2 1}
+
+# These tests are designed to reach some hard-to-reach places
+# inside the string comparison routines.
+#
+# (Later) The sorting behavior changed in 2.7.0. But we will
+# keep these tests. You can never have too many test cases!
+#
+do_test format3-2.1.1 {
+ execsql {
+ UPDATE t1 SET v='x' || -flt;
+ UPDATE t1 SET v='x-2b' where v=='x-0.123';
+ SELECT v FROM t1 ORDER BY v;
+ }
+} {x-123 x-2.15 x-2b x-3.141592653 x-4221 x0.0013442 x1.6 x11}
+do_test format3-2.1.2 {
+ execsql {
+ SELECT v FROM t1 ORDER BY substr(v,2,999);
+ }
+} {x-4221 x-123 x-3.141592653 x-2.15 x0.0013442 x1.6 x11 x-2b}
+do_test format3-2.1.3 {
+ execsql {
+ SELECT v FROM t1 ORDER BY substr(v,2,999)+0.0;
+ }
+} {x-4221 x-123 x-3.141592653 x-2.15 x-2b x0.0013442 x1.6 x11}
+do_test format3-2.1.4 {
+ execsql {
+ SELECT v FROM t1 ORDER BY substr(v,2,999) DESC;
+ }
+} {x-2b x11 x1.6 x0.0013442 x-2.15 x-3.141592653 x-123 x-4221}
+do_test format3-2.1.5 {
+ execsql {
+ SELECT v FROM t1 ORDER BY substr(v,2,999)+0.0 DESC;
+ }
+} {x11 x1.6 x0.0013442 x-2b x-2.15 x-3.141592653 x-123 x-4221}
+
+# This is a bug fix for 2.2.4.
+# Strings are normally mapped to upper-case for a caseless comparison.
+# But this can cause problems for characters in between 'Z' and 'a'.
+#
+do_test format3-3.1 {
+ execsql {
+ CREATE TABLE t2(a,b);
+ INSERT INTO t2 VALUES('AGLIENTU',1);
+ INSERT INTO t2 VALUES('AGLIE`',2);
+ INSERT INTO t2 VALUES('AGNA',3);
+ SELECT a, b FROM t2 ORDER BY a;
+ }
+} {AGLIENTU 1 AGLIE` 2 AGNA 3}
+do_test format3-3.2 {
+ execsql {
+ SELECT a, b FROM t2 ORDER BY a DESC;
+ }
+} {AGNA 3 AGLIE` 2 AGLIENTU 1}
+do_test format3-3.3 {
+ execsql {
+ DELETE FROM t2;
+ INSERT INTO t2 VALUES('aglientu',1);
+ INSERT INTO t2 VALUES('aglie`',2);
+ INSERT INTO t2 VALUES('agna',3);
+ SELECT a, b FROM t2 ORDER BY a;
+ }
+} {aglie` 2 aglientu 1 agna 3}
+do_test format3-3.4 {
+ execsql {
+ SELECT a, b FROM t2 ORDER BY a DESC;
+ }
+} {agna 3 aglientu 1 aglie` 2}
+
+# Version 2.7.0 testing.
+#
+do_test format3-4.1 {
+ execsql {
+ INSERT INTO t1 VALUES(9,'x2.7',3,'IX',4.0e5);
+ INSERT INTO t1 VALUES(10,'x5.0e10',3,'X',-4.0e5);
+ INSERT INTO t1 VALUES(11,'x-4.0e9',3,'XI',4.1e4);
+ INSERT INTO t1 VALUES(12,'x01234567890123456789',3,'XII',-4.2e3);
+ SELECT n FROM t1 ORDER BY n;
+ }
+} {1 2 3 4 5 6 7 8 9 10 11 12}
+do_test format3-4.2 {
+ execsql {
+ SELECT n||'' FROM t1 ORDER BY 1;
+ }
+} {1 2 3 4 5 6 7 8 9 10 11 12}
+do_test format3-4.3 {
+ execsql {
+ SELECT n+0 FROM t1 ORDER BY 1;
+ }
+} {1 2 3 4 5 6 7 8 9 10 11 12}
+do_test format3-4.4 {
+ execsql {
+ SELECT n||'' FROM t1 ORDER BY 1 DESC;
+ }
+} {12 11 10 9 8 7 6 5 4 3 2 1}
+do_test format3-4.5 {
+ execsql {
+ SELECT n+0 FROM t1 ORDER BY 1 DESC;
+ }
+} {12 11 10 9 8 7 6 5 4 3 2 1}
+do_test format3-4.6 {
+ execsql {
+ SELECT v FROM t1 ORDER BY 1;
+ }
+} {x-123 x-2.15 x-2b x-3.141592653 x-4.0e9 x-4221 x0.0013442 x01234567890123456789 x1.6 x11 x2.7 x5.0e10}
+do_test format3-4.7 {
+ execsql {
+ SELECT v FROM t1 ORDER BY 1 DESC;
+ }
+} {x5.0e10 x2.7 x11 x1.6 x01234567890123456789 x0.0013442 x-4221 x-4.0e9 x-3.141592653 x-2b x-2.15 x-123}
+do_test format3-4.8 {
+ execsql {
+ SELECT substr(v,2,99) FROM t1 ORDER BY 1;
+ }
+} {-4.0e9 -4221 -123 -3.141592653 -2.15 0.0013442 1.6 2.7 11 5.0e10 01234567890123456789 -2b}
+
+# Build some new test data, this time with indices.
+#
+do_test format3-5.0 {
+ execsql {
+ DROP TABLE t1;
+ CREATE TABLE t1(w int, x text, y blob);
+ DROP TABLE t2;
+ CREATE TABLE t2(p varchar(1), q clob, r real, s numeric(8));
+ }
+ for {set i 1} {$i<=100} {incr i} {
+ set w $i
+ set x [expr {int(log($i)/log(2))}]
+ set y [expr {$i*$i + 2*$i + 1}]
+ execsql "INSERT INTO t1 VALUES($w,$x,$y)"
+ }
+ execsql {
+ INSERT INTO t2 SELECT 101-w, x, (SELECT max(y) FROM t1)+1-y, y FROM t1;
+ CREATE INDEX i1w ON t1(w);
+ CREATE INDEX i1xy ON t1(x,y);
+ CREATE INDEX i2p ON t2(p);
+ CREATE INDEX i2r ON t2(r);
+ CREATE INDEX i2qs ON t2(q, s);
+ }
+} {}
+
+# Do an SQL statement. Append the search count to the end of the result.
+#
+proc count sql {
+ set ::sqlite_search_count 0
+ return [concat [execsql $sql] $::sqlite_search_count]
+}
+
+# Verify that queries use an index. We are using the special variable
+# "sqlite_search_count" which tallys the number of executions of MoveTo
+# and Next operators in the VDBE. By verifing that the search count is
+# small we can be assured that indices are being used properly.
+#
+do_test format3-5.1 {
+ db close
+ sqlite db test.db
+ count {SELECT x, y FROM t1 WHERE w=10}
+} {3 121 3}
+do_test format3-5.2 {
+ count {SELECT x, y FROM t1 WHERE w=11}
+} {3 144 3}
+do_test format3-5.3 {
+ count {SELECT x, y FROM t1 WHERE 11=w}
+} {3 144 3}
+do_test format3-5.4 {
+ count {SELECT x, y FROM t1 WHERE 11=w AND x>2}
+} {3 144 3}
+do_test format3-5.5 {
+ count {SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2}
+} {3 144 3}
+do_test format3-5.6 {
+ count {SELECT x, y FROM t1 WHERE y<200 AND x>2 AND w=11}
+} {3 144 3}
+do_test format3-5.7 {
+ count {SELECT x, y FROM t1 WHERE w=11 AND y<200 AND x>2}
+} {3 144 3}
+do_test format3-5.8 {
+ count {SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3}
+} {3 144 3}
+do_test format3-5.9 {
+ count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3}
+} {3 144 3}
+do_test format3-5.10 {
+ count {SELECT x, y FROM t1 WHERE x=3 AND w>=10 AND y=121}
+} {3 121 3}
+do_test format3-5.11 {
+ count {SELECT x, y FROM t1 WHERE x=3 AND y=100 AND w<10}
+} {3 100 3}
+
+# New for SQLite version 2.1: Verify that that inequality constraints
+# are used correctly.
+#
+do_test format3-5.12 {
+ count {SELECT w FROM t1 WHERE x=3 AND y<100}
+} {8 3}
+do_test format3-5.13 {
+ count {SELECT w FROM t1 WHERE x=3 AND 100>y}
+} {8 3}
+do_test format3-5.14 {
+ count {SELECT w FROM t1 WHERE 3=x AND y<100}
+} {8 3}
+do_test format3-5.15 {
+ count {SELECT w FROM t1 WHERE 3=x AND 100>y}
+} {8 3}
+do_test format3-5.16 {
+ count {SELECT w FROM t1 WHERE x=3 AND y<=100}
+} {8 9 5}
+do_test format3-5.17 {
+ count {SELECT w FROM t1 WHERE x=3 AND 100>=y}
+} {8 9 5}
+do_test format3-5.18 {
+ count {SELECT w FROM t1 WHERE x=3 AND y>225}
+} {15 3}
+do_test format3-5.19 {
+ count {SELECT w FROM t1 WHERE x=3 AND 225<y}
+} {15 3}
+do_test format3-5.20 {
+ count {SELECT w FROM t1 WHERE x=3 AND y>=225}
+} {14 15 5}
+do_test format3-5.21 {
+ count {SELECT w FROM t1 WHERE x=3 AND 225<=y}
+} {14 15 5}
+do_test format3-5.22 {
+ count {SELECT w FROM t1 WHERE x=3 AND y>121 AND y<196}
+} {11 12 5}
+do_test format3-5.23 {
+ count {SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<=196}
+} {10 11 12 13 9}
+do_test format3-5.24 {
+ count {SELECT w FROM t1 WHERE x=3 AND 121<y AND 196>y}
+} {11 12 5}
+do_test format3-5.25 {
+ count {SELECT w FROM t1 WHERE x=3 AND 121<=y AND 196>=y}
+} {10 11 12 13 9}
+
+# Need to work on optimizing the BETWEEN operator.
+#
+# do_test format3-5.26 {
+# count {SELECT w FROM t1 WHERE x=3 AND y BETWEEN 121 AND 196}
+# } {10 11 12 13 9}
+
+do_test format3-5.27 {
+ count {SELECT w FROM t1 WHERE x=3 AND y+1==122}
+} {10 17}
+do_test format3-5.28 {
+ count {SELECT w FROM t1 WHERE x+1=4 AND y+1==122}
+} {10 99}
+do_test format3-5.29 {
+ count {SELECT w FROM t1 WHERE y==121}
+} {10 99}
+
+
+do_test format3-5.30 {
+ count {SELECT w FROM t1 WHERE w>97}
+} {98 99 100 6}
+do_test format3-5.31 {
+ count {SELECT w FROM t1 WHERE w>=97}
+} {97 98 99 100 8}
+do_test format3-5.33 {
+ count {SELECT w FROM t1 WHERE w==97}
+} {97 3}
+do_test format3-5.34 {
+ count {SELECT w FROM t1 WHERE w+1==98}
+} {97 99}
+do_test format3-5.35 {
+ count {SELECT w FROM t1 WHERE w<3}
+} {1 2 4}
+do_test format3-5.36 {
+ count {SELECT w FROM t1 WHERE w<=3}
+} {1 2 3 6}
+do_test format3-5.37 {
+ count {SELECT w FROM t1 WHERE w+1<=4 ORDER BY w}
+} {1 2 3 199}
+
+
+# Do the same kind of thing except use a join as the data source.
+#
+do_test format3-6.1 {
+ db close
+ sqlite db test.db
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE x=q AND y=s AND r=8977
+ }
+} {34 67 6}
+do_test format3-6.2 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE x=q AND s=y AND r=8977
+ }
+} {34 67 6}
+do_test format3-6.3 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE x=q AND s=y AND r=8977 AND w>10
+ }
+} {34 67 6}
+do_test format3-6.4 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE p<80 AND x=q AND s=y AND r=8977 AND w>10
+ }
+} {34 67 6}
+do_test format3-6.5 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE p<80 AND x=q AND 8977=r AND s=y AND w>10
+ }
+} {34 67 6}
+do_test format3-6.6 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE x=q AND p=77 AND s=y AND w>5
+ }
+} {24 77 6}
+do_test format3-6.7 {
+ count {
+ SELECT w, p FROM t1, t2
+ WHERE x=q AND p>77 AND s=y AND w=5
+ }
+} {5 96 6}
+
+# Lets do a 3-way join.
+#
+do_test format3-7.1 {
+ count {
+ SELECT A.w, B.p, C.w FROM t1 as A, t2 as B, t1 as C
+ WHERE C.w=101-B.p AND B.r=10202-A.y AND A.w=11
+ }
+} {11 90 11 9}
+do_test format3-7.2 {
+ count {
+ SELECT A.w, B.p, C.w FROM t1 as A, t2 as B, t1 as C
+ WHERE C.w=101-B.p AND B.r=10202-A.y AND A.w=12
+ }
+} {12 89 12 9}
+do_test format3-7.3 {
+ count {
+ SELECT A.w, B.p, C.w FROM t1 as A, t2 as B, t1 as C
+ WHERE A.w=15 AND B.p=C.w AND B.r=10202-A.y
+ }
+} {15 86 86 9}
+
+# Test to see that the special case of a constant WHERE clause is
+# handled.
+#
+do_test format3-8.1 {
+ count {
+ SELECT * FROM t1 WHERE 0
+ }
+} {0}
+do_test format3-8.2 {
+ count {
+ SELECT * FROM t1 WHERE 1 LIMIT 1
+ }
+} {1 0 4 1}
+do_test format3-8.3 {
+ execsql {
+ SELECT 99 WHERE 0
+ }
+} {}
+do_test format3-8.4 {
+ execsql {
+ SELECT 99 WHERE 1
+ }
+} {99}
+
+# Verify that IN operators in a WHERE clause are handled correctly.
+#
+do_test format3-9.1 {
+ count {
+ SELECT * FROM t1 WHERE rowid IN (1,2,3,1234) order by 1;
+ }
+} {1 0 4 2 1 9 3 1 16 0}
+do_test format3-9.2 {
+ count {
+ SELECT * FROM t1 WHERE rowid+0 IN (1,2,3,1234) order by 1;
+ }
+} {1 0 4 2 1 9 3 1 16 199}
+do_test format3-9.3 {
+ count {
+ SELECT * FROM t1 WHERE w IN (-1,1,2,3) order by 1;
+ }
+} {1 0 4 2 1 9 3 1 16 10}
+do_test format3-9.4 {
+ count {
+ SELECT * FROM t1 WHERE w+0 IN (-1,1,2,3) order by 1;
+ }
+} {1 0 4 2 1 9 3 1 16 199}
+do_test format3-9.5 {
+ count {
+ SELECT * FROM t1 WHERE rowid IN
+ (select rowid from t1 where rowid IN (-1,2,4))
+ ORDER BY 1;
+ }
+} {2 1 9 4 2 25 1}
+do_test format3-9.6 {
+ count {
+ SELECT * FROM t1 WHERE rowid+0 IN
+ (select rowid from t1 where rowid IN (-1,2,4))
+ ORDER BY 1;
+ }
+} {2 1 9 4 2 25 199}
+do_test format3-9.7 {
+ count {
+ SELECT * FROM t1 WHERE w IN
+ (select rowid from t1 where rowid IN (-1,2,4))
+ ORDER BY 1;
+ }
+} {2 1 9 4 2 25 7}
+do_test format3-9.8 {
+ count {
+ SELECT * FROM t1 WHERE w+0 IN
+ (select rowid from t1 where rowid IN (-1,2,4))
+ ORDER BY 1;
+ }
+} {2 1 9 4 2 25 199}
+do_test format3-9.9 {
+ count {
+ SELECT * FROM t1 WHERE x IN (1,7) ORDER BY 1;
+ }
+} {2 1 9 3 1 16 6}
+do_test format3-9.10 {
+ count {
+ SELECT * FROM t1 WHERE x+0 IN (1,7) ORDER BY 1;
+ }
+} {2 1 9 3 1 16 199}
+do_test format3-9.11 {
+ count {
+ SELECT * FROM t1 WHERE y IN (6400,8100) ORDER BY 1;
+ }
+} {79 6 6400 89 6 8100 199}
+do_test format3-9.12 {
+ count {
+ SELECT * FROM t1 WHERE x=6 AND y IN (6400,8100) ORDER BY 1;
+ }
+} {79 6 6400 89 6 8100 74}
+do_test format3-9.13 {
+ count {
+ SELECT * FROM t1 WHERE x IN (1,7) AND y NOT IN (6400,8100) ORDER BY 1;
+ }
+} {2 1 9 3 1 16 6}
+do_test format3-9.14 {
+ count {
+ SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,10) ORDER BY 1;
+ }
+} {2 1 9 6}
+
+# This procedure executes the SQL. Then it checks the generated program
+# for the SQL and appends a "nosort" to the result if the program contains the
+# SortCallback opcode. If the program does not contain the SortCallback
+# opcode it appends "sort"
+#
+proc cksort {sql} {
+ set data [execsql $sql]
+ set prog [execsql "EXPLAIN $sql"]
+ if {[regexp SortCallback $prog]} {set x sort} {set x nosort}
+ lappend data $x
+ return $data
+}
+# Check out the logic that attempts to implement the ORDER BY clause
+# using an index rather than by sorting.
+#
+do_test format3-10.1 {
+ execsql {
+ CREATE TABLE t3(a,b,c);
+ CREATE INDEX t3a ON t3(a);
+ CREATE INDEX t3bc ON t3(b,c);
+ CREATE INDEX t3acb ON t3(a,c,b);
+ INSERT INTO t3 SELECT w, 101-w, y FROM t1;
+ SELECT count(*), sum(a), sum(b), sum(c) FROM t3;
+ }
+} {100 5050 5050 348550}
+do_test format3-10.2 {
+ cksort {
+ SELECT * FROM t3 ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 nosort}
+do_test format3-10.3 {
+ cksort {
+ SELECT * FROM t3 ORDER BY a+1 LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 sort}
+do_test format3-10.4 {
+ cksort {
+ SELECT * FROM t3 WHERE a<10 ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 nosort}
+do_test format3-10.5 {
+ cksort {
+ SELECT * FROM t3 WHERE a>0 AND a<10 ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 nosort}
+do_test format3-10.6 {
+ cksort {
+ SELECT * FROM t3 WHERE a>0 ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 nosort}
+do_test format3-10.7 {
+ cksort {
+ SELECT * FROM t3 WHERE b>0 ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 sort}
+do_test format3-10.8 {
+ cksort {
+ SELECT * FROM t3 WHERE a IN (3,5,7,1,9,4,2) ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 sort}
+do_test format3-10.9 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test format3-10.10 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test format3-10.11 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a,c LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test format3-10.12 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a,c,b LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test format3-10.13 {
+ cksort {
+ SELECT * FROM t3 WHERE a>0 ORDER BY a DESC LIMIT 3
+ }
+} {100 1 10201 99 2 10000 98 3 9801 nosort}
+do_test format3-10.13.1 {
+ cksort {
+ SELECT * FROM t3 WHERE a>0 ORDER BY a+1 DESC LIMIT 3
+ }
+} {100 1 10201 99 2 10000 98 3 9801 sort}
+do_test format3-10.14 {
+ cksort {
+ SELECT * FROM t3 ORDER BY b LIMIT 3
+ }
+} {100 1 10201 99 2 10000 98 3 9801 nosort}
+do_test format3-10.15 {
+ cksort {
+ SELECT t3.a, t1.x FROM t3, t1 WHERE t3.a=t1.w ORDER BY t3.a LIMIT 3
+ }
+} {1 0 2 1 3 1 nosort}
+do_test format3-10.16 {
+ cksort {
+ SELECT t3.a, t1.x FROM t3, t1 WHERE t3.a=t1.w ORDER BY t1.x, t3.a LIMIT 3
+ }
+} {1 0 2 1 3 1 sort}
+do_test format3-10.17 {
+ cksort {
+ SELECT y FROM t1 ORDER BY w COLLATE text LIMIT 3;
+ }
+} {4 121 10201 sort}
+do_test format3-10.18 {
+ cksort {
+ SELECT y FROM t1 ORDER BY w COLLATE numeric LIMIT 3;
+ }
+} {4 9 16 sort}
+do_test format3-10.19 {
+ cksort {
+ SELECT y FROM t1 ORDER BY w LIMIT 3;
+ }
+} {4 9 16 nosort}
+
+# Check that all comparisons are numeric. Similar tests in misc1.test
+# check the same comparisons on a format4+ database and find that some
+# are numeric and some are text.
+#
+do_test format3-11.1 {
+ execsql {SELECT '0'=='0.0'}
+} {1}
+do_test format3-11.2 {
+ execsql {SELECT '0'==0.0}
+} {1}
+do_test format3-11.3 {
+ execsql {SELECT '123456789012345678901'=='123456789012345678900'}
+} {1}
+do_test format3-11.4 {
+ execsql {
+ CREATE TABLE t6(a INT UNIQUE, b TEXT UNIQUE);
+ INSERT INTO t6 VALUES('0','0.0');
+ SELECT * FROM t6;
+ }
+} {0 0.0}
+do_test format3-11.5 {
+ execsql {
+ INSERT OR IGNORE INTO t6 VALUES(0.0,'x');
+ SELECT * FROM t6;
+ }
+} {0 0.0}
+do_test format3-11.6 {
+ execsql {
+ INSERT OR IGNORE INTO t6 VALUES('y',0);
+ SELECT * FROM t6;
+ }
+} {0 0.0}
+do_test format3-11.7 {
+ execsql {
+ CREATE TABLE t7(x INTEGER, y TEXT, z);
+ INSERT INTO t7 VALUES(0,0,1);
+ INSERT INTO t7 VALUES(0.0,0,2);
+ INSERT INTO t7 VALUES(0,0.0,3);
+ INSERT INTO t7 VALUES(0.0,0.0,4);
+ SELECT DISTINCT x, y FROM t7 ORDER BY z;
+ }
+} {0 0}
+
+# Make sure attempts to attach a format 3 database fail.
+#
+do_test format3-12.1 {
+ file delete -force test2.db
+ sqlite db2 test2.db
+ catchsql {
+ CREATE TABLE t8(x,y);
+ ATTACH DATABASE 'test.db' AS format3;
+ } db2;
+} {1 {incompatible file format in auxiliary database: format3}}
+do_test format3-12.2 {
+ catchsql {
+ ATTACH DATABASE 'test2.db' AS test2;
+ }
+} {1 {cannot attach auxiliary databases to an older format master database}}
+db2 close
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/func.test b/usr/src/lib/libsqlite/test/func.test
new file mode 100644
index 0000000000..521e6af45f
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/func.test
@@ -0,0 +1,348 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 built-in functions.
+#
+# $Id: func.test,v 1.16.2.2 2004/07/18 21:14:05 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a table to work with.
+#
+do_test func-0.0 {
+ execsql {CREATE TABLE tbl1(t1 text)}
+ foreach word {this program is free software} {
+ execsql "INSERT INTO tbl1 VALUES('$word')"
+ }
+ execsql {SELECT t1 FROM tbl1 ORDER BY t1}
+} {free is program software this}
+do_test func-0.1 {
+ execsql {
+ CREATE TABLE t2(a);
+ INSERT INTO t2 VALUES(1);
+ INSERT INTO t2 VALUES(NULL);
+ INSERT INTO t2 VALUES(345);
+ INSERT INTO t2 VALUES(NULL);
+ INSERT INTO t2 VALUES(67890);
+ SELECT * FROM t2;
+ }
+} {1 {} 345 {} 67890}
+
+# Check out the length() function
+#
+do_test func-1.0 {
+ execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
+} {4 2 7 8 4}
+do_test func-1.1 {
+ set r [catch {execsql {SELECT length(*) FROM tbl1 ORDER BY t1}} msg]
+ lappend r $msg
+} {1 {wrong number of arguments to function length()}}
+do_test func-1.2 {
+ set r [catch {execsql {SELECT length(t1,5) FROM tbl1 ORDER BY t1}} msg]
+ lappend r $msg
+} {1 {wrong number of arguments to function length()}}
+do_test func-1.3 {
+ execsql {SELECT length(t1), count(*) FROM tbl1 GROUP BY length(t1)
+ ORDER BY length(t1)}
+} {2 1 4 2 7 1 8 1}
+do_test func-1.4 {
+ execsql {SELECT coalesce(length(a),-1) FROM t2}
+} {1 -1 3 -1 5}
+
+# Check out the substr() function
+#
+do_test func-2.0 {
+ execsql {SELECT substr(t1,1,2) FROM tbl1 ORDER BY t1}
+} {fr is pr so th}
+do_test func-2.1 {
+ execsql {SELECT substr(t1,2,1) FROM tbl1 ORDER BY t1}
+} {r s r o h}
+do_test func-2.2 {
+ execsql {SELECT substr(t1,3,3) FROM tbl1 ORDER BY t1}
+} {ee {} ogr ftw is}
+do_test func-2.3 {
+ execsql {SELECT substr(t1,-1,1) FROM tbl1 ORDER BY t1}
+} {e s m e s}
+do_test func-2.4 {
+ execsql {SELECT substr(t1,-1,2) FROM tbl1 ORDER BY t1}
+} {e s m e s}
+do_test func-2.5 {
+ execsql {SELECT substr(t1,-2,1) FROM tbl1 ORDER BY t1}
+} {e i a r i}
+do_test func-2.6 {
+ execsql {SELECT substr(t1,-2,2) FROM tbl1 ORDER BY t1}
+} {ee is am re is}
+do_test func-2.7 {
+ execsql {SELECT substr(t1,-4,2) FROM tbl1 ORDER BY t1}
+} {fr {} gr wa th}
+do_test func-2.8 {
+ execsql {SELECT t1 FROM tbl1 ORDER BY substr(t1,2,20)}
+} {this software free program is}
+do_test func-2.9 {
+ execsql {SELECT substr(a,1,1) FROM t2}
+} {1 {} 3 {} 6}
+do_test func-2.10 {
+ execsql {SELECT substr(a,2,2) FROM t2}
+} {{} {} 45 {} 78}
+
+# Only do the following tests if TCL has UTF-8 capabilities and
+# the UTF-8 encoding is turned on in the SQLite library.
+#
+if {[sqlite -encoding]=="UTF-8" && "\u1234"!="u1234"} {
+
+# Put some UTF-8 characters in the database
+#
+do_test func-3.0 {
+ execsql {DELETE FROM tbl1}
+ foreach word "contains UTF-8 characters hi\u1234ho" {
+ execsql "INSERT INTO tbl1 VALUES('$word')"
+ }
+ execsql {SELECT t1 FROM tbl1 ORDER BY t1}
+} "UTF-8 characters contains hi\u1234ho"
+do_test func-3.1 {
+ execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
+} {5 10 8 5}
+do_test func-3.2 {
+ execsql {SELECT substr(t1,1,2) FROM tbl1 ORDER BY t1}
+} {UT ch co hi}
+do_test func-3.3 {
+ execsql {SELECT substr(t1,1,3) FROM tbl1 ORDER BY t1}
+} "UTF cha con hi\u1234"
+do_test func-3.4 {
+ execsql {SELECT substr(t1,2,2) FROM tbl1 ORDER BY t1}
+} "TF ha on i\u1234"
+do_test func-3.5 {
+ execsql {SELECT substr(t1,2,3) FROM tbl1 ORDER BY t1}
+} "TF- har ont i\u1234h"
+do_test func-3.6 {
+ execsql {SELECT substr(t1,3,2) FROM tbl1 ORDER BY t1}
+} "F- ar nt \u1234h"
+do_test func-3.7 {
+ execsql {SELECT substr(t1,4,2) FROM tbl1 ORDER BY t1}
+} "-8 ra ta ho"
+do_test func-3.8 {
+ execsql {SELECT substr(t1,-1,1) FROM tbl1 ORDER BY t1}
+} "8 s s o"
+do_test func-3.9 {
+ execsql {SELECT substr(t1,-3,2) FROM tbl1 ORDER BY t1}
+} "F- er in \u1234h"
+do_test func-3.10 {
+ execsql {SELECT substr(t1,-4,3) FROM tbl1 ORDER BY t1}
+} "TF- ter ain i\u1234h"
+do_test func-3.99 {
+ execsql {DELETE FROM tbl1}
+ foreach word {this program is free software} {
+ execsql "INSERT INTO tbl1 VALUES('$word')"
+ }
+ execsql {SELECT t1 FROM tbl1}
+} {this program is free software}
+
+} ;# End [sqlite -encoding]==UTF-8 and \u1234!=u1234
+
+# Test the abs() and round() functions.
+#
+do_test func-4.1 {
+ execsql {
+ CREATE TABLE t1(a,b,c);
+ INSERT INTO t1 VALUES(1,2,3);
+ INSERT INTO t1 VALUES(2,1.2345678901234,-12345.67890);
+ INSERT INTO t1 VALUES(3,-2,-5);
+ }
+ catchsql {SELECT abs(a,b) FROM t1}
+} {1 {wrong number of arguments to function abs()}}
+do_test func-4.2 {
+ catchsql {SELECT abs() FROM t1}
+} {1 {wrong number of arguments to function abs()}}
+do_test func-4.3 {
+ catchsql {SELECT abs(b) FROM t1 ORDER BY a}
+} {0 {2 1.2345678901234 2}}
+do_test func-4.4 {
+ catchsql {SELECT abs(c) FROM t1 ORDER BY a}
+} {0 {3 12345.67890 5}}
+do_test func-4.4.1 {
+ execsql {SELECT abs(a) FROM t2}
+} {1 {} 345 {} 67890}
+do_test func-4.4.2 {
+ execsql {SELECT abs(t1) FROM tbl1}
+} {this program is free software}
+
+do_test func-4.5 {
+ catchsql {SELECT round(a,b,c) FROM t1}
+} {1 {wrong number of arguments to function round()}}
+do_test func-4.6 {
+ catchsql {SELECT round(b,2) FROM t1 ORDER BY b}
+} {0 {-2.00 1.23 2.00}}
+do_test func-4.7 {
+ catchsql {SELECT round(b,0) FROM t1 ORDER BY a}
+} {0 {2 1 -2}}
+do_test func-4.8 {
+ catchsql {SELECT round(c) FROM t1 ORDER BY a}
+} {0 {3 -12346 -5}}
+do_test func-4.9 {
+ catchsql {SELECT round(c,a) FROM t1 ORDER BY a}
+} {0 {3.0 -12345.68 -5.000}}
+do_test func-4.10 {
+ catchsql {SELECT 'x' || round(c,a) || 'y' FROM t1 ORDER BY a}
+} {0 {x3.0y x-12345.68y x-5.000y}}
+do_test func-4.11 {
+ catchsql {SELECT round() FROM t1 ORDER BY a}
+} {1 {wrong number of arguments to function round()}}
+do_test func-4.12 {
+ execsql {SELECT coalesce(round(a,2),'nil') FROM t2}
+} {1.00 nil 345.00 nil 67890.00}
+do_test func-4.13 {
+ execsql {SELECT round(t1,2) FROM tbl1}
+} {0.00 0.00 0.00 0.00 0.00}
+
+# Test the upper() and lower() functions
+#
+do_test func-5.1 {
+ execsql {SELECT upper(t1) FROM tbl1}
+} {THIS PROGRAM IS FREE SOFTWARE}
+do_test func-5.2 {
+ execsql {SELECT lower(upper(t1)) FROM tbl1}
+} {this program is free software}
+do_test func-5.3 {
+ execsql {SELECT upper(a), lower(a) FROM t2}
+} {1 1 {} {} 345 345 {} {} 67890 67890}
+do_test func-5.4 {
+ catchsql {SELECT upper(a,5) FROM t2}
+} {1 {wrong number of arguments to function upper()}}
+do_test func-5.5 {
+ catchsql {SELECT upper(*) FROM t2}
+} {1 {wrong number of arguments to function upper()}}
+
+# Test the coalesce() and nullif() functions
+#
+do_test func-6.1 {
+ execsql {SELECT coalesce(a,'xyz') FROM t2}
+} {1 xyz 345 xyz 67890}
+do_test func-6.2 {
+ execsql {SELECT coalesce(upper(a),'nil') FROM t2}
+} {1 nil 345 nil 67890}
+do_test func-6.3 {
+ execsql {SELECT coalesce(nullif(1,1),'nil')}
+} {nil}
+do_test func-6.4 {
+ execsql {SELECT coalesce(nullif(1,2),'nil')}
+} {1}
+do_test func-6.5 {
+ execsql {SELECT coalesce(nullif(1,NULL),'nil')}
+} {1}
+
+
+# Test the last_insert_rowid() function
+#
+do_test func-7.1 {
+ execsql {SELECT last_insert_rowid()}
+} [db last_insert_rowid]
+
+# Tests for aggregate functions and how they handle NULLs.
+#
+do_test func-8.1 {
+ execsql {
+ SELECT sum(a), count(a), round(avg(a),2), min(a), max(a), count(*) FROM t2;
+ }
+} {68236 3 22745.33 1 67890 5}
+do_test func-8.2 {
+ execsql {
+ SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t2;
+ }
+} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
+do_test func-8.3 {
+ execsql {
+ CREATE TEMP TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
+ SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
+ }
+} {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
+do_test func-8.4 {
+ execsql {
+ SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
+ }
+} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
+
+# How do you test the random() function in a meaningful, deterministic way?
+#
+do_test func-9.1 {
+ execsql {
+ SELECT random() is not null;
+ }
+} {1}
+
+# Use the "sqlite_register_test_function" TCL command which is part of
+# the text fixture in order to verify correct operation of some of
+# the user-defined SQL function APIs that are not used by the built-in
+# functions.
+#
+db close
+set ::DB [sqlite db test.db]
+sqlite_register_test_function $::DB testfunc
+do_test func-10.1 {
+ catchsql {
+ SELECT testfunc(NULL,NULL);
+ }
+} {1 {first argument to test function may not be NULL}}
+do_test func-10.2 {
+ execsql {
+ SELECT testfunc(
+ 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'int', 1234
+ );
+ }
+} {1234}
+do_test func-10.3 {
+ execsql {
+ SELECT testfunc(
+ 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'string', NULL
+ );
+ }
+} {{}}
+do_test func-10.4 {
+ execsql {
+ SELECT testfunc(
+ 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'double', 1.234
+ );
+ }
+} {1.234}
+do_test func-10.5 {
+ execsql {
+ SELECT testfunc(
+ 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'int', 1234,
+ 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'string', NULL,
+ 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'double', 1.234,
+ 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'int', 1234,
+ 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'string', NULL,
+ 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'double', 1.234
+ );
+ }
+} {1.234}
+
+# Test the built-in sqlite_version(*) SQL function.
+#
+do_test func-11.1 {
+ execsql {
+ SELECT sqlite_version(*);
+ }
+} [sqlite -version]
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/hook.test b/usr/src/lib/libsqlite/test/hook.test
new file mode 100644
index 0000000000..dd8ebf3573
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/hook.test
@@ -0,0 +1,86 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2004 Jan 14
+#
+# 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 TCL interface to the
+# SQLite library.
+#
+# The focus of the tests in this file is the following interface:
+#
+# sqlite_commit_hook
+#
+# $Id: hook.test,v 1.3 2004/01/15 02:44:03 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test hook-1.2 {
+ db commit_hook
+} {}
+
+
+do_test hook-3.1 {
+ set commit_cnt 0
+ proc commit_hook {} {
+ incr ::commit_cnt
+ return 0
+ }
+ db commit_hook ::commit_hook
+ db commit_hook
+} {::commit_hook}
+do_test hook-3.2 {
+ set commit_cnt
+} {0}
+do_test hook-3.3 {
+ execsql {
+ CREATE TABLE t2(a,b);
+ }
+ set commit_cnt
+} {1}
+do_test hook-3.4 {
+ execsql {
+ INSERT INTO t2 VALUES(1,2);
+ INSERT INTO t2 SELECT a+1, b+1 FROM t2;
+ INSERT INTO t2 SELECT a+2, b+2 FROM t2;
+ }
+ set commit_cnt
+} {4}
+do_test hook-3.5 {
+ set commit_cnt {}
+ proc commit_hook {} {
+ set ::commit_cnt [execsql {SELECT * FROM t2}]
+ return 0
+ }
+ execsql {
+ INSERT INTO t2 VALUES(5,6);
+ }
+ set commit_cnt
+} {1 2 2 3 3 4 4 5 5 6}
+do_test hook-3.6 {
+ set commit_cnt {}
+ proc commit_hook {} {
+ set ::commit_cnt [execsql {SELECT * FROM t2}]
+ return 1
+ }
+ catchsql {
+ INSERT INTO t2 VALUES(6,7);
+ }
+} {1 {constraint failed}}
+do_test hook-3.7 {
+ set commit_cnt
+} {1 2 2 3 3 4 4 5 5 6 6 7}
+do_test hook-3.8 {
+ execsql {SELECT * FROM t2}
+} {1 2 2 3 3 4 4 5 5 6}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/in.test b/usr/src/lib/libsqlite/test/in.test
new file mode 100644
index 0000000000..612dc1909c
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/in.test
@@ -0,0 +1,306 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 IN and BETWEEN operator.
+#
+# $Id: in.test,v 1.11 2004/01/15 03:30:25 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Generate the test data we will need for the first squences of tests.
+#
+do_test in-1.0 {
+ set fd [open data1.txt w]
+ for {set i 1} {$i<=10} {incr i} {
+ puts $fd "$i\t[expr {int(pow(2,$i))}]"
+ }
+ close $fd
+ execsql {
+ CREATE TABLE t1(a int, b int);
+ COPY t1 FROM 'data1.txt';
+ }
+ file delete -force data1.txt
+ execsql {SELECT count(*) FROM t1}
+} {10}
+
+# Do basic testing of BETWEEN.
+#
+do_test in-1.1 {
+ execsql {SELECT a FROM t1 WHERE b BETWEEN 10 AND 50 ORDER BY a}
+} {4 5}
+do_test in-1.2 {
+ execsql {SELECT a FROM t1 WHERE b NOT BETWEEN 10 AND 50 ORDER BY a}
+} {1 2 3 6 7 8 9 10}
+do_test in-1.3 {
+ execsql {SELECT a FROM t1 WHERE b BETWEEN a AND a*5 ORDER BY a}
+} {1 2 3 4}
+do_test in-1.4 {
+ execsql {SELECT a FROM t1 WHERE b NOT BETWEEN a AND a*5 ORDER BY a}
+} {5 6 7 8 9 10}
+do_test in-1.6 {
+ execsql {SELECT a FROM t1 WHERE b BETWEEN a AND a*5 OR b=512 ORDER BY a}
+} {1 2 3 4 9}
+do_test in-1.7 {
+ execsql {SELECT a+ 100*(a BETWEEN 1 and 3) FROM t1 ORDER BY b}
+} {101 102 103 4 5 6 7 8 9 10}
+
+
+# Testing of the IN operator using static lists on the right-hand side.
+#
+do_test in-2.1 {
+ execsql {SELECT a FROM t1 WHERE b IN (8,12,16,24,32) ORDER BY a}
+} {3 4 5}
+do_test in-2.2 {
+ execsql {SELECT a FROM t1 WHERE b NOT IN (8,12,16,24,32) ORDER BY a}
+} {1 2 6 7 8 9 10}
+do_test in-2.3 {
+ execsql {SELECT a FROM t1 WHERE b IN (8,12,16,24,32) OR b=512 ORDER BY a}
+} {3 4 5 9}
+do_test in-2.4 {
+ execsql {SELECT a FROM t1 WHERE b NOT IN (8,12,16,24,32) OR b=512 ORDER BY a}
+} {1 2 6 7 8 9 10}
+do_test in-2.5 {
+ execsql {SELECT a+100*(b IN (8,16,24)) FROM t1 ORDER BY b}
+} {1 2 103 104 5 6 7 8 9 10}
+
+do_test in-2.6 {
+ set v [catch {execsql {SELECT a FROM t1 WHERE b IN (b+10,20)}} msg]
+ lappend v $msg
+} {1 {right-hand side of IN operator must be constant}}
+do_test in-2.7 {
+ set v [catch {execsql {SELECT a FROM t1 WHERE b IN (max(5,10,b),20)}} msg]
+ lappend v $msg
+} {1 {right-hand side of IN operator must be constant}}
+do_test in-2.8 {
+ execsql {SELECT a FROM t1 WHERE b IN (8*2,64/2) ORDER BY b}
+} {4 5}
+do_test in-2.9 {
+ set v [catch {execsql {SELECT a FROM t1 WHERE b IN (max(5,10),20)}} msg]
+ lappend v $msg
+} {1 {right-hand side of IN operator must be constant}}
+do_test in-2.10 {
+ set v [catch {execsql {SELECT a FROM t1 WHERE min(0,b IN (a,30))}} msg]
+ lappend v $msg
+} {1 {right-hand side of IN operator must be constant}}
+do_test in-2.11 {
+ set v [catch {execsql {SELECT a FROM t1 WHERE c IN (10,20)}} msg]
+ lappend v $msg
+} {1 {no such column: c}}
+
+# Testing the IN operator where the right-hand side is a SELECT
+#
+do_test in-3.1 {
+ execsql {
+ SELECT a FROM t1
+ WHERE b IN (SELECT b FROM t1 WHERE a<5)
+ ORDER BY a
+ }
+} {1 2 3 4}
+do_test in-3.2 {
+ execsql {
+ SELECT a FROM t1
+ WHERE b IN (SELECT b FROM t1 WHERE a<5) OR b==512
+ ORDER BY a
+ }
+} {1 2 3 4 9}
+do_test in-3.3 {
+ execsql {
+ SELECT a + 100*(b IN (SELECT b FROM t1 WHERE a<5)) FROM t1 ORDER BY b
+ }
+} {101 102 103 104 5 6 7 8 9 10}
+
+# Make sure the UPDATE and DELETE commands work with IN-SELECT
+#
+do_test in-4.1 {
+ execsql {
+ UPDATE t1 SET b=b*2
+ WHERE b IN (SELECT b FROM t1 WHERE a>8)
+ }
+ execsql {SELECT b FROM t1 ORDER BY b}
+} {2 4 8 16 32 64 128 256 1024 2048}
+do_test in-4.2 {
+ execsql {
+ DELETE FROM t1 WHERE b IN (SELECT b FROM t1 WHERE a>8)
+ }
+ execsql {SELECT a FROM t1 ORDER BY a}
+} {1 2 3 4 5 6 7 8}
+do_test in-4.3 {
+ execsql {
+ DELETE FROM t1 WHERE b NOT IN (SELECT b FROM t1 WHERE a>4)
+ }
+ execsql {SELECT a FROM t1 ORDER BY a}
+} {5 6 7 8}
+
+# Do an IN with a constant RHS but where the RHS has many, many
+# elements. We need to test that collisions in the hash table
+# are resolved properly.
+#
+do_test in-5.1 {
+ execsql {
+ INSERT INTO t1 VALUES('hello', 'world');
+ SELECT * FROM t1
+ WHERE a IN (
+ 'Do','an','IN','with','a','constant','RHS','but','where','the',
+ 'has','many','elements','We','need','to','test','that',
+ 'collisions','hash','table','are','resolved','properly',
+ 'This','in-set','contains','thirty','one','entries','hello');
+ }
+} {hello world}
+
+# Make sure the IN operator works with INTEGER PRIMARY KEY fields.
+#
+do_test in-6.1 {
+ execsql {
+ CREATE TABLE ta(a INTEGER PRIMARY KEY, b);
+ INSERT INTO ta VALUES(1,1);
+ INSERT INTO ta VALUES(2,2);
+ INSERT INTO ta VALUES(3,3);
+ INSERT INTO ta VALUES(4,4);
+ INSERT INTO ta VALUES(6,6);
+ INSERT INTO ta VALUES(8,8);
+ INSERT INTO ta VALUES(10,
+ 'This is a key that is long enough to require a malloc in the VDBE');
+ SELECT * FROM ta WHERE a<10;
+ }
+} {1 1 2 2 3 3 4 4 6 6 8 8}
+do_test in-6.2 {
+ execsql {
+ CREATE TABLE tb(a INTEGER PRIMARY KEY, b);
+ INSERT INTO tb VALUES(1,1);
+ INSERT INTO tb VALUES(2,2);
+ INSERT INTO tb VALUES(3,3);
+ INSERT INTO tb VALUES(5,5);
+ INSERT INTO tb VALUES(7,7);
+ INSERT INTO tb VALUES(9,9);
+ INSERT INTO tb VALUES(11,
+ 'This is a key that is long enough to require a malloc in the VDBE');
+ SELECT * FROM tb WHERE a<10;
+ }
+} {1 1 2 2 3 3 5 5 7 7 9 9}
+do_test in-6.3 {
+ execsql {
+ SELECT a FROM ta WHERE b IN (SELECT a FROM tb);
+ }
+} {1 2 3}
+do_test in-6.4 {
+ execsql {
+ SELECT a FROM ta WHERE b NOT IN (SELECT a FROM tb);
+ }
+} {4 6 8 10}
+do_test in-6.5 {
+ execsql {
+ SELECT a FROM ta WHERE b IN (SELECT b FROM tb);
+ }
+} {1 2 3 10}
+do_test in-6.6 {
+ execsql {
+ SELECT a FROM ta WHERE b NOT IN (SELECT b FROM tb);
+ }
+} {4 6 8}
+do_test in-6.7 {
+ execsql {
+ SELECT a FROM ta WHERE a IN (SELECT a FROM tb);
+ }
+} {1 2 3}
+do_test in-6.8 {
+ execsql {
+ SELECT a FROM ta WHERE a NOT IN (SELECT a FROM tb);
+ }
+} {4 6 8 10}
+do_test in-6.9 {
+ execsql {
+ SELECT a FROM ta WHERE a IN (SELECT b FROM tb);
+ }
+} {1 2 3}
+do_test in-6.10 {
+ execsql {
+ SELECT a FROM ta WHERE a NOT IN (SELECT b FROM tb);
+ }
+} {4 6 8 10}
+
+# Tests of IN operator against empty sets. (Ticket #185)
+#
+do_test in-7.1 {
+ execsql {
+ SELECT a FROM t1 WHERE a IN ();
+ }
+} {}
+do_test in-7.2 {
+ execsql {
+ SELECT a FROM t1 WHERE a IN (5);
+ }
+} {5}
+do_test in-7.3 {
+ execsql {
+ SELECT a FROM t1 WHERE a NOT IN () ORDER BY a;
+ }
+} {5 6 7 8 hello}
+do_test in-7.4 {
+ execsql {
+ SELECT a FROM t1 WHERE a IN (5) AND b IN ();
+ }
+} {}
+do_test in-7.5 {
+ execsql {
+ SELECT a FROM t1 WHERE a IN (5) AND b NOT IN ();
+ }
+} {5}
+do_test in-7.6 {
+ execsql {
+ SELECT a FROM ta WHERE a IN ();
+ }
+} {}
+do_test in-7.7 {
+ execsql {
+ SELECT a FROM ta WHERE a NOT IN ();
+ }
+} {1 2 3 4 6 8 10}
+
+do_test in-8.1 {
+ execsql {
+ SELECT b FROM t1 WHERE a IN ('hello','there')
+ }
+} {world}
+do_test in-8.2 {
+ execsql {
+ SELECT b FROM t1 WHERE a IN ("hello",'there')
+ }
+} {world}
+
+# Test constructs of the form: expr IN tablename
+#
+do_test in-9.1 {
+ execsql {
+ CREATE TABLE t4 AS SELECT a FROM tb;
+ SELECT * FROM t4;
+ }
+} {1 2 3 5 7 9 11}
+do_test in-9.2 {
+ execsql {
+ SELECT b FROM t1 WHERE a IN t4;
+ }
+} {32 128}
+do_test in-9.3 {
+ execsql {
+ SELECT b FROM t1 WHERE a NOT IN t4;
+ }
+} {64 256 world}
+do_test in-9.4 {
+ catchsql {
+ SELECT b FROM t1 WHERE a NOT IN tb;
+ }
+} {1 {only a single result allowed for a SELECT that is part of an expression}}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/index.test b/usr/src/lib/libsqlite/test/index.test
new file mode 100644
index 0000000000..aabe7f3869
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/index.test
@@ -0,0 +1,536 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 CREATE INDEX statement.
+#
+# $Id: index.test,v 1.24.2.1 2004/07/20 00:50:30 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a basic index and verify it is added to sqlite_master
+#
+do_test index-1.1 {
+ execsql {CREATE TABLE test1(f1 int, f2 int, f3 int)}
+ execsql {CREATE INDEX index1 ON test1(f1)}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {index1 test1}
+do_test index-1.1b {
+ execsql {SELECT name, sql, tbl_name, type FROM sqlite_master
+ WHERE name='index1'}
+} {index1 {CREATE INDEX index1 ON test1(f1)} test1 index}
+do_test index-1.1c {
+ db close
+ sqlite db test.db
+ execsql {SELECT name, sql, tbl_name, type FROM sqlite_master
+ WHERE name='index1'}
+} {index1 {CREATE INDEX index1 ON test1(f1)} test1 index}
+do_test index-1.1d {
+ db close
+ sqlite db test.db
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {index1 test1}
+
+# Verify that the index dies with the table
+#
+do_test index-1.2 {
+ execsql {DROP TABLE test1}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {}
+
+# Try adding an index to a table that does not exist
+#
+do_test index-2.1 {
+ set v [catch {execsql {CREATE INDEX index1 ON test1(f1)}} msg]
+ lappend v $msg
+} {1 {no such table: test1}}
+
+# Try adding an index on a column of a table where the table
+# exists but the column does not.
+#
+do_test index-2.1 {
+ execsql {CREATE TABLE test1(f1 int, f2 int, f3 int)}
+ set v [catch {execsql {CREATE INDEX index1 ON test1(f4)}} msg]
+ lappend v $msg
+} {1 {table test1 has no column named f4}}
+
+# Try an index with some columns that match and others that do now.
+#
+do_test index-2.2 {
+ set v [catch {execsql {CREATE INDEX index1 ON test1(f1, f2, f4, f3)}} msg]
+ execsql {DROP TABLE test1}
+ lappend v $msg
+} {1 {table test1 has no column named f4}}
+
+# Try creating a bunch of indices on the same table
+#
+set r {}
+for {set i 1} {$i<100} {incr i} {
+ lappend r [format index%02d $i]
+}
+do_test index-3.1 {
+ execsql {CREATE TABLE test1(f1 int, f2 int, f3 int, f4 int, f5 int)}
+ for {set i 1} {$i<100} {incr i} {
+ set sql "CREATE INDEX [format index%02d $i] ON test1(f[expr {($i%5)+1}])"
+ execsql $sql
+ }
+ execsql {SELECT name FROM sqlite_master
+ WHERE type='index' AND tbl_name='test1'
+ ORDER BY name}
+} $r
+
+
+# Verify that all the indices go away when we drop the table.
+#
+do_test index-3.3 {
+ execsql {DROP TABLE test1}
+ execsql {SELECT name FROM sqlite_master
+ WHERE type='index' AND tbl_name='test1'
+ ORDER BY name}
+} {}
+
+# Create a table and insert values into that table. Then create
+# an index on that table. Verify that we can select values
+# from the table correctly using the index.
+#
+# Note that the index names "index9" and "indext" are chosen because
+# they both have the same hash.
+#
+do_test index-4.1 {
+ execsql {CREATE TABLE test1(cnt int, power int)}
+ for {set i 1} {$i<20} {incr i} {
+ execsql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
+ }
+ execsql {CREATE INDEX index9 ON test1(cnt)}
+ execsql {CREATE INDEX indext ON test1(power)}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {index9 indext test1}
+do_test index-4.2 {
+ execsql {SELECT cnt FROM test1 WHERE power=4}
+} {2}
+do_test index-4.3 {
+ execsql {SELECT cnt FROM test1 WHERE power=1024}
+} {10}
+do_test index-4.4 {
+ execsql {SELECT power FROM test1 WHERE cnt=6}
+} {64}
+do_test index-4.5 {
+ execsql {DROP INDEX indext}
+ execsql {SELECT power FROM test1 WHERE cnt=6}
+} {64}
+do_test index-4.6 {
+ execsql {SELECT cnt FROM test1 WHERE power=1024}
+} {10}
+do_test index-4.7 {
+ execsql {CREATE INDEX indext ON test1(cnt)}
+ execsql {SELECT power FROM test1 WHERE cnt=6}
+} {64}
+do_test index-4.8 {
+ execsql {SELECT cnt FROM test1 WHERE power=1024}
+} {10}
+do_test index-4.9 {
+ execsql {DROP INDEX index9}
+ execsql {SELECT power FROM test1 WHERE cnt=6}
+} {64}
+do_test index-4.10 {
+ execsql {SELECT cnt FROM test1 WHERE power=1024}
+} {10}
+do_test index-4.11 {
+ execsql {DROP INDEX indext}
+ execsql {SELECT power FROM test1 WHERE cnt=6}
+} {64}
+do_test index-4.12 {
+ execsql {SELECT cnt FROM test1 WHERE power=1024}
+} {10}
+do_test index-4.13 {
+ execsql {DROP TABLE test1}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {}
+integrity_check index-4.14
+
+# Do not allow indices to be added to sqlite_master
+#
+do_test index-5.1 {
+ set v [catch {execsql {CREATE INDEX index1 ON sqlite_master(name)}} msg]
+ lappend v $msg
+} {1 {table sqlite_master may not be indexed}}
+do_test index-5.2 {
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
+} {}
+
+# Do not allow indices with duplicate names to be added
+#
+do_test index-6.1 {
+ execsql {CREATE TABLE test1(f1 int, f2 int)}
+ execsql {CREATE TABLE test2(g1 real, g2 real)}
+ execsql {CREATE INDEX index1 ON test1(f1)}
+ set v [catch {execsql {CREATE INDEX index1 ON test2(g1)}} msg]
+ lappend v $msg
+} {1 {index index1 already exists}}
+do_test index-6.1b {
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {index1 test1 test2}
+do_test index-6.2 {
+ set v [catch {execsql {CREATE INDEX test1 ON test2(g1)}} msg]
+ lappend v $msg
+} {1 {there is already a table named test1}}
+do_test index-6.2b {
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {index1 test1 test2}
+do_test index-6.3 {
+ execsql {DROP TABLE test1}
+ execsql {DROP TABLE test2}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {}
+do_test index-6.4 {
+ execsql {
+ CREATE TABLE test1(a,b);
+ CREATE INDEX index1 ON test1(a);
+ CREATE INDEX index2 ON test1(b);
+ CREATE INDEX index3 ON test1(a,b);
+ DROP TABLE test1;
+ SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name;
+ }
+} {}
+integrity_check index-6.5
+
+
+# Create a primary key
+#
+do_test index-7.1 {
+ execsql {CREATE TABLE test1(f1 int, f2 int primary key)}
+ for {set i 1} {$i<20} {incr i} {
+ execsql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
+ }
+ execsql {SELECT count(*) FROM test1}
+} {19}
+do_test index-7.2 {
+ execsql {SELECT f1 FROM test1 WHERE f2=65536}
+} {16}
+do_test index-7.3 {
+ execsql {
+ SELECT name FROM sqlite_master
+ WHERE type='index' AND tbl_name='test1'
+ }
+} {{(test1 autoindex 1)}}
+do_test index-7.4 {
+ execsql {DROP table test1}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
+} {}
+integrity_check index-7.5
+
+# Make sure we cannot drop a non-existant index.
+#
+do_test index-8.1 {
+ set v [catch {execsql {DROP INDEX index1}} msg]
+ lappend v $msg
+} {1 {no such index: index1}}
+
+# Make sure we don't actually create an index when the EXPLAIN keyword
+# is used.
+#
+do_test index-9.1 {
+ execsql {CREATE TABLE tab1(a int)}
+ execsql {EXPLAIN CREATE INDEX idx1 ON tab1(a)}
+ execsql {SELECT name FROM sqlite_master WHERE tbl_name='tab1'}
+} {tab1}
+do_test index-9.2 {
+ execsql {CREATE INDEX idx1 ON tab1(a)}
+ execsql {SELECT name FROM sqlite_master WHERE tbl_name='tab1' ORDER BY name}
+} {idx1 tab1}
+integrity_check index-9.3
+
+# Allow more than one entry with the same key.
+#
+do_test index-10.0 {
+ execsql {
+ CREATE TABLE t1(a int, b int);
+ CREATE INDEX i1 ON t1(a);
+ INSERT INTO t1 VALUES(1,2);
+ INSERT INTO t1 VALUES(2,4);
+ INSERT INTO t1 VALUES(3,8);
+ INSERT INTO t1 VALUES(1,12);
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {2 12}
+do_test index-10.1 {
+ execsql {
+ SELECT b FROM t1 WHERE a=2 ORDER BY b;
+ }
+} {4}
+do_test index-10.2 {
+ execsql {
+ DELETE FROM t1 WHERE b=12;
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {2}
+do_test index-10.3 {
+ execsql {
+ DELETE FROM t1 WHERE b=2;
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {}
+do_test index-10.4 {
+ execsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES (1,1);
+ INSERT INTO t1 VALUES (1,2);
+ INSERT INTO t1 VALUES (1,3);
+ INSERT INTO t1 VALUES (1,4);
+ INSERT INTO t1 VALUES (1,5);
+ INSERT INTO t1 VALUES (1,6);
+ INSERT INTO t1 VALUES (1,7);
+ INSERT INTO t1 VALUES (1,8);
+ INSERT INTO t1 VALUES (1,9);
+ INSERT INTO t1 VALUES (2,0);
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {1 2 3 4 5 6 7 8 9}
+do_test index-10.5 {
+ execsql {
+ DELETE FROM t1 WHERE b IN (2, 4, 6, 8);
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {1 3 5 7 9}
+do_test index-10.6 {
+ execsql {
+ DELETE FROM t1 WHERE b>2;
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {1}
+do_test index-10.7 {
+ execsql {
+ DELETE FROM t1 WHERE b=1;
+ SELECT b FROM t1 WHERE a=1 ORDER BY b;
+ }
+} {}
+do_test index-10.8 {
+ execsql {
+ SELECT b FROM t1 ORDER BY b;
+ }
+} {0}
+integrity_check index-10.9
+
+# Automatically create an index when we specify a primary key.
+#
+do_test index-11.1 {
+ execsql {
+ CREATE TABLE t3(
+ a text,
+ b int,
+ c float,
+ PRIMARY KEY(b)
+ );
+ }
+ for {set i 1} {$i<=50} {incr i} {
+ execsql "INSERT INTO t3 VALUES('x${i}x',$i,0.$i)"
+ }
+ set sqlite_search_count 0
+ concat [execsql {SELECT c FROM t3 WHERE b==10}] $sqlite_search_count
+} {0.10 3}
+integrity_check index-11.2
+
+
+# Numeric strings should compare as if they were numbers. So even if the
+# strings are not character-by-character the same, if they represent the
+# same number they should compare equal to one another. Verify that this
+# is true in indices.
+#
+do_test index-12.1 {
+ execsql {
+ CREATE TABLE t4(a,b);
+ INSERT INTO t4 VALUES('0.0',1);
+ INSERT INTO t4 VALUES('0.00',2);
+ INSERT INTO t4 VALUES('abc',3);
+ INSERT INTO t4 VALUES('-1.0',4);
+ INSERT INTO t4 VALUES('+1.0',5);
+ INSERT INTO t4 VALUES('0',6);
+ INSERT INTO t4 VALUES('00000',7);
+ SELECT a FROM t4 ORDER BY b;
+ }
+} {0.0 0.00 abc -1.0 +1.0 0 00000}
+do_test index-12.2 {
+ execsql {
+ SELECT a FROM t4 WHERE a==0 ORDER BY b
+ }
+} {0.0 0.00 0 00000}
+do_test index-12.3 {
+ execsql {
+ SELECT a FROM t4 WHERE a<0.5 ORDER BY b
+ }
+} {0.0 0.00 -1.0 0 00000}
+do_test index-12.4 {
+ execsql {
+ SELECT a FROM t4 WHERE a>-0.5 ORDER BY b
+ }
+} {0.0 0.00 abc +1.0 0 00000}
+do_test index-12.5 {
+ execsql {
+ CREATE INDEX t4i1 ON t4(a);
+ SELECT a FROM t4 WHERE a==0 ORDER BY b
+ }
+} {0.0 0.00 0 00000}
+do_test index-12.6 {
+ execsql {
+ SELECT a FROM t4 WHERE a<0.5 ORDER BY b
+ }
+} {0.0 0.00 -1.0 0 00000}
+do_test index-12.7 {
+ execsql {
+ SELECT a FROM t4 WHERE a>-0.5 ORDER BY b
+ }
+} {0.0 0.00 abc +1.0 0 00000}
+integrity_check index-12.8
+
+# Make sure we cannot drop an automatically created index.
+#
+do_test index-13.1 {
+ execsql {
+ CREATE TABLE t5(
+ a int UNIQUE,
+ b float PRIMARY KEY,
+ c varchar(10),
+ UNIQUE(a,c)
+ );
+ INSERT INTO t5 VALUES(1,2,3);
+ SELECT * FROM t5;
+ }
+} {1 2 3}
+do_test index-13.2 {
+ set ::idxlist [execsql {
+ SELECT name FROM sqlite_master WHERE type="index" AND tbl_name="t5";
+ }]
+ llength $::idxlist
+} {3}
+for {set i 0} {$i<[llength $::idxlist]} {incr i} {
+ do_test index-13.3.$i {
+ catchsql "
+ DROP INDEX '[lindex $::idxlist $i]';
+ "
+ } {1 {index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped}}
+}
+do_test index-13.4 {
+ execsql {
+ INSERT INTO t5 VALUES('a','b','c');
+ SELECT * FROM t5;
+ }
+} {1 2 3 a b c}
+integrity_check index-13.5
+
+# Check the sort order of data in an index.
+#
+do_test index-14.1 {
+ execsql {
+ CREATE TABLE t6(a,b,c);
+ CREATE INDEX t6i1 ON t6(a,b);
+ INSERT INTO t6 VALUES('','',1);
+ INSERT INTO t6 VALUES('',NULL,2);
+ INSERT INTO t6 VALUES(NULL,'',3);
+ INSERT INTO t6 VALUES('abc',123,4);
+ INSERT INTO t6 VALUES(123,'abc',5);
+ SELECT c FROM t6 ORDER BY a,b;
+ }
+} {3 5 2 1 4}
+do_test index-14.2 {
+ execsql {
+ SELECT c FROM t6 WHERE a='';
+ }
+} {2 1}
+do_test index-14.3 {
+ execsql {
+ SELECT c FROM t6 WHERE b='';
+ }
+} {1 3}
+do_test index-14.4 {
+ execsql {
+ SELECT c FROM t6 WHERE a>'';
+ }
+} {4}
+do_test index-14.5 {
+ execsql {
+ SELECT c FROM t6 WHERE a>='';
+ }
+} {2 1 4}
+do_test index-14.6 {
+ execsql {
+ SELECT c FROM t6 WHERE a>123;
+ }
+} {2 1 4}
+do_test index-14.7 {
+ execsql {
+ SELECT c FROM t6 WHERE a>=123;
+ }
+} {5 2 1 4}
+do_test index-14.8 {
+ execsql {
+ SELECT c FROM t6 WHERE a<'abc';
+ }
+} {5 2 1}
+do_test index-14.9 {
+ execsql {
+ SELECT c FROM t6 WHERE a<='abc';
+ }
+} {5 2 1 4}
+do_test index-14.10 {
+ execsql {
+ SELECT c FROM t6 WHERE a<='';
+ }
+} {5 2 1}
+do_test index-14.11 {
+ execsql {
+ SELECT c FROM t6 WHERE a<'';
+ }
+} {5}
+integrity_check index-14.12
+
+do_test index-15.1 {
+ execsql {
+ DELETE FROM t1;
+ SELECT * FROM t1;
+ }
+} {}
+do_test index-15.2 {
+ execsql {
+ INSERT INTO t1 VALUES('1.234e5',1);
+ INSERT INTO t1 VALUES('12.33e04',2);
+ INSERT INTO t1 VALUES('12.35E4',3);
+ INSERT INTO t1 VALUES('12.34e',4);
+ INSERT INTO t1 VALUES('12.32e+4',5);
+ INSERT INTO t1 VALUES('12.36E+04',6);
+ INSERT INTO t1 VALUES('12.36E+',7);
+ INSERT INTO t1 VALUES('+123.10000E+0003',8);
+ INSERT INTO t1 VALUES('+',9);
+ INSERT INTO t1 VALUES('+12347.E+02',10);
+ INSERT INTO t1 VALUES('+12347E+02',11);
+ SELECT b FROM t1 ORDER BY a;
+ }
+} {8 5 2 1 3 6 11 9 10 4 7}
+integrity_check index-15.1
+
+# Drop index with a quoted name. Ticket #695.
+#
+do_test index-16.1 {
+ execsql {
+ CREATE INDEX "t6i2" ON t6(c);
+ DROP INDEX "t6i2";
+ }
+} {}
+do_test index-16.2 {
+ execsql {
+ DROP INDEX "t6i1";
+ }
+} {}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/insert.test b/usr/src/lib/libsqlite/test/insert.test
new file mode 100644
index 0000000000..b615347712
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/insert.test
@@ -0,0 +1,289 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 INSERT statement.
+#
+# $Id: insert.test,v 1.15 2003/06/15 23:42:25 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Try to insert into a non-existant table.
+#
+do_test insert-1.1 {
+ set v [catch {execsql {INSERT INTO test1 VALUES(1,2,3)}} msg]
+ lappend v $msg
+} {1 {no such table: test1}}
+
+# Try to insert into sqlite_master
+#
+do_test insert-1.2 {
+ set v [catch {execsql {INSERT INTO sqlite_master VALUES(1,2,3,4)}} msg]
+ lappend v $msg
+} {1 {table sqlite_master may not be modified}}
+
+# Try to insert the wrong number of entries.
+#
+do_test insert-1.3 {
+ execsql {CREATE TABLE test1(one int, two int, three int)}
+ set v [catch {execsql {INSERT INTO test1 VALUES(1,2)}} msg]
+ lappend v $msg
+} {1 {table test1 has 3 columns but 2 values were supplied}}
+do_test insert-1.3b {
+ set v [catch {execsql {INSERT INTO test1 VALUES(1,2,3,4)}} msg]
+ lappend v $msg
+} {1 {table test1 has 3 columns but 4 values were supplied}}
+do_test insert-1.3c {
+ set v [catch {execsql {INSERT INTO test1(one,two) VALUES(1,2,3,4)}} msg]
+ lappend v $msg
+} {1 {4 values for 2 columns}}
+do_test insert-1.3d {
+ set v [catch {execsql {INSERT INTO test1(one,two) VALUES(1)}} msg]
+ lappend v $msg
+} {1 {1 values for 2 columns}}
+
+# Try to insert into a non-existant column of a table.
+#
+do_test insert-1.4 {
+ set v [catch {execsql {INSERT INTO test1(one,four) VALUES(1,2)}} msg]
+ lappend v $msg
+} {1 {table test1 has no column named four}}
+
+# Make sure the inserts actually happen
+#
+do_test insert-1.5 {
+ execsql {INSERT INTO test1 VALUES(1,2,3)}
+ execsql {SELECT * FROM test1}
+} {1 2 3}
+do_test insert-1.5b {
+ execsql {INSERT INTO test1 VALUES(4,5,6)}
+ execsql {SELECT * FROM test1 ORDER BY one}
+} {1 2 3 4 5 6}
+do_test insert-1.5c {
+ execsql {INSERT INTO test1 VALUES(7,8,9)}
+ execsql {SELECT * FROM test1 ORDER BY one}
+} {1 2 3 4 5 6 7 8 9}
+
+do_test insert-1.6 {
+ execsql {DELETE FROM test1}
+ execsql {INSERT INTO test1(one,two) VALUES(1,2)}
+ execsql {SELECT * FROM test1 ORDER BY one}
+} {1 2 {}}
+do_test insert-1.6b {
+ execsql {INSERT INTO test1(two,three) VALUES(5,6)}
+ execsql {SELECT * FROM test1 ORDER BY one}
+} {{} 5 6 1 2 {}}
+do_test insert-1.6c {
+ execsql {INSERT INTO test1(three,one) VALUES(7,8)}
+ execsql {SELECT * FROM test1 ORDER BY one}
+} {{} 5 6 1 2 {} 8 {} 7}
+
+# A table to use for testing default values
+#
+do_test insert-2.1 {
+ execsql {
+ CREATE TABLE test2(
+ f1 int default -111,
+ f2 real default +4.32,
+ f3 int default +222,
+ f4 int default 7.89
+ )
+ }
+ execsql {SELECT * from test2}
+} {}
+do_test insert-2.2 {
+ execsql {INSERT INTO test2(f1,f3) VALUES(+10,-10)}
+ execsql {SELECT * FROM test2}
+} {10 4.32 -10 7.89}
+do_test insert-2.3 {
+ execsql {INSERT INTO test2(f2,f4) VALUES(1.23,-3.45)}
+ execsql {SELECT * FROM test2 WHERE f1==-111}
+} {-111 1.23 222 -3.45}
+do_test insert-2.4 {
+ execsql {INSERT INTO test2(f1,f2,f4) VALUES(77,+1.23,3.45)}
+ execsql {SELECT * FROM test2 WHERE f1==77}
+} {77 1.23 222 3.45}
+do_test insert-2.10 {
+ execsql {
+ DROP TABLE test2;
+ CREATE TABLE test2(
+ f1 int default 111,
+ f2 real default -4.32,
+ f3 text default hi,
+ f4 text default 'abc-123',
+ f5 varchar(10)
+ )
+ }
+ execsql {SELECT * from test2}
+} {}
+do_test insert-2.11 {
+ execsql {INSERT INTO test2(f2,f4) VALUES(-2.22,'hi!')}
+ execsql {SELECT * FROM test2}
+} {111 -2.22 hi hi! {}}
+do_test insert-2.12 {
+ execsql {INSERT INTO test2(f1,f5) VALUES(1,'xyzzy')}
+ execsql {SELECT * FROM test2 ORDER BY f1}
+} {1 -4.32 hi abc-123 xyzzy 111 -2.22 hi hi! {}}
+
+# Do additional inserts with default values, but this time
+# on a table that has indices. In particular we want to verify
+# that the correct default values are inserted into the indices.
+#
+do_test insert-3.1 {
+ execsql {
+ DELETE FROM test2;
+ CREATE INDEX index9 ON test2(f1,f2);
+ CREATE INDEX indext ON test2(f4,f5);
+ SELECT * from test2;
+ }
+} {}
+do_test insert-3.2 {
+ execsql {INSERT INTO test2(f2,f4) VALUES(-3.33,'hum')}
+ execsql {SELECT * FROM test2 WHERE f1=111 AND f2=-3.33}
+} {111 -3.33 hi hum {}}
+do_test insert-3.3 {
+ execsql {INSERT INTO test2(f1,f2,f5) VALUES(22,-4.44,'wham')}
+ execsql {SELECT * FROM test2 WHERE f1=111 AND f2=-3.33}
+} {111 -3.33 hi hum {}}
+do_test insert-3.4 {
+ execsql {SELECT * FROM test2 WHERE f1=22 AND f2=-4.44}
+} {22 -4.44 hi abc-123 wham}
+integrity_check insert-3.5
+
+# Test of expressions in the VALUES clause
+#
+do_test insert-4.1 {
+ execsql {
+ CREATE TABLE t3(a,b,c);
+ INSERT INTO t3 VALUES(1+2+3,4,5);
+ SELECT * FROM t3;
+ }
+} {6 4 5}
+do_test insert-4.2 {
+ execsql {
+ INSERT INTO t3 VALUES((SELECT max(a) FROM t3)+1,5,6);
+ SELECT * FROM t3 ORDER BY a;
+ }
+} {6 4 5 7 5 6}
+do_test insert-4.3 {
+ catchsql {
+ INSERT INTO t3 VALUES((SELECT max(a) FROM t3)+1,t3.a,6);
+ SELECT * FROM t3 ORDER BY a;
+ }
+} {1 {no such column: t3.a}}
+do_test insert-4.4 {
+ execsql {
+ INSERT INTO t3 VALUES((SELECT b FROM t3 WHERE a=0),6,7);
+ SELECT * FROM t3 ORDER BY a;
+ }
+} {{} 6 7 6 4 5 7 5 6}
+do_test insert-4.5 {
+ execsql {
+ SELECT b,c FROM t3 WHERE a IS NULL;
+ }
+} {6 7}
+do_test insert-4.6 {
+ catchsql {
+ INSERT INTO t3 VALUES(notafunc(2,3),2,3);
+ }
+} {1 {no such function: notafunc}}
+do_test insert-4.7 {
+ execsql {
+ INSERT INTO t3 VALUES(min(1,2,3),max(1,2,3),99);
+ SELECT * FROM t3 WHERE c=99;
+ }
+} {1 3 99}
+
+# Test the ability to insert from a temporary table into itself.
+# Ticket #275.
+#
+do_test insert-5.1 {
+ execsql {
+ CREATE TEMP TABLE t4(x);
+ INSERT INTO t4 VALUES(1);
+ SELECT * FROM t4;
+ }
+} {1}
+do_test insert-5.2 {
+ execsql {
+ INSERT INTO t4 SELECT x+1 FROM t4;
+ SELECT * FROM t4;
+ }
+} {1 2}
+do_test insert-5.3 {
+ # verify that a temporary table is used to copy t4 to t4
+ set x [execsql {
+ EXPLAIN INSERT INTO t4 SELECT x+2 FROM t4;
+ }]
+ expr {[lsearch $x OpenTemp]>0}
+} {1}
+do_test insert-5.4 {
+ # Verify that table "test1" begins on page 3. This should be the same
+ # page number used by "t4" above.
+ execsql {
+ SELECT rootpage FROM sqlite_master WHERE name='test1';
+ }
+} {3}
+do_test insert-5.5 {
+ # Verify that "t4" begins on page 3.
+ execsql {
+ SELECT rootpage FROM sqlite_temp_master WHERE name='t4';
+ }
+} {3}
+do_test insert-5.6 {
+ # This should not use an intermediate temporary table.
+ execsql {
+ INSERT INTO t4 SELECT one FROM test1 WHERE three=7;
+ SELECT * FROM t4
+ }
+} {1 2 8}
+do_test insert-5.7 {
+ # verify that no temporary table is used to copy test1 to t4
+ set x [execsql {
+ EXPLAIN INSERT INTO t4 SELECT one FROM test1;
+ }]
+ expr {[lsearch $x OpenTemp]>0}
+} {0}
+
+# Ticket #334: REPLACE statement corrupting indices.
+#
+do_test insert-6.1 {
+ execsql {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
+ INSERT INTO t1 VALUES(1,2);
+ INSERT INTO t1 VALUES(2,3);
+ SELECT b FROM t1 WHERE b=2;
+ }
+} {2}
+do_test insert-6.2 {
+ execsql {
+ REPLACE INTO t1 VALUES(1,4);
+ SELECT b FROM t1 WHERE b=2;
+ }
+} {}
+do_test insert-6.3 {
+ execsql {
+ UPDATE OR REPLACE t1 SET a=2 WHERE b=4;
+ SELECT * FROM t1 WHERE b=4;
+ }
+} {2 4}
+do_test insert-6.4 {
+ execsql {
+ SELECT * FROM t1 WHERE b=3;
+ }
+} {}
+
+integrity_check insert-99.0
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/insert2.test b/usr/src/lib/libsqlite/test/insert2.test
new file mode 100644
index 0000000000..1d1d72a11a
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/insert2.test
@@ -0,0 +1,197 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 INSERT statement that takes is
+# result from a SELECT.
+#
+# $Id: insert2.test,v 1.10 2002/06/25 13:16:04 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create some tables with data that we can select against
+#
+do_test insert2-1.0 {
+ execsql {CREATE TABLE d1(n int, log int);}
+ for {set i 1} {$i<=20} {incr i} {
+ for {set j 0} {pow(2,$j)<$i} {incr j} {}
+ execsql "INSERT INTO d1 VALUES($i,$j)"
+ }
+ execsql {SELECT * FROM d1 ORDER BY n}
+} {1 0 2 1 3 2 4 2 5 3 6 3 7 3 8 3 9 4 10 4 11 4 12 4 13 4 14 4 15 4 16 4 17 5 18 5 19 5 20 5}
+
+# Insert into a new table from the old one.
+#
+do_test insert2-1.1.1 {
+ execsql {
+ CREATE TABLE t1(log int, cnt int);
+ PRAGMA count_changes=on;
+ INSERT INTO t1 SELECT log, count(*) FROM d1 GROUP BY log;
+ }
+} {6}
+do_test insert2-1.1.2 {
+ db changes
+} {6}
+do_test insert2-1.1.3 {
+ execsql {SELECT * FROM t1 ORDER BY log}
+} {0 1 1 1 2 2 3 4 4 8 5 4}
+
+do_test insert2-1.2.1 {
+ catch {execsql {DROP TABLE t1}}
+ execsql {
+ CREATE TABLE t1(log int, cnt int);
+ INSERT INTO t1
+ SELECT log, count(*) FROM d1 GROUP BY log
+ EXCEPT SELECT n-1,log FROM d1;
+ }
+} {4}
+do_test insert2-1.2.2 {
+ execsql {
+ SELECT * FROM t1 ORDER BY log;
+ }
+} {0 1 3 4 4 8 5 4}
+do_test insert2-1.3.1 {
+ catch {execsql {DROP TABLE t1}}
+ execsql {
+ CREATE TABLE t1(log int, cnt int);
+ PRAGMA count_changes=off;
+ INSERT INTO t1
+ SELECT log, count(*) FROM d1 GROUP BY log
+ INTERSECT SELECT n-1,log FROM d1;
+ }
+} {}
+do_test insert2-1.3.2 {
+ execsql {
+ SELECT * FROM t1 ORDER BY log;
+ }
+} {1 1 2 2}
+do_test insert2-1.4 {
+ catch {execsql {DROP TABLE t1}}
+ set r [execsql {
+ CREATE TABLE t1(log int, cnt int);
+ CREATE INDEX i1 ON t1(log);
+ CREATE INDEX i2 ON t1(cnt);
+ INSERT INTO t1 SELECT log, count() FROM d1 GROUP BY log;
+ SELECT * FROM t1 ORDER BY log;
+ }]
+ lappend r [execsql {SELECT cnt FROM t1 WHERE log=3}]
+ lappend r [execsql {SELECT log FROM t1 WHERE cnt=4 ORDER BY log}]
+} {0 1 1 1 2 2 3 4 4 8 5 4 4 {3 5}}
+
+do_test insert2-2.0 {
+ execsql {
+ CREATE TABLE t3(a,b,c);
+ CREATE TABLE t4(x,y);
+ INSERT INTO t4 VALUES(1,2);
+ SELECT * FROM t4;
+ }
+} {1 2}
+do_test insert2-2.1 {
+ execsql {
+ INSERT INTO t3(a,c) SELECT * FROM t4;
+ SELECT * FROM t3;
+ }
+} {1 {} 2}
+do_test insert2-2.2 {
+ execsql {
+ DELETE FROM t3;
+ INSERT INTO t3(c,b) SELECT * FROM t4;
+ SELECT * FROM t3;
+ }
+} {{} 2 1}
+do_test insert2-2.3 {
+ execsql {
+ DELETE FROM t3;
+ INSERT INTO t3(c,a,b) SELECT x, 'hi', y FROM t4;
+ SELECT * FROM t3;
+ }
+} {hi 2 1}
+
+integrity_check insert2-3.0
+
+# File table t4 with lots of data
+#
+do_test insert2-3.1 {
+ execsql {
+ SELECT * from t4;
+ }
+} {1 2}
+do_test insert2-3.2 {
+ execsql {
+ BEGIN;
+ INSERT INTO t4 VALUES(2,4);
+ INSERT INTO t4 VALUES(3,6);
+ INSERT INTO t4 VALUES(4,8);
+ INSERT INTO t4 VALUES(5,10);
+ INSERT INTO t4 VALUES(6,12);
+ INSERT INTO t4 VALUES(7,14);
+ INSERT INTO t4 VALUES(8,16);
+ INSERT INTO t4 VALUES(9,18);
+ INSERT INTO t4 VALUES(10,20);
+ COMMIT;
+ }
+ db changes
+} {9}
+do_test insert2-3.2.1 {
+ execsql {
+ SELECT count(*) FROM t4;
+ }
+} {10}
+do_test insert2-3.3 {
+ execsql {
+ BEGIN;
+ INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
+ INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
+ INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
+ INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4;
+ COMMIT;
+ SELECT count(*) FROM t4;
+ }
+} {160}
+do_test insert2-3.4 {
+ execsql {
+ BEGIN;
+ UPDATE t4 SET y='lots of data for the row where x=' || x
+ || ' and y=' || y || ' - even more data to fill space';
+ COMMIT;
+ SELECT count(*) FROM t4;
+ }
+} {160}
+do_test insert2-3.5 {
+ execsql {
+ BEGIN;
+ INSERT INTO t4 SELECT x+(SELECT max(x)+1 FROM t4),y FROM t4;
+ SELECT count(*) from t4;
+ ROLLBACK;
+ }
+} {320}
+do_test insert2-3.6 {
+ execsql {
+ SELECT count(*) FROM t4;
+ }
+} {160}
+do_test insert2-3.7 {
+ execsql {
+ BEGIN;
+ DELETE FROM t4 WHERE x!=123;
+ SELECT count(*) FROM t4;
+ ROLLBACK;
+ }
+} {1}
+do_test insert2-3.8 {
+ db changes
+} {159}
+integrity_check insert2-3.9
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/interrupt.test b/usr/src/lib/libsqlite/test/interrupt.test
new file mode 100644
index 0000000000..d98ff2ae7e
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/interrupt.test
@@ -0,0 +1,170 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2004 Feb 8
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is the sqlite_interrupt() API.
+#
+# $Id: interrupt.test,v 1.4.2.1 2004/05/10 20:27:42 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Compute a checksum on the entire database.
+#
+proc cksum {{db db}} {
+ set txt [$db eval {SELECT name, type, sql FROM sqlite_master}]\n
+ foreach tbl [$db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
+ append txt [$db eval "SELECT * FROM $tbl"]\n
+ }
+ foreach prag {default_synchronous default_cache_size} {
+ append txt $prag-[$db eval "PRAGMA $prag"]\n
+ }
+ set cksum [string length $txt]-[md5 $txt]
+ # puts $cksum-[file size test.db]
+ return $cksum
+}
+
+# This routine attempts to execute the sql in $sql. It triggers an
+# interrupt a progressively later and later points during the processing
+# and checks to make sure SQLITE_INTERRUPT is returned. Eventually,
+# the routine completes successfully.
+#
+proc interrupt_test {testid sql result {initcnt 0} {maxcnt 1000000}} {
+ set orig_sum [cksum]
+ set i $initcnt
+ global sqlite_interrupt_count
+ while {$i<$maxcnt} {
+ incr i
+ set sqlite_interrupt_count $i
+ do_test $testid.$i.1 [format {
+ set ::r [catchsql %s]
+ set ::code [db errorcode]
+ expr {$::code==0 || $::code==9}
+ } [list $sql]] 1
+ if {$::code==9} {
+ do_test $testid.$i.2 {
+ cksum
+ } $orig_sum
+ } elseif {$sqlite_interrupt_count>0} {
+ do_test $testid.$i.99 {
+ set ::r
+ } [list 0 $result]
+ break
+ }
+ }
+ set sqlite_interrupt_count 0
+}
+
+do_test interrupt-1.1 {
+ execsql {
+ CREATE TABLE t1(a,b);
+ SELECT name FROM sqlite_master;
+ }
+} {t1}
+interrupt_test interrupt-1.2 {DROP TABLE t1} {} 1 14
+do_test interrupt-1.3 {
+ execsql {
+ SELECT name FROM sqlite_master;
+ }
+} {}
+integrity_check interrupt-1.4
+
+do_test interrrupt-2.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1 VALUES(1,randstr(300,400));
+ INSERT INTO t1 SELECT a+1, randstr(300,400) FROM t1;
+ INSERT INTO t1 SELECT a+2, a || '-' || b FROM t1;
+ INSERT INTO t1 SELECT a+4, a || '-' || b FROM t1;
+ INSERT INTO t1 SELECT a+8, a || '-' || b FROM t1;
+ INSERT INTO t1 SELECT a+16, a || '-' || b FROM t1;
+ INSERT INTO t1 SELECT a+32, a || '-' || b FROM t1;
+ COMMIT;
+ UPDATE t1 SET b=substr(b,-5,5);
+ SELECT count(*) from t1;
+ }
+} 64
+set origsize [file size test.db]
+set cksum [db eval {SELECT md5sum(a || b) FROM t1}]
+interrupt_test interrupt-2.2 {VACUUM} {} 100
+do_test interrupt-2.3 {
+ execsql {
+ SELECT md5sum(a || b) FROM t1;
+ }
+} $cksum
+do_test interrupt-2.4 {
+ expr {$::origsize>[file size test.db]}
+} 1
+integrity_check interrupt-2.5
+
+# Ticket #594. If an interrupt occurs in the middle of a transaction
+# and that transaction is later rolled back, the internal schema tables do
+# not reset.
+#
+for {set i 1} {$i<50} {incr i 5} {
+ do_test interrupt-3.$i.1 {
+ execsql {
+ BEGIN;
+ CREATE TEMP TABLE t2(x,y);
+ SELECT name FROM sqlite_temp_master;
+ }
+ } {t2}
+ do_test interrupt-3.$i.2 {
+ set ::sqlite_interrupt_count $::i
+ catchsql {
+ INSERT INTO t2 SELECT * FROM t1;
+ }
+ } {1 interrupted}
+ do_test interrupt-3.$i.3 {
+ execsql {
+ SELECT name FROM sqlite_temp_master;
+ }
+ } {t2}
+ do_test interrupt-3.$i.4 {
+ catchsql {
+ ROLLBACK
+ }
+ } {0 {}}
+ do_test interrupt-3.$i.5 {
+ catchsql {SELECT name FROM sqlite_temp_master};
+ execsql {
+ SELECT name FROM sqlite_temp_master;
+ }
+ } {}
+}
+
+# There are reports of a memory leak if an interrupt occurs during
+# the beginning of a complex query - before the first callback. We
+# will try to reproduce it here:
+#
+execsql {
+ CREATE TABLE t2(a,b,c);
+ INSERT INTO t2 SELECT round(a/10), randstr(50,80), randstr(50,60) FROM t1;
+}
+set sql {
+ SELECT max(min(b,c)), min(max(b,c)), a FROM t2 GROUP BY a ORDER BY a;
+}
+set sqlite_interrupt_count 1000000
+execsql $sql
+set max_count [expr {1000000-$sqlite_interrupt_count}]
+for {set i 1} {$i<$max_count-5} {incr i 1} {
+ do_test interrupt-4.$i.1 {
+ set ::sqlite_interrupt_count $::i
+ catchsql $sql
+ } {1 interrupted}
+}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/intpkey.test b/usr/src/lib/libsqlite/test/intpkey.test
new file mode 100644
index 0000000000..546ab8649a
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/intpkey.test
@@ -0,0 +1,490 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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.
+#
+# This file implements tests for the special processing associated
+# with INTEGER PRIMARY KEY columns.
+#
+# $Id: intpkey.test,v 1.14 2003/06/15 23:42:25 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a table with a primary key and a datatype other than
+# integer
+#
+do_test intpkey-1.0 {
+ execsql {
+ CREATE TABLE t1(a TEXT PRIMARY KEY, b, c);
+ }
+} {}
+
+# There should be an index associated with the primary key
+#
+do_test intpkey-1.1 {
+ execsql {
+ SELECT name FROM sqlite_master
+ WHERE type='index' AND tbl_name='t1';
+ }
+} {{(t1 autoindex 1)}}
+
+# Now create a table with an integer primary key and verify that
+# there is no associated index.
+#
+do_test intpkey-1.2 {
+ execsql {
+ DROP TABLE t1;
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
+ SELECT name FROM sqlite_master
+ WHERE type='index' AND tbl_name='t1';
+ }
+} {}
+
+# Insert some records into the new table. Specify the primary key
+# and verify that the key is used as the record number.
+#
+do_test intpkey-1.3 {
+ execsql {
+ INSERT INTO t1 VALUES(5,'hello','world');
+ }
+ db last_insert_rowid
+} {5}
+do_test intpkey-1.4 {
+ execsql {
+ SELECT * FROM t1;
+ }
+} {5 hello world}
+do_test intpkey-1.5 {
+ execsql {
+ SELECT rowid, * FROM t1;
+ }
+} {5 5 hello world}
+
+# Attempting to insert a duplicate primary key should give a constraint
+# failure.
+#
+do_test intpkey-1.6 {
+ set r [catch {execsql {
+ INSERT INTO t1 VALUES(5,'second','entry');
+ }} msg]
+ lappend r $msg
+} {1 {PRIMARY KEY must be unique}}
+do_test intpkey-1.7 {
+ execsql {
+ SELECT rowid, * FROM t1;
+ }
+} {5 5 hello world}
+do_test intpkey-1.8 {
+ set r [catch {execsql {
+ INSERT INTO t1 VALUES(6,'second','entry');
+ }} msg]
+ lappend r $msg
+} {0 {}}
+do_test intpkey-1.8.1 {
+ db last_insert_rowid
+} {6}
+do_test intpkey-1.9 {
+ execsql {
+ SELECT rowid, * FROM t1;
+ }
+} {5 5 hello world 6 6 second entry}
+
+# A ROWID is automatically generated for new records that do not specify
+# the integer primary key.
+#
+do_test intpkey-1.10 {
+ execsql {
+ INSERT INTO t1(b,c) VALUES('one','two');
+ SELECT b FROM t1 ORDER BY b;
+ }
+} {hello one second}
+
+# Try to change the ROWID for the new entry.
+#
+do_test intpkey-1.11 {
+ execsql {
+ UPDATE t1 SET a=4 WHERE b='one';
+ SELECT * FROM t1;
+ }
+} {4 one two 5 hello world 6 second entry}
+
+# Make sure SELECT statements are able to use the primary key column
+# as an index.
+#
+do_test intpkey-1.12 {
+ execsql {
+ SELECT * FROM t1 WHERE a==4;
+ }
+} {4 one two}
+
+# Try to insert a non-integer value into the primary key field. This
+# should result in a data type mismatch.
+#
+do_test intpkey-1.13.1 {
+ set r [catch {execsql {
+ INSERT INTO t1 VALUES('x','y','z');
+ }} msg]
+ lappend r $msg
+} {1 {datatype mismatch}}
+do_test intpkey-1.13.2 {
+ set r [catch {execsql {
+ INSERT INTO t1 VALUES('','y','z');
+ }} msg]
+ lappend r $msg
+} {1 {datatype mismatch}}
+do_test intpkey-1.14 {
+ set r [catch {execsql {
+ INSERT INTO t1 VALUES(3.4,'y','z');
+ }} msg]
+ lappend r $msg
+} {1 {datatype mismatch}}
+do_test intpkey-1.15 {
+ set r [catch {execsql {
+ INSERT INTO t1 VALUES(-3,'y','z');
+ }} msg]
+ lappend r $msg
+} {0 {}}
+do_test intpkey-1.16 {
+ execsql {SELECT * FROM t1}
+} {-3 y z 4 one two 5 hello world 6 second entry}
+
+#### INDICES
+# Check to make sure indices work correctly with integer primary keys
+#
+do_test intpkey-2.1 {
+ execsql {
+ CREATE INDEX i1 ON t1(b);
+ SELECT * FROM t1 WHERE b=='y'
+ }
+} {-3 y z}
+do_test intpkey-2.1.1 {
+ execsql {
+ SELECT * FROM t1 WHERE b=='y' AND rowid<0
+ }
+} {-3 y z}
+do_test intpkey-2.1.2 {
+ execsql {
+ SELECT * FROM t1 WHERE b=='y' AND rowid<0 AND rowid>=-20
+ }
+} {-3 y z}
+do_test intpkey-2.1.3 {
+ execsql {
+ SELECT * FROM t1 WHERE b>='y'
+ }
+} {-3 y z}
+do_test intpkey-2.1.4 {
+ execsql {
+ SELECT * FROM t1 WHERE b>='y' AND rowid<10
+ }
+} {-3 y z}
+
+do_test intpkey-2.2 {
+ execsql {
+ UPDATE t1 SET a=8 WHERE b=='y';
+ SELECT * FROM t1 WHERE b=='y';
+ }
+} {8 y z}
+do_test intpkey-2.3 {
+ execsql {
+ SELECT rowid, * FROM t1;
+ }
+} {4 4 one two 5 5 hello world 6 6 second entry 8 8 y z}
+do_test intpkey-2.4 {
+ execsql {
+ SELECT rowid, * FROM t1 WHERE b<'second'
+ }
+} {5 5 hello world 4 4 one two}
+do_test intpkey-2.4.1 {
+ execsql {
+ SELECT rowid, * FROM t1 WHERE 'second'>b
+ }
+} {5 5 hello world 4 4 one two}
+do_test intpkey-2.4.2 {
+ execsql {
+ SELECT rowid, * FROM t1 WHERE 8>rowid AND 'second'>b
+ }
+} {4 4 one two 5 5 hello world}
+do_test intpkey-2.4.3 {
+ execsql {
+ SELECT rowid, * FROM t1 WHERE 8>rowid AND 'second'>b AND 0<rowid
+ }
+} {4 4 one two 5 5 hello world}
+do_test intpkey-2.5 {
+ execsql {
+ SELECT rowid, * FROM t1 WHERE b>'a'
+ }
+} {5 5 hello world 4 4 one two 6 6 second entry 8 8 y z}
+do_test intpkey-2.6 {
+ execsql {
+ DELETE FROM t1 WHERE rowid=4;
+ SELECT * FROM t1 WHERE b>'a';
+ }
+} {5 hello world 6 second entry 8 y z}
+do_test intpkey-2.7 {
+ execsql {
+ UPDATE t1 SET a=-4 WHERE rowid=8;
+ SELECT * FROM t1 WHERE b>'a';
+ }
+} {5 hello world 6 second entry -4 y z}
+do_test intpkey-2.7 {
+ execsql {
+ SELECT * FROM t1
+ }
+} {-4 y z 5 hello world 6 second entry}
+
+# Do an SQL statement. Append the search count to the end of the result.
+#
+proc count sql {
+ set ::sqlite_search_count 0
+ return [concat [execsql $sql] $::sqlite_search_count]
+}
+
+# Create indices that include the integer primary key as one of their
+# columns.
+#
+do_test intpkey-3.1 {
+ execsql {
+ CREATE INDEX i2 ON t1(a);
+ }
+} {}
+do_test intpkey-3.2 {
+ count {
+ SELECT * FROM t1 WHERE a=5;
+ }
+} {5 hello world 0}
+do_test intpkey-3.3 {
+ count {
+ SELECT * FROM t1 WHERE a>4 AND a<6;
+ }
+} {5 hello world 2}
+do_test intpkey-3.4 {
+ count {
+ SELECT * FROM t1 WHERE b>='hello' AND b<'hello2';
+ }
+} {5 hello world 3}
+do_test intpkey-3.5 {
+ execsql {
+ CREATE INDEX i3 ON t1(c,a);
+ }
+} {}
+do_test intpkey-3.6 {
+ count {
+ SELECT * FROM t1 WHERE c=='world';
+ }
+} {5 hello world 3}
+do_test intpkey-3.7 {
+ execsql {INSERT INTO t1 VALUES(11,'hello','world')}
+ count {
+ SELECT * FROM t1 WHERE c=='world';
+ }
+} {5 hello world 11 hello world 5}
+do_test intpkey-3.8 {
+ count {
+ SELECT * FROM t1 WHERE c=='world' AND a>7;
+ }
+} {11 hello world 5}
+do_test intpkey-3.9 {
+ count {
+ SELECT * FROM t1 WHERE 7<a;
+ }
+} {11 hello world 1}
+
+# Test inequality constraints on integer primary keys and rowids
+#
+do_test intpkey-4.1 {
+ count {
+ SELECT * FROM t1 WHERE 11=rowid
+ }
+} {11 hello world 0}
+do_test intpkey-4.2 {
+ count {
+ SELECT * FROM t1 WHERE 11=rowid AND b=='hello'
+ }
+} {11 hello world 0}
+do_test intpkey-4.3 {
+ count {
+ SELECT * FROM t1 WHERE 11=rowid AND b=='hello' AND c IS NOT NULL;
+ }
+} {11 hello world 0}
+do_test intpkey-4.4 {
+ count {
+ SELECT * FROM t1 WHERE rowid==11
+ }
+} {11 hello world 0}
+do_test intpkey-4.5 {
+ count {
+ SELECT * FROM t1 WHERE oid==11 AND b=='hello'
+ }
+} {11 hello world 0}
+do_test intpkey-4.6 {
+ count {
+ SELECT * FROM t1 WHERE a==11 AND b=='hello' AND c IS NOT NULL;
+ }
+} {11 hello world 0}
+
+do_test intpkey-4.7 {
+ count {
+ SELECT * FROM t1 WHERE 8<rowid;
+ }
+} {11 hello world 1}
+do_test intpkey-4.8 {
+ count {
+ SELECT * FROM t1 WHERE 8<rowid AND 11>=oid;
+ }
+} {11 hello world 1}
+do_test intpkey-4.9 {
+ count {
+ SELECT * FROM t1 WHERE 11<=_rowid_ AND 12>=a;
+ }
+} {11 hello world 1}
+do_test intpkey-4.10 {
+ count {
+ SELECT * FROM t1 WHERE 0>=_rowid_;
+ }
+} {-4 y z 1}
+do_test intpkey-4.11 {
+ count {
+ SELECT * FROM t1 WHERE a<0;
+ }
+} {-4 y z 1}
+do_test intpkey-4.12 {
+ count {
+ SELECT * FROM t1 WHERE a<0 AND a>10;
+ }
+} {1}
+
+# Make sure it is OK to insert a rowid of 0
+#
+do_test intpkey-5.1 {
+ execsql {
+ INSERT INTO t1 VALUES(0,'zero','entry');
+ }
+ count {
+ SELECT * FROM t1 WHERE a=0;
+ }
+} {0 zero entry 0}
+do_test intpkey=5.2 {
+ execsql {
+ SELECT rowid, a FROM t1
+ }
+} {-4 -4 0 0 5 5 6 6 11 11}
+
+# Test the ability of the COPY command to put data into a
+# table that contains an integer primary key.
+#
+do_test intpkey-6.1 {
+ set f [open ./data1.txt w]
+ puts $f "20\tb-20\tc-20"
+ puts $f "21\tb-21\tc-21"
+ puts $f "22\tb-22\tc-22"
+ close $f
+ execsql {
+ COPY t1 FROM 'data1.txt';
+ SELECT * FROM t1 WHERE a>=20;
+ }
+} {20 b-20 c-20 21 b-21 c-21 22 b-22 c-22}
+do_test intpkey-6.2 {
+ execsql {
+ SELECT * FROM t1 WHERE b=='hello'
+ }
+} {5 hello world 11 hello world}
+do_test intpkey-6.3 {
+ execsql {
+ DELETE FROM t1 WHERE b='b-21';
+ SELECT * FROM t1 WHERE b=='b-21';
+ }
+} {}
+do_test intpkey-6.4 {
+ execsql {
+ SELECT * FROM t1 WHERE a>=20
+ }
+} {20 b-20 c-20 22 b-22 c-22}
+
+# Do an insert of values with the columns specified out of order.
+#
+do_test intpkey-7.1 {
+ execsql {
+ INSERT INTO t1(c,b,a) VALUES('row','new',30);
+ SELECT * FROM t1 WHERE rowid>=30;
+ }
+} {30 new row}
+do_test intpkey-7.2 {
+ execsql {
+ SELECT * FROM t1 WHERE rowid>20;
+ }
+} {22 b-22 c-22 30 new row}
+
+# Do an insert from a select statement.
+#
+do_test intpkey-8.1 {
+ execsql {
+ CREATE TABLE t2(x INTEGER PRIMARY KEY, y, z);
+ INSERT INTO t2 SELECT * FROM t1;
+ SELECT rowid FROM t2;
+ }
+} {-4 0 5 6 11 20 22 30}
+do_test intpkey-8.2 {
+ execsql {
+ SELECT x FROM t2;
+ }
+} {-4 0 5 6 11 20 22 30}
+
+do_test intpkey-9.1 {
+ execsql {
+ UPDATE t1 SET c='www' WHERE c='world';
+ SELECT rowid, a, c FROM t1 WHERE c=='www';
+ }
+} {5 5 www 11 11 www}
+
+
+# Check insert of NULL for primary key
+#
+do_test intpkey-10.1 {
+ execsql {
+ DROP TABLE t2;
+ CREATE TABLE t2(x INTEGER PRIMARY KEY, y, z);
+ INSERT INTO t2 VALUES(NULL, 1, 2);
+ SELECT * from t2;
+ }
+} {1 1 2}
+do_test intpkey-10.2 {
+ execsql {
+ INSERT INTO t2 VALUES(NULL, 2, 3);
+ SELECT * from t2 WHERE x=2;
+ }
+} {2 2 3}
+do_test intpkey-10.3 {
+ execsql {
+ INSERT INTO t2 SELECT NULL, z, y FROM t2;
+ SELECT * FROM t2;
+ }
+} {1 1 2 2 2 3 3 2 1 4 3 2}
+
+# This tests checks to see if a floating point number can be used
+# to reference an integer primary key.
+#
+do_test intpkey-11.1 {
+ execsql {
+ SELECT b FROM t1 WHERE a=2.0+3.0;
+ }
+} {hello}
+do_test intpkey-11.1 {
+ execsql {
+ SELECT b FROM t1 WHERE a=2.0+3.5;
+ }
+} {}
+
+integrity_check intpkey-12.1
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/ioerr.test b/usr/src/lib/libsqlite/test/ioerr.test
new file mode 100644
index 0000000000..d7539bc209
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/ioerr.test
@@ -0,0 +1,123 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 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.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing for correct handling of I/O errors
+# such as writes failing because the disk is full.
+#
+# The tests in this file use special facilities that are only
+# available in the SQLite test fixture.
+#
+# $Id: ioerr.test,v 1.3 2003/04/25 15:37:59 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+set ::go 1
+for {set n 1} {$go} {incr n} {
+ do_test ioerr-1.$n.1 {
+ set ::sqlite_io_error_pending 0
+ db close
+ catch {file delete -force test.db}
+ catch {file delete -force test.db-journal}
+ sqlite db test.db
+ execsql {SELECT * FROM sqlite_master}
+ } {}
+ do_test ioerr-1.$n.2 [subst {
+ set ::sqlite_io_error_pending $n
+ }] $n
+ do_test ioerr-1.$n.3 {
+ set r [catch {db eval {
+ CREATE TABLE t1(a,b,c);
+ SELECT * FROM sqlite_master;
+ BEGIN TRANSACTION;
+ INSERT INTO t1 VALUES(1,2,3);
+ INSERT INTO t1 VALUES(4,5,6);
+ ROLLBACK;
+ SELECT * FROM t1;
+ BEGIN TRANSACTION;
+ INSERT INTO t1 VALUES(1,2,3);
+ INSERT INTO t1 VALUES(4,5,6);
+ COMMIT;
+ SELECT * FROM t1;
+ DELETE FROM t1 WHERE a<100;
+ }} msg]
+ # if {$r} {puts $msg}
+ set ::go [expr {$::sqlite_io_error_pending<=0}]
+ expr {$::sqlite_io_error_pending>0 || $r!=0}
+ } {1}
+}
+set ::sqlite_io_error_pending 0
+
+proc cksum {{db db}} {
+ set txt [$db eval {SELECT name, type, sql FROM sqlite_master}]\n
+ foreach tbl [$db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
+ append txt [$db eval "SELECT * FROM $tbl"]\n
+ }
+ foreach prag {default_synchronous default_cache_size} {
+ append txt $prag-[$db eval "PRAGMA $prag"]\n
+ }
+ set cksum [string length $txt]-[md5 $txt]
+ # puts $cksum-[file size test.db]
+ return $cksum
+}
+
+set ::go 1
+for {set n 1} {$go} {incr n} {
+ do_test ioerr-2.$n.1 {
+ set ::sqlite_io_error_pending 0
+ db close
+ catch {file delete -force test.db}
+ catch {file delete -force test.db-journal}
+ sqlite db test.db
+ execsql {
+ BEGIN;
+ CREATE TABLE t1(a, b, c);
+ INSERT INTO t1 VALUES(1, randstr(5,50), randstr(5,50));
+ INSERT INTO t1 SELECT a+2, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT a+4, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT a+8, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT a+16, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT a+32, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT a+64, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT a+128, b||'-'||rowid, c||'-'||rowid FROM t1;
+ CREATE TABLE t2 AS SELECT * FROM t1;
+ CREATE TABLE t3 AS SELECT * FROM t1;
+ COMMIT;
+ DROP TABLE t2;
+ }
+ set ::cksum [cksum]
+ execsql {
+ SELECT name FROM sqlite_master WHERE type='table'
+ }
+ } {t1 t3}
+ do_test ioerr-2.$n.2 [subst {
+ set ::sqlite_io_error_pending $n
+ }] $n
+ do_test ioerr-2.$n.3 {
+ set r [catch {db eval {
+ VACUUM;
+ }} msg]
+ # puts "error_pending=$::sqlite_io_error_pending"
+ # if {$r} {puts $msg}
+ set ::go [expr {$::sqlite_io_error_pending<=0}]
+ expr {$::sqlite_io_error_pending>0 || $r!=0}
+ set ::sqlite_io_error_pending 0
+ db close
+ sqlite db test.db
+ cksum
+ } $cksum
+}
+set ::sqlite_io_error_pending 0
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/join.test b/usr/src/lib/libsqlite/test/join.test
new file mode 100644
index 0000000000..990a623e54
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/join.test
@@ -0,0 +1,396 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 May 24
+#
+# 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.
+#
+# This file implements tests for joins, including outer joins.
+#
+# $Id: join.test,v 1.11 2003/09/27 13:39:40 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test join-1.1 {
+ execsql {
+ CREATE TABLE t1(a,b,c);
+ INSERT INTO t1 VALUES(1,2,3);
+ INSERT INTO t1 VALUES(2,3,4);
+ INSERT INTO t1 VALUES(3,4,5);
+ SELECT * FROM t1;
+ }
+} {1 2 3 2 3 4 3 4 5}
+do_test join-1.2 {
+ execsql {
+ CREATE TABLE t2(b,c,d);
+ INSERT INTO t2 VALUES(1,2,3);
+ INSERT INTO t2 VALUES(2,3,4);
+ INSERT INTO t2 VALUES(3,4,5);
+ SELECT * FROM t2;
+ }
+} {1 2 3 2 3 4 3 4 5}
+
+do_test join-1.3 {
+ execsql2 {
+ SELECT * FROM t1 NATURAL JOIN t2;
+ }
+} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5}
+do_test join-1.3.1 {
+ execsql2 {
+ SELECT * FROM t2 NATURAL JOIN t1;
+ }
+} {t2.b 2 t2.c 3 t2.d 4 t1.a 1 t2.b 3 t2.c 4 t2.d 5 t1.a 2}
+do_test join-1.4 {
+ execsql2 {
+ SELECT * FROM t1 INNER JOIN t2 USING(b,c);
+ }
+} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5}
+do_test join-1.5 {
+ execsql2 {
+ SELECT * FROM t1 INNER JOIN t2 USING(b);
+ }
+} {t1.a 1 t1.b 2 t1.c 3 t2.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.c 4 t2.d 5}
+do_test join-1.6 {
+ execsql2 {
+ SELECT * FROM t1 INNER JOIN t2 USING(c);
+ }
+} {t1.a 1 t1.b 2 t1.c 3 t2.b 2 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.b 3 t2.d 5}
+do_test join-1.7 {
+ execsql2 {
+ SELECT * FROM t1 INNER JOIN t2 USING(c,b);
+ }
+} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5}
+
+do_test join-1.8 {
+ execsql {
+ SELECT * FROM t1 NATURAL CROSS JOIN t2;
+ }
+} {1 2 3 4 2 3 4 5}
+do_test join-1.9 {
+ execsql {
+ SELECT * FROM t1 CROSS JOIN t2 USING(b,c);
+ }
+} {1 2 3 4 2 3 4 5}
+do_test join-1.10 {
+ execsql {
+ SELECT * FROM t1 NATURAL INNER JOIN t2;
+ }
+} {1 2 3 4 2 3 4 5}
+do_test join-1.11 {
+ execsql {
+ SELECT * FROM t1 INNER JOIN t2 USING(b,c);
+ }
+} {1 2 3 4 2 3 4 5}
+do_test join-1.12 {
+ execsql {
+ SELECT * FROM t1 natural inner join t2;
+ }
+} {1 2 3 4 2 3 4 5}
+do_test join-1.13 {
+ execsql2 {
+ SELECT * FROM t1 NATURAL JOIN
+ (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as t3
+ }
+} {t1.a 1 t1.b 2 t1.c 3 t3.d 4 t3.e 5}
+do_test join-1.14 {
+ execsql2 {
+ SELECT * FROM (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as 'tx'
+ NATURAL JOIN t1
+ }
+} {tx.c 3 tx.d 4 tx.e 5 t1.a 1 t1.b 2}
+
+do_test join-1.15 {
+ execsql {
+ CREATE TABLE t3(c,d,e);
+ INSERT INTO t3 VALUES(2,3,4);
+ INSERT INTO t3 VALUES(3,4,5);
+ INSERT INTO t3 VALUES(4,5,6);
+ SELECT * FROM t3;
+ }
+} {2 3 4 3 4 5 4 5 6}
+do_test join-1.16 {
+ execsql {
+ SELECT * FROM t1 natural join t2 natural join t3;
+ }
+} {1 2 3 4 5 2 3 4 5 6}
+do_test join-1.17 {
+ execsql2 {
+ SELECT * FROM t1 natural join t2 natural join t3;
+ }
+} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t3.e 5 t1.a 2 t1.b 3 t1.c 4 t2.d 5 t3.e 6}
+do_test join-1.18 {
+ execsql {
+ CREATE TABLE t4(d,e,f);
+ INSERT INTO t4 VALUES(2,3,4);
+ INSERT INTO t4 VALUES(3,4,5);
+ INSERT INTO t4 VALUES(4,5,6);
+ SELECT * FROM t4;
+ }
+} {2 3 4 3 4 5 4 5 6}
+do_test join-1.19 {
+ execsql {
+ SELECT * FROM t1 natural join t2 natural join t4;
+ }
+} {1 2 3 4 5 6}
+do_test join-1.19 {
+ execsql2 {
+ SELECT * FROM t1 natural join t2 natural join t4;
+ }
+} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t4.e 5 t4.f 6}
+do_test join-1.20 {
+ execsql {
+ SELECT * FROM t1 natural join t2 natural join t3 WHERE t1.a=1
+ }
+} {1 2 3 4 5}
+
+do_test join-2.1 {
+ execsql {
+ SELECT * FROM t1 NATURAL LEFT JOIN t2;
+ }
+} {1 2 3 4 2 3 4 5 3 4 5 {}}
+do_test join-2.2 {
+ execsql {
+ SELECT * FROM t2 NATURAL LEFT OUTER JOIN t1;
+ }
+} {1 2 3 {} 2 3 4 1 3 4 5 2}
+do_test join-2.3 {
+ catchsql {
+ SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
+ }
+} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
+do_test join-2.4 {
+ execsql {
+ SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d
+ }
+} {1 2 3 {} {} {} 2 3 4 {} {} {} 3 4 5 1 2 3}
+do_test join-2.5 {
+ execsql {
+ SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d WHERE t1.a>1
+ }
+} {2 3 4 {} {} {} 3 4 5 1 2 3}
+do_test join-2.6 {
+ execsql {
+ SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d WHERE t2.b IS NULL OR t2.b>1
+ }
+} {1 2 3 {} {} {} 2 3 4 {} {} {}}
+
+do_test join-3.1 {
+ catchsql {
+ SELECT * FROM t1 NATURAL JOIN t2 ON t1.a=t2.b;
+ }
+} {1 {a NATURAL join may not have an ON or USING clause}}
+do_test join-3.2 {
+ catchsql {
+ SELECT * FROM t1 NATURAL JOIN t2 USING(b);
+ }
+} {1 {a NATURAL join may not have an ON or USING clause}}
+do_test join-3.3 {
+ catchsql {
+ SELECT * FROM t1 JOIN t2 ON t1.a=t2.b USING(b);
+ }
+} {1 {cannot have both ON and USING clauses in the same join}}
+do_test join-3.4 {
+ catchsql {
+ SELECT * FROM t1 JOIN t2 USING(a);
+ }
+} {1 {cannot join using column a - column not present in both tables}}
+do_test join-3.5 {
+ catchsql {
+ SELECT * FROM t1 USING(a);
+ }
+} {0 {1 2 3 2 3 4 3 4 5}}
+do_test join-3.6 {
+ catchsql {
+ SELECT * FROM t1 JOIN t2 ON t3.a=t2.b;
+ }
+} {1 {no such column: t3.a}}
+do_test join-3.7 {
+ catchsql {
+ SELECT * FROM t1 INNER OUTER JOIN t2;
+ }
+} {1 {unknown or unsupported join type: INNER OUTER}}
+do_test join-3.7 {
+ catchsql {
+ SELECT * FROM t1 LEFT BOGUS JOIN t2;
+ }
+} {1 {unknown or unsupported join type: LEFT BOGUS}}
+
+do_test join-4.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t5(a INTEGER PRIMARY KEY);
+ CREATE TABLE t6(a INTEGER);
+ INSERT INTO t6 VALUES(NULL);
+ INSERT INTO t6 VALUES(NULL);
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ COMMIT;
+ }
+ execsql {
+ SELECT * FROM t6 NATURAL JOIN t5;
+ }
+} {}
+do_test join-4.2 {
+ execsql {
+ SELECT * FROM t6, t5 WHERE t6.a<t5.a;
+ }
+} {}
+do_test join-4.3 {
+ execsql {
+ SELECT * FROM t6, t5 WHERE t6.a>t5.a;
+ }
+} {}
+do_test join-4.4 {
+ execsql {
+ UPDATE t6 SET a='xyz';
+ SELECT * FROM t6 NATURAL JOIN t5;
+ }
+} {}
+do_test join-4.6 {
+ execsql {
+ SELECT * FROM t6, t5 WHERE t6.a<t5.a;
+ }
+} {}
+do_test join-4.7 {
+ execsql {
+ SELECT * FROM t6, t5 WHERE t6.a>t5.a;
+ }
+} {}
+do_test join-4.8 {
+ execsql {
+ UPDATE t6 SET a=1;
+ SELECT * FROM t6 NATURAL JOIN t5;
+ }
+} {}
+do_test join-4.9 {
+ execsql {
+ SELECT * FROM t6, t5 WHERE t6.a<t5.a;
+ }
+} {}
+do_test join-4.10 {
+ execsql {
+ SELECT * FROM t6, t5 WHERE t6.a>t5.a;
+ }
+} {}
+
+do_test join-5.1 {
+ execsql {
+ BEGIN;
+ create table centros (id integer primary key, centro);
+ INSERT INTO centros VALUES(1,'xxx');
+ create table usuarios (id integer primary key, nombre, apellidos,
+ idcentro integer);
+ INSERT INTO usuarios VALUES(1,'a','aa',1);
+ INSERT INTO usuarios VALUES(2,'b','bb',1);
+ INSERT INTO usuarios VALUES(3,'c','cc',NULL);
+ create index idcentro on usuarios (idcentro);
+ END;
+ select usuarios.id, usuarios.nombre, centros.centro from
+ usuarios left outer join centros on usuarios.idcentro = centros.id;
+ }
+} {1 a xxx 2 b xxx 3 c {}}
+
+# A test for ticket #247.
+#
+do_test join-7.1 {
+ execsql {
+ CREATE TABLE t7 (x, y);
+ INSERT INTO t7 VALUES ("pa1", 1);
+ INSERT INTO t7 VALUES ("pa2", NULL);
+ INSERT INTO t7 VALUES ("pa3", NULL);
+ INSERT INTO t7 VALUES ("pa4", 2);
+ INSERT INTO t7 VALUES ("pa30", 131);
+ INSERT INTO t7 VALUES ("pa31", 130);
+ INSERT INTO t7 VALUES ("pa28", NULL);
+
+ CREATE TABLE t8 (a integer primary key, b);
+ INSERT INTO t8 VALUES (1, "pa1");
+ INSERT INTO t8 VALUES (2, "pa4");
+ INSERT INTO t8 VALUES (3, NULL);
+ INSERT INTO t8 VALUES (4, NULL);
+ INSERT INTO t8 VALUES (130, "pa31");
+ INSERT INTO t8 VALUES (131, "pa30");
+
+ SELECT coalesce(t8.a,999) from t7 LEFT JOIN t8 on y=a;
+ }
+} {1 999 999 2 131 130 999}
+
+# Make sure a left join where the right table is really a view that
+# is itself a join works right. Ticket #306.
+#
+do_test join-8.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t9(a INTEGER PRIMARY KEY, b);
+ INSERT INTO t9 VALUES(1,11);
+ INSERT INTO t9 VALUES(2,22);
+ CREATE TABLE t10(x INTEGER PRIMARY KEY, y);
+ INSERT INTO t10 VALUES(1,2);
+ INSERT INTO t10 VALUES(3,3);
+ CREATE TABLE t11(p INTEGER PRIMARY KEY, q);
+ INSERT INTO t11 VALUES(2,111);
+ INSERT INTO t11 VALUES(3,333);
+ CREATE VIEW v10_11 AS SELECT x, q FROM t10, t11 WHERE t10.y=t11.p;
+ COMMIT;
+ SELECT * FROM t9 LEFT JOIN v10_11 ON( a=x );
+ }
+} {1 11 1 111 2 22 {} {}}
+do_test join-8.2 {
+ execsql {
+ SELECT * FROM t9 LEFT JOIN (SELECT x, q FROM t10, t11 WHERE t10.y=t11.p)
+ ON( a=x);
+ }
+} {1 11 1 111 2 22 {} {}}
+do_test join-8.3 {
+ execsql {
+ SELECT * FROM v10_11 LEFT JOIN t9 ON( a=x );
+ }
+} {1 111 1 11 3 333 {} {}}
+
+# Ticket #350 describes a scenario where LEFT OUTER JOIN does not
+# function correctly if the right table in the join is really
+# subquery.
+#
+# To test the problem, we generate the same LEFT OUTER JOIN in two
+# separate selects but with on using a subquery and the other calling
+# the table directly. Then connect the two SELECTs using an EXCEPT.
+# Both queries should generate the same results so the answer should
+# be an empty set.
+#
+do_test join-9.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t12(a,b);
+ INSERT INTO t12 VALUES(1,11);
+ INSERT INTO t12 VALUES(2,22);
+ CREATE TABLE t13(b,c);
+ INSERT INTO t13 VALUES(22,222);
+ COMMIT;
+ SELECT * FROM t12 NATURAL LEFT JOIN t13
+ EXCEPT
+ SELECT * FROM t12 NATURAL LEFT JOIN (SELECT * FROM t13 WHERE b>0);
+ }
+} {}
+do_test join-9.2 {
+ execsql {
+ CREATE VIEW v13 AS SELECT * FROM t13 WHERE b>0;
+ SELECT * FROM t12 NATURAL LEFT JOIN t13
+ EXCEPT
+ SELECT * FROM t12 NATURAL LEFT JOIN v13;
+ }
+} {}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/join2.test b/usr/src/lib/libsqlite/test/join2.test
new file mode 100644
index 0000000000..493e1a8613
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/join2.test
@@ -0,0 +1,76 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 May 24
+#
+# 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.
+#
+# This file implements tests for joins, including outer joins.
+#
+# $Id: join2.test,v 1.1 2004/01/24 20:18:13 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test join2-1.1 {
+ execsql {
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1 VALUES(1,11);
+ INSERT INTO t1 VALUES(2,22);
+ INSERT INTO t1 VALUES(3,33);
+ SELECT * FROM t1;
+ }
+} {1 11 2 22 3 33}
+do_test join2-1.2 {
+ execsql {
+ CREATE TABLE t2(b,c);
+ INSERT INTO t2 VALUES(11,111);
+ INSERT INTO t2 VALUES(33,333);
+ INSERT INTO t2 VALUES(44,444);
+ SELECT * FROM t2;
+ }
+} {11 111 33 333 44 444};
+do_test join2-1.3 {
+ execsql {
+ CREATE TABLE t3(c,d);
+ INSERT INTO t3 VALUES(111,1111);
+ INSERT INTO t3 VALUES(444,4444);
+ INSERT INTO t3 VALUES(555,5555);
+ SELECT * FROM t3;
+ }
+} {111 1111 444 4444 555 5555}
+
+do_test join2-1.4 {
+ execsql {
+ SELECT * FROM
+ t1 NATURAL JOIN t2 NATURAL JOIN t3
+ }
+} {1 11 111 1111}
+do_test join2-1.5 {
+ execsql {
+ SELECT * FROM
+ t1 NATURAL JOIN t2 NATURAL LEFT OUTER JOIN t3
+ }
+} {1 11 111 1111 3 33 333 {}}
+do_test join2-1.6 {
+ execsql {
+ SELECT * FROM
+ t1 NATURAL LEFT OUTER JOIN t2 NATURAL JOIN t3
+ }
+} {1 11 111 1111}
+do_test join2-1.6 {
+ execsql {
+ SELECT * FROM
+ t1 NATURAL LEFT OUTER JOIN (t2 NATURAL JOIN t3)
+ }
+} {1 11 111 1111 2 22 {} {} 3 33 {} {}}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/join3_28.test b/usr/src/lib/libsqlite/test/join3_28.test
new file mode 100644
index 0000000000..5ddbb8a1d5
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/join3_28.test
@@ -0,0 +1,37 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 May 24
+#
+# 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.
+#
+# This file implements tests for joins, including outer joins, where
+# there are a large number of tables involved in the join.
+#
+# $Id: join3_28.test,v 1.1.2.1 2004/07/22 16:08:39 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+catch {unset result}
+set result {}
+for {set N 1} {$N<=40} {incr N} {
+ lappend result $N
+ do_test join3-1.$N {
+ execsql "CREATE TABLE t${N}(x);"
+ execsql "INSERT INTO t$N VALUES($N)"
+ set sql "SELECT * FROM t1"
+ for {set i 2} {$i<=$N} {incr i} {append sql ", t$i"}
+ execsql $sql
+ } $result
+}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/join4_28.test b/usr/src/lib/libsqlite/test/join4_28.test
new file mode 100644
index 0000000000..189a44af32
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/join4_28.test
@@ -0,0 +1,80 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 May 24
+#
+# 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.
+#
+# This file implements tests for left outer joins containing WHERE
+# clauses that restrict the scope of the left term of the join.
+#
+# $Id: join4_28.test,v 1.1.2.1 2004/07/22 16:08:39 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test join4-1.1 {
+ execsql {
+ create temp table t1(a integer, b varchar(10));
+ insert into t1 values(1,'one');
+ insert into t1 values(2,'two');
+ insert into t1 values(3,'three');
+ insert into t1 values(4,'four');
+
+ create temp table t2(x integer, y varchar(10), z varchar(10));
+ insert into t2 values(2,'niban','ok');
+ insert into t2 values(4,'yonban','err');
+ }
+ execsql {
+ select * from t1 left outer join t2 on t1.a=t2.x where t2.z='ok'
+ }
+} {2 two 2 niban ok}
+do_test join4-1.2 {
+ execsql {
+ select * from t1 left outer join t2 on t1.a=t2.x and t2.z='ok'
+ }
+} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
+do_test join4-1.3 {
+ execsql {
+ create index i2 on t2(z);
+ }
+ execsql {
+ select * from t1 left outer join t2 on t1.a=t2.x where t2.z='ok'
+ }
+} {2 two 2 niban ok}
+do_test join4-1.4 {
+ execsql {
+ select * from t1 left outer join t2 on t1.a=t2.x and t2.z='ok'
+ }
+} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
+do_test join4-1.5 {
+ execsql {
+ select * from t1 left outer join t2 on t1.a=t2.x where t2.z>='ok'
+ }
+} {2 two 2 niban ok}
+do_test join4-1.4 {
+ execsql {
+ select * from t1 left outer join t2 on t1.a=t2.x and t2.z>='ok'
+ }
+} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
+do_test join4-1.6 {
+ execsql {
+ select * from t1 left outer join t2 on t1.a=t2.x where t2.z IN ('ok')
+ }
+} {2 two 2 niban ok}
+do_test join4-1.7 {
+ execsql {
+ select * from t1 left outer join t2 on t1.a=t2.x and t2.z IN ('ok')
+ }
+} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/lastinsert.test b/usr/src/lib/libsqlite/test/lastinsert.test
new file mode 100644
index 0000000000..8137d1763b
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/lastinsert.test
@@ -0,0 +1,322 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 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.
+#
+#***********************************************************************
+#
+# Tests to make sure that value returned by last_insert_rowid() (LIRID)
+# is updated properly, especially inside triggers
+#
+# Note 1: insert into table is now the only statement which changes LIRID
+# Note 2: upon entry into before or instead of triggers,
+# LIRID is unchanged (rather than -1)
+# Note 3: LIRID is changed within the context of a trigger,
+# but is restored once the trigger exits
+# Note 4: LIRID is not changed by an insert into a view (since everything
+# is done within instead of trigger context)
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# ----------------------------------------------------------------------------
+# 1.x - basic tests (no triggers)
+
+# LIRID changed properly after an insert into a table
+do_test lastinsert-1.1 {
+ catchsql {
+ create table t1 (k integer primary key);
+ insert into t1 values (1);
+ insert into t1 values (NULL);
+ insert into t1 values (NULL);
+ select last_insert_rowid();
+ }
+} {0 3}
+
+# LIRID unchanged after an update on a table
+do_test lastinsert-1.2 {
+ catchsql {
+ update t1 set k=4 where k=2;
+ select last_insert_rowid();
+ }
+} {0 3}
+
+# LIRID unchanged after a delete from a table
+do_test lastinsert-1.3 {
+ catchsql {
+ delete from t1 where k=4;
+ select last_insert_rowid();
+ }
+} {0 3}
+
+# LIRID unchanged after create table/view statements
+do_test lastinsert-1.4 {
+ catchsql {
+ create table t2 (k integer primary key, val1, val2, val3);
+ create view v as select * from t1;
+ select last_insert_rowid();
+ }
+} {0 3}
+
+# ----------------------------------------------------------------------------
+# 2.x - tests with after insert trigger
+
+# LIRID changed properly after an insert into table containing an after trigger
+do_test lastinsert-2.1 {
+ catchsql {
+ delete from t2;
+ create trigger r1 after insert on t1 for each row begin
+ insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
+ update t2 set k=k+10, val2=100+last_insert_rowid();
+ update t2 set val3=1000+last_insert_rowid();
+ end;
+ insert into t1 values (13);
+ select last_insert_rowid();
+ }
+} {0 13}
+
+# LIRID equals NEW.k upon entry into after insert trigger
+do_test lastinsert-2.2 {
+ catchsql {
+ select val1 from t2;
+ }
+} {0 13}
+
+# LIRID changed properly by insert within context of after insert trigger
+do_test lastinsert-2.3 {
+ catchsql {
+ select val2 from t2;
+ }
+} {0 126}
+
+# LIRID unchanged by update within context of after insert trigger
+do_test lastinsert-2.4 {
+ catchsql {
+ select val3 from t2;
+ }
+} {0 1026}
+
+# ----------------------------------------------------------------------------
+# 3.x - tests with after update trigger
+
+# LIRID not changed after an update onto a table containing an after trigger
+do_test lastinsert-3.1 {
+ catchsql {
+ delete from t2;
+ drop trigger r1;
+ create trigger r1 after update on t1 for each row begin
+ insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
+ update t2 set k=k+10, val2=100+last_insert_rowid();
+ update t2 set val3=1000+last_insert_rowid();
+ end;
+ update t1 set k=14 where k=3;
+ select last_insert_rowid();
+ }
+} {0 13}
+
+# LIRID unchanged upon entry into after update trigger
+do_test lastinsert-3.2 {
+ catchsql {
+ select val1 from t2;
+ }
+} {0 13}
+
+# LIRID changed properly by insert within context of after update trigger
+do_test lastinsert-3.3 {
+ catchsql {
+ select val2 from t2;
+ }
+} {0 128}
+
+# LIRID unchanged by update within context of after update trigger
+do_test lastinsert-3.4 {
+ catchsql {
+ select val3 from t2;
+ }
+} {0 1028}
+
+# ----------------------------------------------------------------------------
+# 4.x - tests with instead of insert trigger
+
+# LIRID not changed after an insert into view containing an instead of trigger
+do_test lastinsert-4.1 {
+ catchsql {
+ delete from t2;
+ drop trigger r1;
+ create trigger r1 instead of insert on v for each row begin
+ insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
+ update t2 set k=k+10, val2=100+last_insert_rowid();
+ update t2 set val3=1000+last_insert_rowid();
+ end;
+ insert into v values (15);
+ select last_insert_rowid();
+ }
+} {0 13}
+
+# LIRID unchanged upon entry into instead of trigger
+do_test lastinsert-4.2 {
+ catchsql {
+ select val1 from t2;
+ }
+} {0 13}
+
+# LIRID changed properly by insert within context of instead of trigger
+do_test lastinsert-4.3 {
+ catchsql {
+ select val2 from t2;
+ }
+} {0 130}
+
+# LIRID unchanged by update within context of instead of trigger
+do_test lastinsert-4.4 {
+ catchsql {
+ select val3 from t2;
+ }
+} {0 1030}
+
+# ----------------------------------------------------------------------------
+# 5.x - tests with before delete trigger
+
+# LIRID not changed after a delete on a table containing a before trigger
+do_test lastinsert-5.1 {
+ catchsql {
+ delete from t2;
+ drop trigger r1;
+ create trigger r1 before delete on t1 for each row begin
+ insert into t2 values (77, last_insert_rowid(), NULL, NULL);
+ update t2 set k=k+10, val2=100+last_insert_rowid();
+ update t2 set val3=1000+last_insert_rowid();
+ end;
+ delete from t1 where k=1;
+ select last_insert_rowid();
+ }
+} {0 13}
+
+# LIRID unchanged upon entry into delete trigger
+do_test lastinsert-5.2 {
+ catchsql {
+ select val1 from t2;
+ }
+} {0 13}
+
+# LIRID changed properly by insert within context of delete trigger
+do_test lastinsert-5.3 {
+ catchsql {
+ select val2 from t2;
+ }
+} {0 177}
+
+# LIRID unchanged by update within context of delete trigger
+do_test lastinsert-5.4 {
+ catchsql {
+ select val3 from t2;
+ }
+} {0 1077}
+
+# ----------------------------------------------------------------------------
+# 6.x - tests with instead of update trigger
+
+# LIRID not changed after an update on a view containing an instead of trigger
+do_test lastinsert-6.1 {
+ catchsql {
+ delete from t2;
+ drop trigger r1;
+ create trigger r1 instead of update on v for each row begin
+ insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
+ update t2 set k=k+10, val2=100+last_insert_rowid();
+ update t2 set val3=1000+last_insert_rowid();
+ end;
+ update v set k=16 where k=14;
+ select last_insert_rowid();
+ }
+} {0 13}
+
+# LIRID unchanged upon entry into instead of trigger
+do_test lastinsert-6.2 {
+ catchsql {
+ select val1 from t2;
+ }
+} {0 13}
+
+# LIRID changed properly by insert within context of instead of trigger
+do_test lastinsert-6.3 {
+ catchsql {
+ select val2 from t2;
+ }
+} {0 132}
+
+# LIRID unchanged by update within context of instead of trigger
+do_test lastinsert-6.4 {
+ catchsql {
+ select val3 from t2;
+ }
+} {0 1032}
+
+# ----------------------------------------------------------------------------
+# 7.x - complex tests with temporary tables and nested instead of triggers
+
+do_test lastinsert-7.1 {
+ catchsql {
+ drop table t1; drop table t2; drop trigger r1;
+ create temp table t1 (k integer primary key);
+ create temp table t2 (k integer primary key);
+ create temp view v1 as select * from t1;
+ create temp view v2 as select * from t2;
+ create temp table rid (k integer primary key, rin, rout);
+ insert into rid values (1, NULL, NULL);
+ insert into rid values (2, NULL, NULL);
+ create temp trigger r1 instead of insert on v1 for each row begin
+ update rid set rin=last_insert_rowid() where k=1;
+ insert into t1 values (100+NEW.k);
+ insert into v2 values (100+last_insert_rowid());
+ update rid set rout=last_insert_rowid() where k=1;
+ end;
+ create temp trigger r2 instead of insert on v2 for each row begin
+ update rid set rin=last_insert_rowid() where k=2;
+ insert into t2 values (1000+NEW.k);
+ update rid set rout=last_insert_rowid() where k=2;
+ end;
+ insert into t1 values (77);
+ select last_insert_rowid();
+ }
+} {0 77}
+
+do_test lastinsert-7.2 {
+ catchsql {
+ insert into v1 values (5);
+ select last_insert_rowid();
+ }
+} {0 77}
+
+do_test lastinsert-7.3 {
+ catchsql {
+ select rin from rid where k=1;
+ }
+} {0 77}
+
+do_test lastinsert-7.4 {
+ catchsql {
+ select rout from rid where k=1;
+ }
+} {0 105}
+
+do_test lastinsert-7.5 {
+ catchsql {
+ select rin from rid where k=2;
+ }
+} {0 105}
+
+do_test lastinsert-7.6 {
+ catchsql {
+ select rout from rid where k=2;
+ }
+} {0 1205}
+
+finish_test
+
diff --git a/usr/src/lib/libsqlite/test/laststmtchanges.test b/usr/src/lib/libsqlite/test/laststmtchanges.test
new file mode 100644
index 0000000000..b35ed12731
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/laststmtchanges.test
@@ -0,0 +1,247 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 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.
+#
+#***********************************************************************
+#
+# Tests to make sure that value returned by last_statement_change_count()
+# (LSCC) is updated properly, especially inside triggers
+#
+# Note 1: LSCC remains constant within a statement and only updates once
+# the statement is finished (triggers count as part of statement)
+# Note 2: LSCC is changed within the context of a trigger
+# much like last_insert_rowid() (see lastinsert.test),
+# but is restored once the trigger exits
+# Note 3: LSCC is not changed by a change to a view (since everything
+# is done within instead of trigger context)
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# ----------------------------------------------------------------------------
+# 1.x - basic tests (no triggers)
+
+# LSCC set properly after insert
+do_test laststmtchanges-1.1 {
+ catchsql {
+ create table t0 (x);
+ insert into t0 values (1);
+ insert into t0 values (1);
+ insert into t0 values (2);
+ insert into t0 values (2);
+ insert into t0 values (1);
+ insert into t0 values (1);
+ insert into t0 values (1);
+ insert into t0 values (2);
+ select last_statement_change_count();
+ }
+} {0 1}
+
+# LSCC set properly after update
+do_test laststmtchanges-1.2 {
+ catchsql {
+ update t0 set x=3 where x=1;
+ select last_statement_change_count();
+ }
+} {0 5}
+
+# LSCC unchanged within an update statement
+do_test laststmtchanges-1.3 {
+ catchsql {
+ update t0 set x=x+last_statement_change_count() where x=3;
+ select count() from t0 where x=8;
+ }
+} {0 5}
+
+# LSCC set properly after update on table where no rows changed
+do_test laststmtchanges-1.4 {
+ catchsql {
+ update t0 set x=77 where x=88;
+ select last_statement_change_count();
+ }
+} {0 0}
+
+# LSCC set properly after delete from table
+do_test laststmtchanges-1.5 {
+ catchsql {
+ delete from t0 where x=2;
+ select last_statement_change_count();
+ }
+} {0 3}
+
+# ----------------------------------------------------------------------------
+# 2.x - tests with after insert trigger
+
+# LSCC changed properly after insert into table containing after trigger
+do_test laststmtchanges-2.1 {
+ catchsql {
+ create table t1 (k integer primary key);
+ create table t2 (k integer primary key, v1, v2);
+ create trigger r1 after insert on t1 for each row begin
+ insert into t2 values (NULL, last_statement_change_count(), NULL);
+ update t0 set x=x;
+ update t2 set v2=last_statement_change_count();
+ end;
+ insert into t1 values (77);
+ select last_statement_change_count();
+ }
+} {0 1}
+
+# LSCC unchanged upon entry into after insert trigger
+do_test laststmtchanges-2.2 {
+ catchsql {
+ select v1 from t2;
+ }
+} {0 3}
+
+# LSCC changed properly by update within context of after insert trigger
+do_test laststmtchanges-2.3 {
+ catchsql {
+ select v2 from t2;
+ }
+} {0 5}
+
+# ----------------------------------------------------------------------------
+# 3.x - tests with after update trigger
+
+# LSCC changed properly after update into table containing after trigger
+do_test laststmtchanges-3.1 {
+ catchsql {
+ drop trigger r1;
+ delete from t2; delete from t2;
+ create trigger r1 after update on t1 for each row begin
+ insert into t2 values (NULL, last_statement_change_count(), NULL);
+ delete from t0 where oid=1 or oid=2;
+ update t2 set v2=last_statement_change_count();
+ end;
+ update t1 set k=k;
+ select last_statement_change_count();
+ }
+} {0 1}
+
+# LSCC unchanged upon entry into after update trigger
+do_test laststmtchanges-3.2 {
+ catchsql {
+ select v1 from t2;
+ }
+} {0 0}
+
+# LSCC changed properly by delete within context of after update trigger
+do_test laststmtchanges-3.3 {
+ catchsql {
+ select v2 from t2;
+ }
+} {0 2}
+
+# ----------------------------------------------------------------------------
+# 4.x - tests with before delete trigger
+
+# LSCC changed properly on delete from table containing before trigger
+do_test laststmtchanges-4.1 {
+ catchsql {
+ drop trigger r1;
+ delete from t2; delete from t2;
+ create trigger r1 before delete on t1 for each row begin
+ insert into t2 values (NULL, last_statement_change_count(), NULL);
+ insert into t0 values (5);
+ update t2 set v2=last_statement_change_count();
+ end;
+ delete from t1;
+ select last_statement_change_count();
+ }
+} {0 1}
+
+# LSCC unchanged upon entry into before delete trigger
+do_test laststmtchanges-4.2 {
+ catchsql {
+ select v1 from t2;
+ }
+} {0 0}
+
+# LSCC changed properly by insert within context of before delete trigger
+do_test laststmtchanges-4.3 {
+ catchsql {
+ select v2 from t2;
+ }
+} {0 1}
+
+# ----------------------------------------------------------------------------
+# 5.x - complex tests with temporary tables and nested instead of triggers
+
+do_test laststmtchanges-5.1 {
+ catchsql {
+ drop table t0; drop table t1; drop table t2;
+ create temp table t0(x);
+ create temp table t1 (k integer primary key);
+ create temp table t2 (k integer primary key);
+ create temp view v1 as select * from t1;
+ create temp view v2 as select * from t2;
+ create temp table n1 (k integer primary key, n);
+ create temp table n2 (k integer primary key, n);
+ insert into t0 values (1);
+ insert into t0 values (2);
+ insert into t0 values (1);
+ insert into t0 values (1);
+ insert into t0 values (1);
+ insert into t0 values (2);
+ insert into t0 values (2);
+ insert into t0 values (1);
+ create temp trigger r1 instead of insert on v1 for each row begin
+ insert into n1 values (NULL, last_statement_change_count());
+ update t0 set x=x*10 where x=1;
+ insert into n1 values (NULL, last_statement_change_count());
+ insert into t1 values (NEW.k);
+ insert into n1 values (NULL, last_statement_change_count());
+ update t0 set x=x*10 where x=0;
+ insert into v2 values (100+NEW.k);
+ insert into n1 values (NULL, last_statement_change_count());
+ end;
+ create temp trigger r2 instead of insert on v2 for each row begin
+ insert into n2 values (NULL, last_statement_change_count());
+ insert into t2 values (1000+NEW.k);
+ insert into n2 values (NULL, last_statement_change_count());
+ update t0 set x=x*100 where x=0;
+ insert into n2 values (NULL, last_statement_change_count());
+ delete from t0 where x=2;
+ insert into n2 values (NULL, last_statement_change_count());
+ end;
+ insert into t1 values (77);
+ select last_statement_change_count();
+ }
+} {0 1}
+
+do_test laststmtchanges-5.2 {
+ catchsql {
+ delete from t1 where k=88;
+ select last_statement_change_count();
+ }
+} {0 0}
+
+do_test laststmtchanges-5.3 {
+ catchsql {
+ insert into v1 values (5);
+ select last_statement_change_count();
+ }
+} {0 0}
+
+do_test laststmtchanges-5.4 {
+ catchsql {
+ select n from n1;
+ }
+} {0 {0 5 1 0}}
+
+do_test laststmtchanges-5.5 {
+ catchsql {
+ select n from n2;
+ }
+} {0 {0 1 0 3}}
+
+finish_test
+
diff --git a/usr/src/lib/libsqlite/test/limit.test b/usr/src/lib/libsqlite/test/limit.test
new file mode 100644
index 0000000000..04a56fe798
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/limit.test
@@ -0,0 +1,320 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 November 6
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing the LIMIT ... OFFSET ... clause
+# of SELECT statements.
+#
+# $Id: limit.test,v 1.11.2.1 2004/07/19 23:33:04 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Build some test data
+#
+set fd [open data1.txt w]
+for {set i 1} {$i<=32} {incr i} {
+ for {set j 0} {pow(2,$j)<$i} {incr j} {}
+ puts $fd "[expr {32-$i}]\t[expr {10-$j}]"
+}
+close $fd
+execsql {
+ CREATE TABLE t1(x int, y int);
+ COPY t1 FROM 'data1.txt'
+}
+file delete data1.txt
+
+do_test limit-1.0 {
+ execsql {SELECT count(*) FROM t1}
+} {32}
+do_test limit-1.1 {
+ execsql {SELECT count(*) FROM t1 LIMIT 5}
+} {32}
+do_test limit-1.2.1 {
+ execsql {SELECT x FROM t1 ORDER BY x LIMIT 5}
+} {0 1 2 3 4}
+do_test limit-1.2.2 {
+ execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 2}
+} {2 3 4 5 6}
+do_test limit-1.2.3 {
+ execsql {SELECT x FROM t1 ORDER BY x LIMIT 2, 5}
+} {2 3 4 5 6}
+do_test limit-1.3 {
+ execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 5}
+} {5 6 7 8 9}
+do_test limit-1.4.1 {
+ execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 30}
+} {30 31}
+do_test limit-1.4.2 {
+ execsql {SELECT x FROM t1 ORDER BY x LIMIT 30, 50}
+} {30 31}
+do_test limit-1.5 {
+ execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 50}
+} {}
+do_test limit-1.6 {
+ execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5}
+} {0 5 0 5 0 5 1 5 0 5 2 5 0 5 3 5 0 5 4 5}
+do_test limit-1.7 {
+ execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5 OFFSET 32}
+} {1 5 0 5 1 5 1 5 1 5 2 5 1 5 3 5 1 5 4 5}
+
+do_test limit-2.1 {
+ execsql {
+ CREATE VIEW v1 AS SELECT * FROM t1 LIMIT 2;
+ SELECT count(*) FROM (SELECT * FROM v1);
+ }
+} 2
+do_test limit-2.2 {
+ execsql {
+ CREATE TABLE t2 AS SELECT * FROM t1 LIMIT 2;
+ SELECT count(*) FROM t2;
+ }
+} 2
+do_test limit-2.3 {
+ execsql {
+ SELECT count(*) FROM t1 WHERE rowid IN (SELECT rowid FROM t1 LIMIT 2);
+ }
+} 2
+
+do_test limit-3.1 {
+ execsql {
+ SELECT z FROM (SELECT y*10+x AS z FROM t1 ORDER BY x LIMIT 10)
+ ORDER BY z LIMIT 5;
+ }
+} {50 51 52 53 54}
+
+do_test limit-4.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t3(x);
+ INSERT INTO t3 SELECT x FROM t1 ORDER BY x LIMIT 10 OFFSET 1;
+ INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+ INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+ INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+ INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+ INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+ INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+ INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+ INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+ INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+ INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+ END;
+ SELECT count(*) FROM t3;
+ }
+} {10240}
+do_test limit-4.2 {
+ execsql {
+ SELECT x FROM t3 LIMIT 2 OFFSET 10000
+ }
+} {10001 10002}
+do_test limit-4.3 {
+ execsql {
+ CREATE TABLE t4 AS SELECT x,
+ 'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
+ 'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
+ 'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
+ 'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
+ 'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x AS y
+ FROM t3 LIMIT 1000;
+ SELECT x FROM t4 ORDER BY y DESC LIMIT 1 OFFSET 999;
+ }
+} {1000}
+
+do_test limit-5.1 {
+ execsql {
+ CREATE TABLE t5(x,y);
+ INSERT INTO t5 SELECT x-y, x+y FROM t1 WHERE x BETWEEN 10 AND 15
+ ORDER BY x LIMIT 2;
+ SELECT * FROM t5 ORDER BY x;
+ }
+} {5 15 6 16}
+do_test limit-5.2 {
+ execsql {
+ DELETE FROM t5;
+ INSERT INTO t5 SELECT x-y, x+y FROM t1 WHERE x BETWEEN 10 AND 15
+ ORDER BY x DESC LIMIT 2;
+ SELECT * FROM t5 ORDER BY x;
+ }
+} {9 19 10 20}
+do_test limit-5.3 {
+ execsql {
+ DELETE FROM t5;
+ INSERT INTO t5 SELECT x-y, x+y FROM t1 WHERE x ORDER BY x DESC LIMIT 31;
+ SELECT * FROM t5 ORDER BY x LIMIT 2;
+ }
+} {-4 6 -3 7}
+do_test limit-5.4 {
+ execsql {
+ SELECT * FROM t5 ORDER BY x DESC, y DESC LIMIT 2;
+ }
+} {21 41 21 39}
+do_test limit-5.5 {
+ execsql {
+ DELETE FROM t5;
+ INSERT INTO t5 SELECT a.x*100+b.x, a.y*100+b.y FROM t1 AS a, t1 AS b
+ ORDER BY 1, 2 LIMIT 1000;
+ SELECT count(*), sum(x), sum(y), min(x), max(x), min(y), max(y) FROM t5;
+ }
+} {1000 1528204 593161 0 3107 505 1005}
+
+# There is some contraversy about whether LIMIT 0 should be the same as
+# no limit at all or if LIMIT 0 should result in zero output rows.
+#
+do_test limit-6.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t6(a);
+ INSERT INTO t6 VALUES(1);
+ INSERT INTO t6 VALUES(2);
+ INSERT INTO t6 SELECT a+2 FROM t6;
+ COMMIT;
+ SELECT * FROM t6;
+ }
+} {1 2 3 4}
+do_test limit-6.2 {
+ execsql {
+ SELECT * FROM t6 LIMIT -1 OFFSET -1;
+ }
+} {1 2 3 4}
+do_test limit-6.3 {
+ execsql {
+ SELECT * FROM t6 LIMIT 2 OFFSET -123;
+ }
+} {1 2}
+do_test limit-6.4 {
+ execsql {
+ SELECT * FROM t6 LIMIT -432 OFFSET 2;
+ }
+} {3 4}
+do_test limit-6.5 {
+ execsql {
+ SELECT * FROM t6 LIMIT -1
+ }
+} {1 2 3 4}
+do_test limit-6.6 {
+ execsql {
+ SELECT * FROM t6 LIMIT -1 OFFSET 1
+ }
+} {2 3 4}
+do_test limit-6.7 {
+ execsql {
+ SELECT * FROM t6 LIMIT 0
+ }
+} {}
+do_test limit-6.8 {
+ execsql {
+ SELECT * FROM t6 LIMIT 0 OFFSET 1
+ }
+} {}
+
+# Make sure LIMIT works well with compound SELECT statements.
+# Ticket #393
+#
+do_test limit-7.1.1 {
+ catchsql {
+ SELECT x FROM t2 LIMIT 5 UNION ALL SELECT a FROM t6;
+ }
+} {1 {LIMIT clause should come after UNION ALL not before}}
+do_test limit-7.1.2 {
+ catchsql {
+ SELECT x FROM t2 LIMIT 5 UNION SELECT a FROM t6;
+ }
+} {1 {LIMIT clause should come after UNION not before}}
+do_test limit-7.1.3 {
+ catchsql {
+ SELECT x FROM t2 LIMIT 5 EXCEPT SELECT a FROM t6 LIMIT 3;
+ }
+} {1 {LIMIT clause should come after EXCEPT not before}}
+do_test limit-7.1.4 {
+ catchsql {
+ SELECT x FROM t2 LIMIT 0,5 INTERSECT SELECT a FROM t6;
+ }
+} {1 {LIMIT clause should come after INTERSECT not before}}
+do_test limit-7.2 {
+ execsql {
+ SELECT x FROM t2 UNION ALL SELECT a FROM t6 LIMIT 5;
+ }
+} {31 30 1 2 3}
+do_test limit-7.3 {
+ execsql {
+ SELECT x FROM t2 UNION ALL SELECT a FROM t6 LIMIT 3 OFFSET 1;
+ }
+} {30 1 2}
+do_test limit-7.4 {
+ execsql {
+ SELECT x FROM t2 UNION ALL SELECT a FROM t6 ORDER BY 1 LIMIT 3 OFFSET 1;
+ }
+} {2 3 4}
+do_test limit-7.5 {
+ execsql {
+ SELECT x FROM t2 UNION SELECT x+2 FROM t2 LIMIT 2 OFFSET 1;
+ }
+} {31 32}
+do_test limit-7.6 {
+ execsql {
+ SELECT x FROM t2 UNION SELECT x+2 FROM t2 ORDER BY 1 DESC LIMIT 2 OFFSET 1;
+ }
+} {32 31}
+do_test limit-7.7 {
+ execsql {
+ SELECT a+9 FROM t6 EXCEPT SELECT y FROM t2 LIMIT 2;
+ }
+} {11 12}
+do_test limit-7.8 {
+ execsql {
+ SELECT a+9 FROM t6 EXCEPT SELECT y FROM t2 ORDER BY 1 DESC LIMIT 2;
+ }
+} {13 12}
+do_test limit-7.9 {
+ execsql {
+ SELECT a+26 FROM t6 INTERSECT SELECT x FROM t2 LIMIT 1;
+ }
+} {30}
+do_test limit-7.10 {
+ execsql {
+ SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2 LIMIT 1;
+ }
+} {30}
+do_test limit-7.11 {
+ execsql {
+ SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2 LIMIT 1 OFFSET 1;
+ }
+} {31}
+do_test limit-7.12 {
+ execsql {
+ SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2
+ ORDER BY 1 DESC LIMIT 1 OFFSET 1;
+ }
+} {30}
+
+# Tests for limit in conjunction with distinct. The distinct should
+# occur before both the limit and the offset. Ticket #749.
+#
+do_test limit-8.1 {
+ execsql {
+ SELECT DISTINCT round(x/100) FROM t3 LIMIT 5;
+ }
+} {0 1 2 3 4}
+do_test limit-8.2 {
+ execsql {
+ SELECT DISTINCT round(x/100) FROM t3 LIMIT 5 OFFSET 5;
+ }
+} {5 6 7 8 9}
+do_test limit-8.3 {
+ execsql {
+ SELECT DISTINCT round(x/100) FROM t3 LIMIT 5 OFFSET 25;
+ }
+} {25 26 27 28 29}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/lock.test b/usr/src/lib/libsqlite/test/lock.test
new file mode 100644
index 0000000000..ca4310c4b2
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/lock.test
@@ -0,0 +1,352 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 database locks.
+#
+# $Id: lock.test,v 1.20 2004/02/14 16:31:04 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create an alternative connection to the database
+#
+do_test lock-1.0 {
+ sqlite db2 ./test.db
+ set dummy {}
+} {}
+do_test lock-1.1 {
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
+} {}
+do_test lock-1.2 {
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name} db2
+} {}
+do_test lock-1.3 {
+ execsql {CREATE TABLE t1(a int, b int)}
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
+} {t1}
+#do_test lock-1.4 {
+# catchsql {
+# SELECT name FROM sqlite_master WHERE type='table' ORDER BY name
+# } db2
+#} {1 {database schema has changed}}
+do_test lock-1.5 {
+ catchsql {
+ SELECT name FROM sqlite_master WHERE type='table' ORDER BY name
+ } db2
+} {0 t1}
+
+do_test lock-1.6 {
+ execsql {INSERT INTO t1 VALUES(1,2)}
+ execsql {SELECT * FROM t1}
+} {1 2}
+do_test lock-1.7 {
+ execsql {SELECT * FROM t1} db2
+} {1 2}
+do_test lock-1.8 {
+ execsql {UPDATE t1 SET a=b, b=a} db2
+ execsql {SELECT * FROM t1} db2
+} {2 1}
+do_test lock-1.9 {
+ execsql {SELECT * FROM t1}
+} {2 1}
+do_test lock-1.10 {
+ execsql {BEGIN TRANSACTION}
+ execsql {SELECT * FROM t1}
+} {2 1}
+do_test lock-1.11 {
+ catchsql {SELECT * FROM t1} db2
+} {1 {database is locked}}
+do_test lock-1.12 {
+ execsql {ROLLBACK}
+ catchsql {SELECT * FROM t1}
+} {0 {2 1}}
+
+do_test lock-1.13 {
+ execsql {CREATE TABLE t2(x int, y int)}
+ execsql {INSERT INTO t2 VALUES(8,9)}
+ execsql {SELECT * FROM t2}
+} {8 9}
+do_test lock-1.14.1 {
+ catchsql {SELECT * FROM t2} db2
+} {1 {no such table: t2}}
+do_test lock-1.14.2 {
+ catchsql {SELECT * FROM t1} db2
+} {0 {2 1}}
+do_test lock-1.15 {
+ catchsql {SELECT * FROM t2} db2
+} {0 {8 9}}
+
+do_test lock-1.16 {
+ db eval {SELECT * FROM t1} qv {
+ set x [db eval {SELECT * FROM t1}]
+ }
+ set x
+} {2 1}
+do_test lock-1.17 {
+ db eval {SELECT * FROM t1} qv {
+ set x [db eval {SELECT * FROM t2}]
+ }
+ set x
+} {8 9}
+
+# You cannot UPDATE a table from within the callback of a SELECT
+# on that same table because the SELECT has the table locked.
+#
+do_test lock-1.18 {
+ db eval {SELECT * FROM t1} qv {
+ set r [catch {db eval {UPDATE t1 SET a=b, b=a}} msg]
+ lappend r $msg
+ }
+ set r
+} {1 {database table is locked}}
+
+# But you can UPDATE a different table from the one that is used in
+# the SELECT.
+#
+do_test lock-1.19 {
+ db eval {SELECT * FROM t1} qv {
+ set r [catch {db eval {UPDATE t2 SET x=y, y=x}} msg]
+ lappend r $msg
+ }
+ set r
+} {0 {}}
+do_test lock-1.20 {
+ execsql {SELECT * FROM t2}
+} {9 8}
+
+# It is possible to do a SELECT of the same table within the
+# callback of another SELECT on that same table because two
+# or more read-only cursors can be open at once.
+#
+do_test lock-1.21 {
+ db eval {SELECT * FROM t1} qv {
+ set r [catch {db eval {SELECT a FROM t1}} msg]
+ lappend r $msg
+ }
+ set r
+} {0 2}
+
+# Under UNIX you can do two SELECTs at once with different database
+# connections, because UNIX supports reader/writer locks. Under windows,
+# this is not possible.
+#
+if {$::tcl_platform(platform)=="unix"} {
+ do_test lock-1.22 {
+ db eval {SELECT * FROM t1} qv {
+ set r [catch {db2 eval {SELECT a FROM t1}} msg]
+ lappend r $msg
+ }
+ set r
+ } {0 2}
+}
+integrity_check lock-1.23
+
+# If one thread has a transaction another thread cannot start
+# a transaction.
+#
+do_test lock-2.1 {
+ execsql {BEGIN TRANSACTION}
+ set r [catch {execsql {BEGIN TRANSACTION} db2} msg]
+ lappend r $msg
+} {1 {database is locked}}
+
+# Nor can the other thread do a query.
+#
+do_test lock-2.2 {
+ set r [catch {execsql {SELECT * FROM t2} db2} msg]
+ lappend r $msg
+} {1 {database is locked}}
+
+# If the other thread (the one that does not hold the transaction)
+# tries to start a transaction, we get a busy callback.
+#
+do_test lock-2.3 {
+ proc callback {args} {
+ set ::callback_value $args
+ break
+ }
+ set ::callback_value {}
+ db2 busy callback
+ set r [catch {execsql {BEGIN TRANSACTION} db2} msg]
+ lappend r $msg
+ lappend r $::callback_value
+} {1 {database is locked} {{} 1}}
+do_test lock-2.4 {
+ proc callback {file count} {
+ lappend ::callback_value $count
+ if {$count>4} break
+ }
+ set ::callback_value {}
+ db2 busy callback
+ set r [catch {execsql {BEGIN TRANSACTION} db2} msg]
+ lappend r $msg
+ lappend r $::callback_value
+} {1 {database is locked} {1 2 3 4 5}}
+do_test lock-2.5 {
+ proc callback {file count} {
+ lappend ::callback_value $count
+ if {$count>4} break
+ }
+ set ::callback_value {}
+ db2 busy callback
+ set r [catch {execsql {SELECT * FROM t1} db2} msg]
+ lappend r $msg
+ lappend r $::callback_value
+} {1 {database is locked} {1 2 3 4 5}}
+
+# In this test, the 3rd invocation of the busy callback causes
+# the first thread to release its transaction. That allows the
+# second thread to continue.
+#
+do_test lock-2.6 {
+ proc callback {file count} {
+ lappend ::callback_value $count
+ if {$count>2} {
+ execsql {ROLLBACK}
+ }
+ }
+ set ::callback_value {}
+ db2 busy callback
+ set r [catch {execsql {SELECT * FROM t2} db2} msg]
+ lappend r $msg
+ lappend r $::callback_value
+} {0 {9 8} {1 2 3}}
+do_test lock-2.7 {
+ execsql {BEGIN TRANSACTION}
+ proc callback {file count} {
+ lappend ::callback_value $count
+ if {$count>2} {
+ execsql {ROLLBACK}
+ }
+ }
+ set ::callback_value {}
+ db2 busy callback
+ set r [catch {execsql {BEGIN TRANSACTION} db2} msg]
+ execsql {ROLLBACK} db2
+ lappend r $msg
+ lappend r $::callback_value
+} {0 {} {1 2 3}}
+
+# Test the built-in busy timeout handler
+#
+do_test lock-2.8 {
+ db2 timeout 400
+ execsql BEGIN
+ catchsql BEGIN db2
+} {1 {database is locked}}
+do_test lock-2.9 {
+ db2 timeout 0
+ execsql COMMIT
+} {}
+integrity_check lock-2.10
+
+# Try to start two transactions in a row
+#
+do_test lock-3.1 {
+ execsql {BEGIN TRANSACTION}
+ set r [catch {execsql {BEGIN TRANSACTION}} msg]
+ execsql {ROLLBACK}
+ lappend r $msg
+} {1 {cannot start a transaction within a transaction}}
+integrity_check lock-3.2
+
+# Make sure the busy handler and error messages work when
+# opening a new pointer to the database while another pointer
+# has the database locked.
+#
+do_test lock-4.1 {
+ db2 close
+ catch {db eval ROLLBACK}
+ db eval BEGIN
+ sqlite db2 ./test.db
+ set rc [catch {db2 eval {SELECT * FROM t1}} msg]
+ lappend rc $msg
+} {1 {database is locked}}
+do_test lock-4.2 {
+ set ::callback_value {}
+ set rc [catch {db2 eval {SELECT * FROM t1}} msg]
+ lappend rc $msg $::callback_value
+} {1 {database is locked} {}}
+do_test lock-4.3 {
+ proc callback {file count} {
+ lappend ::callback_value $count
+ if {$count>4} break
+ }
+ db2 busy callback
+ set rc [catch {db2 eval {SELECT * FROM t1}} msg]
+ lappend rc $msg $::callback_value
+} {1 {database is locked} {1 2 3 4 5}}
+execsql {ROLLBACK}
+
+# When one thread is writing, other threads cannot read. Except if the
+# writing thread is writing to its temporary tables, the other threads
+# can still read.
+#
+proc tx_exec {sql} {
+ db2 eval $sql
+}
+do_test lock-5.1 {
+ execsql {
+ SELECT * FROM t1
+ }
+} {2 1}
+do_test lock-5.2 {
+ db function tx_exec tx_exec
+ catchsql {
+ INSERT INTO t1(a,b) SELECT 3, tx_exec('SELECT y FROM t2 LIMIT 1');
+ }
+} {1 {database is locked}}
+do_test lock-5.3 {
+ execsql {
+ CREATE TEMP TABLE t3(x);
+ SELECT * FROM t3;
+ }
+} {}
+do_test lock-5.4 {
+ catchsql {
+ INSERT INTO t3 SELECT tx_exec('SELECT y FROM t2 LIMIT 1');
+ }
+} {0 {}}
+do_test lock-5.5 {
+ execsql {
+ SELECT * FROM t3;
+ }
+} {8}
+do_test lock-5.6 {
+ catchsql {
+ UPDATE t1 SET a=tx_exec('SELECT x FROM t2');
+ }
+} {1 {database is locked}}
+do_test lock-5.7 {
+ execsql {
+ SELECT * FROM t1;
+ }
+} {2 1}
+do_test lock-5.8 {
+ catchsql {
+ UPDATE t3 SET x=tx_exec('SELECT x FROM t2');
+ }
+} {0 {}}
+do_test lock-5.9 {
+ execsql {
+ SELECT * FROM t3;
+ }
+} {9}
+
+do_test lock-999.1 {
+ rename db2 {}
+} {}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/main.test b/usr/src/lib/libsqlite/test/main.test
new file mode 100644
index 0000000000..529e40ed61
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/main.test
@@ -0,0 +1,300 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 exercising the code in main.c.
+#
+# $Id: main.test,v 1.14 2003/05/04 17:58:27 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Tests of the sqlite_complete() function.
+#
+do_test main-1.1 {
+ db complete {This is a test}
+} {0}
+do_test main-1.2 {
+ db complete {
+ }
+} {1}
+do_test main-1.3 {
+ db complete {
+ -- a comment ;
+ }
+} {1}
+do_test main-1.4 {
+ db complete {
+ -- a comment ;
+ ;
+ }
+} {1}
+do_test main-1.5 {
+ db complete {DROP TABLE 'xyz;}
+} {0}
+do_test main-1.6 {
+ db complete {DROP TABLE 'xyz';}
+} {1}
+do_test main-1.7 {
+ db complete {DROP TABLE "xyz;}
+} {0}
+do_test main-1.8 {
+ db complete {DROP TABLE "xyz';}
+} {0}
+do_test main-1.9 {
+ db complete {DROP TABLE "xyz";}
+} {1}
+do_test main-1.10 {
+ db complete {DROP TABLE xyz; hi}
+} {0}
+do_test main-1.11 {
+ db complete {DROP TABLE xyz; }
+} {1}
+do_test main-1.12 {
+ db complete {DROP TABLE xyz; -- hi }
+} {1}
+do_test main-1.13 {
+ db complete {DROP TABLE xyz; -- hi
+ }
+} {1}
+do_test main-1.14 {
+ db complete {SELECT a-b FROM t1; }
+} {1}
+do_test main-1.15 {
+ db complete {SELECT a-b FROM t1 }
+} {0}
+do_test main-1.16 {
+ db complete {
+ CREATE TABLE abc(x,y);
+ }
+} {1}
+do_test main-1.17 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE abc BEGIN UPDATE pqr;
+ }
+} {0}
+do_test main-1.18 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE abc BEGIN UPDATE pqr; END;
+ }
+} {1}
+do_test main-1.19 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE abc BEGIN
+ UPDATE pqr;
+ unknown command;
+ }
+} {0}
+do_test main-1.20 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr;
+ }
+} {0}
+do_test main-1.21 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE end BEGIN
+ SELECT a, b FROM end;
+ }
+} {0}
+do_test main-1.22 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE end BEGIN
+ SELECT a, b FROM end;
+ END;
+ }
+} {1}
+do_test main-1.23 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE end BEGIN
+ SELECT a, b FROM end;
+ END;
+ SELECT a, b FROM end;
+ }
+} {1}
+do_test main-1.24 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE [;end;] BEGIN
+ UPDATE pqr;
+ }
+} {0}
+do_test main-1.25 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=[;end;];;;
+ }
+} {0}
+do_test main-1.26 {
+ db complete {
+ CREATE -- a comment
+ TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ }
+} {0}
+do_test main-1.27.1 {
+ db complete {
+ CREATE -- a comment
+ TRIGGERX xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ }
+} {1}
+do_test main-1.27.2 {
+ db complete {
+ CREATE/**/TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ }
+} {0}
+do_test main-1.27.3 {
+ db complete {
+ /* */ EXPLAIN -- A comment
+ CREATE/**/TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ }
+} {0}
+do_test main-1.27.4 {
+ db complete {
+ BOGUS token
+ CREATE TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ }
+} {1}
+do_test main-1.27.5 {
+ db complete {
+ EXPLAIN
+ CREATE TEMP TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ }
+} {0}
+do_test main-1.28 {
+ db complete {
+ CREATE TEMP TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ }
+} {0}
+do_test main-1.29 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ EXPLAIN select * from xyz;
+ }
+} {0}
+do_test main-1.30 {
+ db complete {
+ CREATE TABLE /* In comment ; */
+ }
+} {0}
+do_test main-1.31 {
+ db complete {
+ CREATE TABLE /* In comment ; */ hi;
+ }
+} {1}
+do_test main-1.31 {
+ db complete {
+ CREATE TABLE /* In comment ; */;
+ }
+} {1}
+do_test main-1.32 {
+ db complete {
+ stuff;
+ /*
+ CREATE TABLE
+ multiple lines
+ of text
+ */
+ }
+} {1}
+do_test main-1.33 {
+ db complete {
+ /*
+ CREATE TABLE
+ multiple lines
+ of text;
+ }
+} {0}
+do_test main-1.34 {
+ db complete {
+ /*
+ CREATE TABLE
+ multiple lines "*/
+ of text;
+ }
+} {1}
+do_test main-1.35 {
+ db complete {hi /**/ there;}
+} {1}
+do_test main-1.36 {
+ db complete {hi there/***/;}
+} {1}
+
+
+# Try to open a database with a corrupt database file.
+#
+do_test main-2.0 {
+ catch {db close}
+ file delete -force test.db
+ set fd [open test.db w]
+ puts $fd hi!
+ close $fd
+ set v [catch {sqlite db test.db} msg]
+ if {$v} {lappend v $msg} {lappend v {}}
+} {0 {}}
+
+# Here are some tests for tokenize.c.
+#
+do_test main-3.1 {
+ catch {db close}
+ foreach f [glob -nocomplain testdb/*] {file delete -force $f}
+ file delete -force testdb
+ sqlite db testdb
+ set v [catch {execsql {SELECT * from T1 where x!!5}} msg]
+ lappend v $msg
+} {1 {unrecognized token: "!!"}}
+do_test main-3.2 {
+ catch {db close}
+ foreach f [glob -nocomplain testdb/*] {file delete -force $f}
+ file delete -force testdb
+ sqlite db testdb
+ set v [catch {execsql {SELECT * from T1 where @x}} msg]
+ lappend v $msg
+} {1 {unrecognized token: "@"}}
+
+do_test main-3.3 {
+ catch {db close}
+ foreach f [glob -nocomplain testdb/*] {file delete -force $f}
+ file delete -force testdb
+ sqlite db testdb
+ execsql {
+ create table T1(X REAL);
+ insert into T1 values(0.5);
+ insert into T1 values(0.5e2);
+ insert into T1 values(0.5e-002);
+ insert into T1 values(5e-002);
+ insert into T1 values(-5.0e-2);
+ insert into T1 values(-5.1e-2);
+ insert into T1 values(0.5e2);
+ insert into T1 values(0.5E+02);
+ insert into T1 values(5E+02);
+ insert into T1 values(5.0E+03);
+ select x*10 from T1 order by x*5;
+ }
+} {-0.51 -0.5 0.05 0.5 5 500 500 500 5000 50000}
+do_test main-3.4 {
+ set v [catch {execsql {create bogus}} msg]
+ lappend v $msg
+} {1 {near "bogus": syntax error}}
+do_test main-3.5 {
+ set v [catch {execsql {create}} msg]
+ lappend v $msg
+} {1 {near "create": syntax error}}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/malloc.test b/usr/src/lib/libsqlite/test/malloc.test
new file mode 100644
index 0000000000..613435d28a
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/malloc.test
@@ -0,0 +1,228 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 attempts to check the library in an out-of-memory situation.
+# When compiled with -DMEMORY_DEBUG=1, the SQLite library accepts a special
+# command (sqlite_malloc_fail N) which causes the N-th malloc to fail. This
+# special feature is used to see what happens in the library if a malloc
+# were to really fail due to an out-of-memory situation.
+#
+# $Id: malloc.test,v 1.6 2004/02/14 01:39:50 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Only run these tests if memory debugging is turned on.
+#
+if {[info command sqlite_malloc_stat]==""} {
+ puts "Skipping malloc tests: not compiled with -DMEMORY_DEBUG..."
+ finish_test
+ return
+}
+
+for {set go 1; set i 1} {$go} {incr i} {
+ do_test malloc-1.$i {
+ sqlite_malloc_fail 0
+ catch {db close}
+ catch {file delete -force test.db}
+ catch {file delete -force test.db-journal}
+ sqlite_malloc_fail $i
+ set v [catch {sqlite db test.db} msg]
+ if {$v} {
+ set msg ""
+ } else {
+ set v [catch {execsql {
+ CREATE TABLE t1(
+ a int, b float, c double, d text, e varchar(20),
+ primary key(a,b,c)
+ );
+ CREATE INDEX i1 ON t1(a,b);
+ INSERT INTO t1 VALUES(1,2.3,4.5,'hi','there');
+ INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder');
+ SELECT * FROM t1;
+ SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0;
+ DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1);
+ SELECT count(*) FROM t1;
+ }} msg]
+ }
+ set leftover [lindex [sqlite_malloc_stat] 2]
+ if {$leftover>0} {
+ if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
+ set ::go 0
+ set v {1 1}
+ } else {
+ set v2 [expr {$msg=="" || $msg=="out of memory"}]
+ if {!$v2} {puts "\nError message returned: $msg"}
+ lappend v $v2
+ }
+ } {1 1}
+}
+
+set fd [open ./data.tmp w]
+for {set i 1} {$i<=20} {incr i} {
+ puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}] abcdefghijklmnopqrstuvwxyz"
+}
+close $fd
+
+for {set go 1; set i 1} {$go} {incr i} {
+ do_test malloc-2.$i {
+ sqlite_malloc_fail 0
+ catch {db close}
+ catch {file delete -force test.db}
+ catch {file delete -force test.db-journal}
+ sqlite_malloc_fail $i
+ set v [catch {sqlite db test.db} msg]
+ if {$v} {
+ set msg ""
+ } else {
+ set v [catch {execsql {
+ CREATE TABLE t1(a int, b int, c int);
+ CREATE INDEX i1 ON t1(a,b);
+ COPY t1 FROM 'data.tmp';
+ SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1;
+ UPDATE t1 SET b=b||b||b||b;
+ UPDATE t1 SET b=a WHERE a in (10,12,22);
+ INSERT INTO t1(c,b,a) VALUES(20,10,5);
+ INSERT INTO t1 SELECT * FROM t1
+ WHERE a IN (SELECT a FROM t1 WHERE a<10);
+ DELETE FROM t1 WHERE a>=10;
+ DROP INDEX i1;
+ DELETE FROM t1;
+ }} msg]
+ }
+ set leftover [lindex [sqlite_malloc_stat] 2]
+ if {$leftover>0} {
+ if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
+ set ::go 0
+ set v {1 1}
+ } else {
+ set v2 [expr {$msg=="" || $msg=="out of memory"}]
+ if {!$v2} {puts "\nError message returned: $msg"}
+ lappend v $v2
+ }
+ } {1 1}
+}
+
+set fd [open ./data.tmp w]
+for {set i 1} {$i<=10} {incr i} {
+ puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}]"
+}
+close $fd
+
+for {set go 1; set i 1} {$go} {incr i} {
+ do_test malloc-3.$i {
+ sqlite_malloc_fail 0
+ catch {db close}
+ catch {file delete -force test.db}
+ catch {file delete -force test.db-journal}
+ sqlite_malloc_fail $i
+ set v [catch {sqlite db test.db} msg]
+ if {$v} {
+ set msg ""
+ } else {
+ set v [catch {execsql {
+ BEGIN TRANSACTION;
+ CREATE TABLE t1(a int, b int, c int);
+ CREATE INDEX i1 ON t1(a,b);
+ COPY t1 FROM 'data.tmp';
+ INSERT INTO t1(c,b,a) VALUES(20,10,5);
+ DELETE FROM t1 WHERE a>=10;
+ DROP INDEX i1;
+ DELETE FROM t1;
+ ROLLBACK;
+ }} msg]
+ }
+ set leftover [lindex [sqlite_malloc_stat] 2]
+ if {$leftover>0} {
+ if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
+ set ::go 0
+ set v {1 1}
+ } else {
+ set v2 [expr {$msg=="" || $msg=="out of memory"}]
+ if {!$v2} {puts "\nError message returned: $msg"}
+ lappend v $v2
+ }
+ } {1 1}
+}
+for {set go 1; set i 1} {$go} {incr i} {
+ do_test malloc-4.$i {
+ sqlite_malloc_fail 0
+ catch {db close}
+ catch {file delete -force test.db}
+ catch {file delete -force test.db-journal}
+ sqlite_malloc_fail $i
+ set v [catch {sqlite db test.db} msg]
+ if {$v} {
+ set msg ""
+ } else {
+ set v [catch {execsql {
+ BEGIN TRANSACTION;
+ CREATE TABLE t1(a int, b int, c int);
+ CREATE INDEX i1 ON t1(a,b);
+ COPY t1 FROM 'data.tmp';
+ UPDATE t1 SET b=a WHERE a in (10,12,22);
+ INSERT INTO t1 SELECT * FROM t1
+ WHERE a IN (SELECT a FROM t1 WHERE a<10);
+ DROP INDEX i1;
+ DELETE FROM t1;
+ COMMIT;
+ }} msg]
+ }
+ set leftover [lindex [sqlite_malloc_stat] 2]
+ if {$leftover>0} {
+ if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
+ set ::go 0
+ set v {1 1}
+ } else {
+ set v2 [expr {$msg=="" || $msg=="out of memory"}]
+ if {!$v2} {puts "\nError message returned: $msg"}
+ lappend v $v2
+ }
+ } {1 1}
+}
+for {set go 1; set i 1} {$go} {incr i} {
+ do_test malloc-5.$i {
+ sqlite_malloc_fail 0
+ catch {db close}
+ catch {file delete -force test.db}
+ catch {file delete -force test.db-journal}
+ sqlite_malloc_fail $i
+ set v [catch {sqlite db test.db} msg]
+ if {$v} {
+ set msg ""
+ } else {
+ set v [catch {execsql {
+ BEGIN TRANSACTION;
+ CREATE TABLE t1(a,b);
+ CREATE TABLE t2(x,y);
+ CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO t2(x,y) VALUES(new.rowid,1);
+ END;
+ INSERT INTO t1(a,b) VALUES(2,3);
+ COMMIT;
+ }} msg]
+ }
+ set leftover [lindex [sqlite_malloc_stat] 2]
+ if {$leftover>0} {
+ if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
+ set ::go 0
+ set v {1 1}
+ } else {
+ set v2 [expr {$msg=="" || $msg=="out of memory"}]
+ if {!$v2} {puts "\nError message returned: $msg"}
+ lappend v $v2
+ }
+ } {1 1}
+}
+sqlite_malloc_fail 0
+finish_test
diff --git a/usr/src/lib/libsqlite/test/memdb.test b/usr/src/lib/libsqlite/test/memdb.test
new file mode 100644
index 0000000000..c70d60c4d3
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/memdb.test
@@ -0,0 +1,399 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 in-memory database backend.
+#
+# $Id: memdb.test,v 1.6 2003/08/05 13:13:39 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# In the following sequence of tests, compute the MD5 sum of the content
+# of a table, make lots of modifications to that table, then do a rollback.
+# Verify that after the rollback, the MD5 checksum is unchanged.
+#
+# These tests were browed from trans.tcl.
+#
+do_test memdb-1.1 {
+ db close
+ sqlite db :memory:
+ # sqlite db test.db
+ execsql {
+ BEGIN;
+ CREATE TABLE t3(x TEXT);
+ INSERT INTO t3 VALUES(randstr(10,400));
+ INSERT INTO t3 VALUES(randstr(10,400));
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ COMMIT;
+ SELECT count(*) FROM t3;
+ }
+} {1024}
+
+# The following procedure computes a "signature" for table "t3". If
+# T3 changes in any way, the signature should change.
+#
+# This is used to test ROLLBACK. We gather a signature for t3, then
+# make lots of changes to t3, then rollback and take another signature.
+# The two signatures should be the same.
+#
+proc signature {{fn {}}} {
+ set rx [db eval {SELECT x FROM t3}]
+ # set r1 [md5 $rx\n]
+ if {$fn!=""} {
+ # set fd [open $fn w]
+ # puts $fd $rx
+ # close $fd
+ }
+ # set r [db eval {SELECT count(*), md5sum(x) FROM t3}]
+ # puts "SIG($fn)=$r1"
+ return [list [string length $rx] $rx]
+}
+
+# Do rollbacks. Make sure the signature does not change.
+#
+set limit 10
+for {set i 2} {$i<=$limit} {incr i} {
+ set ::sig [signature one]
+ # puts "sig=$sig"
+ set cnt [lindex $::sig 0]
+ set ::journal_format [expr {($i%3)+1}]
+ if {$i%2==0} {
+ execsql {PRAGMA synchronous=FULL}
+ } else {
+ execsql {PRAGMA synchronous=NORMAL}
+ }
+ do_test memdb-1.$i.1-$cnt {
+ execsql {
+ BEGIN;
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ ROLLBACK;
+ }
+ set sig2 [signature two]
+ } $sig
+ # puts "sig2=$sig2"
+ # if {$sig2!=$sig} exit
+ do_test memdb-1.$i.2-$cnt {
+ execsql {
+ BEGIN;
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ ROLLBACK;
+ }
+ signature
+ } $sig
+ if {$i<$limit} {
+ do_test memdb-1.$i.9-$cnt {
+ execsql {
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0;
+ }
+ } {}
+ }
+ set ::pager_old_format 0
+}
+
+do_test memdb-2.1 {
+ execsql {
+ PRAGMA integrity_check
+ }
+} {ok}
+
+do_test memdb-3.1 {
+ execsql {
+ CREATE TABLE t4(a,b,c,d);
+ BEGIN;
+ INSERT INTO t4 VALUES(1,2,3,4);
+ SELECT * FROM t4;
+ }
+} {1 2 3 4}
+do_test memdb-3.2 {
+ execsql {
+ SELECT name FROM sqlite_master WHERE type='table';
+ }
+} {t3 t4}
+do_test memdb-3.3 {
+ execsql {
+ DROP TABLE t4;
+ SELECT name FROM sqlite_master WHERE type='table';
+ }
+} {t3}
+do_test memdb-3.4 {
+ execsql {
+ ROLLBACK;
+ SELECT name FROM sqlite_master WHERE type='table';
+ }
+} {t3 t4}
+
+# Create tables for the first group of tests.
+#
+do_test memdb-4.0 {
+ execsql {
+ CREATE TABLE t1(a, b, c, UNIQUE(a,b));
+ CREATE TABLE t2(x);
+ SELECT c FROM t1 ORDER BY c;
+ }
+} {}
+
+# Six columns of configuration data as follows:
+#
+# i The reference number of the test
+# conf The conflict resolution algorithm on the BEGIN statement
+# cmd An INSERT or REPLACE command to execute against table t1
+# t0 True if there is an error from $cmd
+# t1 Content of "c" column of t1 assuming no error in $cmd
+# t2 Content of "x" column of t2
+#
+foreach {i conf cmd t0 t1 t2} {
+ 1 {} INSERT 1 {} 1
+ 2 {} {INSERT OR IGNORE} 0 3 1
+ 3 {} {INSERT OR REPLACE} 0 4 1
+ 4 {} REPLACE 0 4 1
+ 5 {} {INSERT OR FAIL} 1 {} 1
+ 6 {} {INSERT OR ABORT} 1 {} 1
+ 7 {} {INSERT OR ROLLBACK} 1 {} {}
+ 8 IGNORE INSERT 0 3 1
+ 9 IGNORE {INSERT OR IGNORE} 0 3 1
+ 10 IGNORE {INSERT OR REPLACE} 0 4 1
+ 11 IGNORE REPLACE 0 4 1
+ 12 IGNORE {INSERT OR FAIL} 1 {} 1
+ 13 IGNORE {INSERT OR ABORT} 1 {} 1
+ 14 IGNORE {INSERT OR ROLLBACK} 1 {} {}
+ 15 REPLACE INSERT 0 4 1
+ 16 FAIL INSERT 1 {} 1
+ 17 ABORT INSERT 1 {} 1
+ 18 ROLLBACK INSERT 1 {} {}
+} {
+ do_test memdb-4.$i {
+ if {$conf!=""} {set conf "ON CONFLICT $conf"}
+ set r0 [catch {execsql [subst {
+ DELETE FROM t1;
+ DELETE FROM t2;
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN $conf;
+ INSERT INTO t2 VALUES(1);
+ $cmd INTO t1 VALUES(1,2,4);
+ }]} r1]
+ catch {execsql {COMMIT}}
+ if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
+ set r2 [execsql {SELECT x FROM t2}]
+ list $r0 $r1 $r2
+ } [list $t0 $t1 $t2]
+}
+
+do_test memdb-5.0 {
+ execsql {
+ DROP TABLE t2;
+ DROP TABLE t3;
+ CREATE TABLE t2(a,b,c);
+ INSERT INTO t2 VALUES(1,2,1);
+ INSERT INTO t2 VALUES(2,3,2);
+ INSERT INTO t2 VALUES(3,4,1);
+ INSERT INTO t2 VALUES(4,5,4);
+ SELECT c FROM t2 ORDER BY b;
+ CREATE TABLE t3(x);
+ INSERT INTO t3 VALUES(1);
+ }
+} {1 2 1 4}
+
+# Six columns of configuration data as follows:
+#
+# i The reference number of the test
+# conf1 The conflict resolution algorithm on the UNIQUE constraint
+# conf2 The conflict resolution algorithm on the BEGIN statement
+# cmd An UPDATE command to execute against table t1
+# t0 True if there is an error from $cmd
+# t1 Content of "b" column of t1 assuming no error in $cmd
+# t2 Content of "x" column of t3
+#
+foreach {i conf1 conf2 cmd t0 t1 t2} {
+ 1 {} {} UPDATE 1 {6 7 8 9} 1
+ 2 REPLACE {} UPDATE 0 {7 6 9} 1
+ 3 IGNORE {} UPDATE 0 {6 7 3 9} 1
+ 4 FAIL {} UPDATE 1 {6 7 3 4} 1
+ 5 ABORT {} UPDATE 1 {1 2 3 4} 1
+ 6 ROLLBACK {} UPDATE 1 {1 2 3 4} 0
+ 7 REPLACE {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
+ 8 IGNORE {} {UPDATE OR REPLACE} 0 {7 6 9} 1
+ 9 FAIL {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
+ 10 ABORT {} {UPDATE OR REPLACE} 0 {7 6 9} 1
+ 11 ROLLBACK {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
+ 12 {} {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
+ 13 {} {} {UPDATE OR REPLACE} 0 {7 6 9} 1
+ 14 {} {} {UPDATE OR FAIL} 1 {6 7 3 4} 1
+ 15 {} {} {UPDATE OR ABORT} 1 {1 2 3 4} 1
+ 16 {} {} {UPDATE OR ROLLBACK} 1 {1 2 3 4} 0
+ 17 {} IGNORE UPDATE 0 {6 7 3 9} 1
+ 18 {} REPLACE UPDATE 0 {7 6 9} 1
+ 19 {} FAIL UPDATE 1 {6 7 3 4} 1
+ 20 {} ABORT UPDATE 1 {1 2 3 4} 1
+ 21 {} ROLLBACK UPDATE 1 {1 2 3 4} 0
+ 22 REPLACE IGNORE UPDATE 0 {6 7 3 9} 1
+ 23 IGNORE REPLACE UPDATE 0 {7 6 9} 1
+ 24 REPLACE FAIL UPDATE 1 {6 7 3 4} 1
+ 25 IGNORE ABORT UPDATE 1 {1 2 3 4} 1
+ 26 REPLACE ROLLBACK UPDATE 1 {1 2 3 4} 0
+} {
+ if {$t0} {set t1 {column a is not unique}}
+ do_test memdb-5.$i {
+ if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
+ if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
+ set r0 [catch {execsql [subst {
+ DROP TABLE t1;
+ CREATE TABLE t1(a,b,c, UNIQUE(a) $conf1);
+ INSERT INTO t1 SELECT * FROM t2;
+ UPDATE t3 SET x=0;
+ BEGIN $conf2;
+ $cmd t3 SET x=1;
+ $cmd t1 SET b=b*2;
+ $cmd t1 SET a=c+5;
+ }]} r1]
+ catch {execsql {COMMIT}}
+ if {!$r0} {set r1 [execsql {SELECT a FROM t1 ORDER BY b}]}
+ set r2 [execsql {SELECT x FROM t3}]
+ list $r0 $r1 $r2
+ } [list $t0 $t1 $t2]
+}
+
+do_test memdb-6.1 {
+ execsql {
+ SELECT * FROM t2;
+ }
+} {1 2 1 2 3 2 3 4 1 4 5 4}
+do_test memdb-6.2 {
+ execsql {
+ BEGIN;
+ DROP TABLE t2;
+ SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1;
+ }
+} {t1 t3 t4}
+do_test memdb-6.3 {
+ execsql {
+ ROLLBACK;
+ SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1;
+ }
+} {t1 t2 t3 t4}
+do_test memdb-6.4 {
+ execsql {
+ SELECT * FROM t2;
+ }
+} {1 2 1 2 3 2 3 4 1 4 5 4}
+do_test memdb-6.5 {
+ execsql {
+ SELECT a FROM t2 UNION SELECT b FROM t2 ORDER BY 1;
+ }
+} {1 2 3 4 5}
+do_test memdb-6.6 {
+ execsql {
+ CREATE INDEX i2 ON t2(c);
+ SELECT a FROM t2 ORDER BY c;
+ }
+} {1 3 2 4}
+do_test memdb-6.6 {
+ execsql {
+ SELECT a FROM t2 ORDER BY c DESC;
+ }
+} {4 2 3 1}
+do_test memdb-6.7 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t5(x,y);
+ INSERT INTO t5 VALUES(1,2);
+ SELECT * FROM t5;
+ }
+} {1 2}
+do_test memdb-6.8 {
+ execsql {
+ SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1;
+ }
+} {t1 t2 t3 t4 t5}
+do_test memdb-6.9 {
+ execsql {
+ ROLLBACK;
+ SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1;
+ }
+} {t1 t2 t3 t4}
+do_test memdb-6.10 {
+ execsql {
+ CREATE TABLE t5(x PRIMARY KEY, y UNIQUE);
+ SELECT * FROM t5;
+ }
+} {}
+do_test memdb-6.11 {
+ execsql {
+ SELECT * FROM t5 ORDER BY y DESC;
+ }
+} {}
+do_test memdb-6.12 {
+ execsql {
+ INSERT INTO t5 VALUES(1,2);
+ INSERT INTO t5 VALUES(3,4);
+ REPLACE INTO t5 VALUES(1,4);
+ SELECT rowid,* FROM t5;
+ }
+} {3 1 4}
+do_test memdb-6.13 {
+ execsql {
+ DELETE FROM t5 WHERE x>5;
+ SELECT * FROM t5;
+ }
+} {1 4}
+do_test memdb-6.14 {
+ execsql {
+ DELETE FROM t5 WHERE y<3;
+ SELECT * FROM t5;
+ }
+} {1 4}
+do_test memdb-6.15 {
+ execsql {
+ DELETE FROM t5 WHERE x>0;
+ SELECT * FROM t5;
+ }
+} {}
+
+do_test memdb-7.1 {
+ execsql {
+ CREATE TABLE t6(x);
+ INSERT INTO t6 VALUES(1);
+ INSERT INTO t6 SELECT x+1 FROM t6;
+ INSERT INTO t6 SELECT x+2 FROM t6;
+ INSERT INTO t6 SELECT x+4 FROM t6;
+ INSERT INTO t6 SELECT x+8 FROM t6;
+ INSERT INTO t6 SELECT x+16 FROM t6;
+ INSERT INTO t6 SELECT x+32 FROM t6;
+ INSERT INTO t6 SELECT x+64 FROM t6;
+ INSERT INTO t6 SELECT x+128 FROM t6;
+ SELECT count(*) FROM (SELECT DISTINCT x FROM t6);
+ }
+} {256}
+for {set i 1} {$i<=256} {incr i} {
+ do_test memdb-7.2.$i {
+ execsql "DELETE FROM t6 WHERE x=\
+ (SELECT x FROM t6 ORDER BY random() LIMIT 1)"
+ execsql {SELECT count(*) FROM t6}
+ } [expr {256-$i}]
+}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/memleak.test b/usr/src/lib/libsqlite/test/memleak.test
new file mode 100644
index 0000000000..96c7783481
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/memleak.test
@@ -0,0 +1,94 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 runs all tests.
+#
+# $Id: memleak.test,v 1.3 2004/02/12 18:46:39 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+rename finish_test really_finish_test
+proc finish_test {} {
+ catch {db close}
+ memleak_check
+}
+
+if {[file exists ./sqlite_test_count]} {
+ set COUNT [exec cat ./sqlite_test_count]
+} else {
+ set COUNT 3
+}
+
+# LeakList will hold a list of the number of unfreed mallocs after
+# each round of the test. This number should be constant. If it
+# grows, it may mean there is a memory leak in the library.
+#
+set LeakList {}
+
+set EXCLUDE {
+ all.test
+ quick.test
+ malloc.test
+ misuse.test
+ memleak.test
+ btree2.test
+ trans.test
+}
+if {[sqlite -has-codec]} {
+ lappend EXCLUDE \
+ attach.test \
+ attach2.test \
+ auth.test \
+ format3.test \
+ version.test
+}
+if {[llength $argv]>0} {
+ set FILELIST $argv
+ set argv {}
+} else {
+ set FILELIST [lsort -dictionary [glob $testdir/*.test]]
+}
+
+foreach testfile $FILELIST {
+ set tail [file tail $testfile]
+ if {[lsearch -exact $EXCLUDE $tail]>=0} continue
+ set LeakList {}
+ for {set COUNTER 0} {$COUNTER<$COUNT} {incr COUNTER} {
+ source $testfile
+ if {[info exists Leak]} {
+ lappend LeakList $Leak
+ }
+ }
+ if {$LeakList!=""} {
+ puts -nonewline memory-leak-test-$tail...
+ incr ::nTest
+ foreach x $LeakList {
+ if {$x!=[lindex $LeakList 0]} {
+ puts " failed! ($LeakList)"
+ incr ::nErr
+ lappend ::failList memory-leak-test-$tail
+ break
+ }
+ }
+ puts " Ok"
+ }
+}
+really_finish_test
+
+# Run the malloc tests and the misuse test after memory leak detection.
+# Both tests leak memory.
+#
+#catch {source $testdir/misuse.test}
+#catch {source $testdir/malloc.test}
+
+really_finish_test
diff --git a/usr/src/lib/libsqlite/test/minmax.test b/usr/src/lib/libsqlite/test/minmax.test
new file mode 100644
index 0000000000..8235983f0d
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/minmax.test
@@ -0,0 +1,362 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 SELECT statements that contain
+# aggregate min() and max() functions and which are handled as
+# as a special case.
+#
+# $Id: minmax.test,v 1.9.2.2 2004/07/18 21:14:05 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test minmax-1.0 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t1(x, y);
+ INSERT INTO t1 VALUES(1,1);
+ INSERT INTO t1 VALUES(2,2);
+ INSERT INTO t1 VALUES(3,2);
+ INSERT INTO t1 VALUES(4,3);
+ INSERT INTO t1 VALUES(5,3);
+ INSERT INTO t1 VALUES(6,3);
+ INSERT INTO t1 VALUES(7,3);
+ INSERT INTO t1 VALUES(8,4);
+ INSERT INTO t1 VALUES(9,4);
+ INSERT INTO t1 VALUES(10,4);
+ INSERT INTO t1 VALUES(11,4);
+ INSERT INTO t1 VALUES(12,4);
+ INSERT INTO t1 VALUES(13,4);
+ INSERT INTO t1 VALUES(14,4);
+ INSERT INTO t1 VALUES(15,4);
+ INSERT INTO t1 VALUES(16,5);
+ INSERT INTO t1 VALUES(17,5);
+ INSERT INTO t1 VALUES(18,5);
+ INSERT INTO t1 VALUES(19,5);
+ INSERT INTO t1 VALUES(20,5);
+ COMMIT;
+ SELECT DISTINCT y FROM t1 ORDER BY y;
+ }
+} {1 2 3 4 5}
+
+do_test minmax-1.1 {
+ set sqlite_search_count 0
+ execsql {SELECT min(x) FROM t1}
+} {1}
+do_test minmax-1.2 {
+ set sqlite_search_count
+} {19}
+do_test minmax-1.3 {
+ set sqlite_search_count 0
+ execsql {SELECT max(x) FROM t1}
+} {20}
+do_test minmax-1.4 {
+ set sqlite_search_count
+} {19}
+do_test minmax-1.5 {
+ execsql {CREATE INDEX t1i1 ON t1(x)}
+ set sqlite_search_count 0
+ execsql {SELECT min(x) FROM t1}
+} {1}
+do_test minmax-1.6 {
+ set sqlite_search_count
+} {2}
+do_test minmax-1.7 {
+ set sqlite_search_count 0
+ execsql {SELECT max(x) FROM t1}
+} {20}
+do_test minmax-1.8 {
+ set sqlite_search_count
+} {1}
+do_test minmax-1.9 {
+ set sqlite_search_count 0
+ execsql {SELECT max(y) FROM t1}
+} {5}
+do_test minmax-1.10 {
+ set sqlite_search_count
+} {19}
+
+do_test minmax-2.0 {
+ execsql {
+ CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
+ INSERT INTO t2 SELECT * FROM t1;
+ }
+ set sqlite_search_count 0
+ execsql {SELECT min(a) FROM t2}
+} {1}
+do_test minmax-2.1 {
+ set sqlite_search_count
+} {0}
+do_test minmax-2.2 {
+ set sqlite_search_count 0
+ execsql {SELECT max(a) FROM t2}
+} {20}
+do_test minmax-2.3 {
+ set sqlite_search_count
+} {0}
+
+do_test minmax-3.0 {
+ execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)}
+ set sqlite_search_count 0
+ execsql {SELECT max(a) FROM t2}
+} {21}
+do_test minmax-3.1 {
+ set sqlite_search_count
+} {0}
+do_test minmax-3.2 {
+ execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)}
+ set sqlite_search_count 0
+ execsql {
+ SELECT b FROM t2 WHERE a=(SELECT max(a) FROM t2)
+ }
+} {999}
+do_test minmax-3.3 {
+ set sqlite_search_count
+} {0}
+
+do_test minmax-4.1 {
+ execsql {
+ SELECT coalesce(min(x+0),-1), coalesce(max(x+0),-1) FROM
+ (SELECT * FROM t1 UNION SELECT NULL as 'x', NULL as 'y')
+ }
+} {1 20}
+do_test minmax-4.2 {
+ execsql {
+ SELECT y, sum(x) FROM
+ (SELECT null, y+1 FROM t1 UNION SELECT * FROM t1)
+ GROUP BY y ORDER BY y;
+ }
+} {1 1 2 5 3 22 4 92 5 90 6 0}
+do_test minmax-4.3 {
+ execsql {
+ SELECT y, count(x), count(*) FROM
+ (SELECT null, y+1 FROM t1 UNION SELECT * FROM t1)
+ GROUP BY y ORDER BY y;
+ }
+} {1 1 1 2 2 3 3 4 5 4 8 9 5 5 6 6 0 1}
+
+# Make sure the min(x) and max(x) optimizations work on empty tables
+# including empty tables with indices. Ticket #296.
+#
+do_test minmax-5.1 {
+ execsql {
+ CREATE TABLE t3(x INTEGER UNIQUE NOT NULL);
+ SELECT coalesce(min(x),999) FROM t3;
+ }
+} {999}
+do_test minmax-5.2 {
+ execsql {
+ SELECT coalesce(min(rowid),999) FROM t3;
+ }
+} {999}
+do_test minmax-5.3 {
+ execsql {
+ SELECT coalesce(max(x),999) FROM t3;
+ }
+} {999}
+do_test minmax-5.4 {
+ execsql {
+ SELECT coalesce(max(rowid),999) FROM t3;
+ }
+} {999}
+do_test minmax-5.5 {
+ execsql {
+ SELECT coalesce(max(rowid),999) FROM t3 WHERE rowid<25;
+ }
+} {999}
+
+# Make sure the min(x) and max(x) optimizations work when there
+# is a LIMIT clause. Ticket #396.
+#
+do_test minmax-6.1 {
+ execsql {
+ SELECT min(a) FROM t2 LIMIT 1
+ }
+} {1}
+do_test minmax-6.2 {
+ execsql {
+ SELECT max(a) FROM t2 LIMIT 3
+ }
+} {22}
+do_test minmax-6.3 {
+ execsql {
+ SELECT min(a) FROM t2 LIMIT 0,100
+ }
+} {1}
+do_test minmax-6.4 {
+ execsql {
+ SELECT max(a) FROM t2 LIMIT 1,100
+ }
+} {}
+do_test minmax-6.5 {
+ execsql {
+ SELECT min(x) FROM t3 LIMIT 1
+ }
+} {{}}
+do_test minmax-6.6 {
+ execsql {
+ SELECT max(x) FROM t3 LIMIT 0
+ }
+} {}
+do_test minmax-6.7 {
+ execsql {
+ SELECT max(a) FROM t2 LIMIT 0
+ }
+} {}
+
+# Make sure the max(x) and min(x) optimizations work for nested
+# queries. Ticket #587.
+#
+do_test minmax-7.1 {
+ execsql {
+ SELECT max(x) FROM t1;
+ }
+} 20
+do_test minmax-7.2 {
+ execsql {
+ SELECT * FROM (SELECT max(x) FROM t1);
+ }
+} 20
+do_test minmax-7.3 {
+ execsql {
+ SELECT min(x) FROM t1;
+ }
+} 1
+do_test minmax-7.4 {
+ execsql {
+ SELECT * FROM (SELECT min(x) FROM t1);
+ }
+} 1
+
+# Make sure min(x) and max(x) work correctly when the datatype is
+# TEXT instead of NUMERIC. Ticket #623.
+#
+do_test minmax-8.1 {
+ execsql {
+ CREATE TABLE t4(a TEXT);
+ INSERT INTO t4 VALUES('1234');
+ INSERT INTO t4 VALUES('234');
+ INSERT INTO t4 VALUES('34');
+ SELECT min(a), max(a) FROM t4;
+ }
+} {1234 34}
+do_test minmax-8.2 {
+ execsql {
+ CREATE TABLE t5(a INTEGER);
+ INSERT INTO t5 VALUES('1234');
+ INSERT INTO t5 VALUES('234');
+ INSERT INTO t5 VALUES('34');
+ SELECT min(a), max(a) FROM t5;
+ }
+} {34 1234}
+
+# Ticket #658: Test the min()/max() optimization when the FROM clause
+# is a subquery.
+#
+do_test minmax-9.1 {
+ execsql {
+ SELECT max(rowid) FROM (
+ SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5
+ )
+ }
+} {1}
+do_test minmax-9.2 {
+ execsql {
+ SELECT max(rowid) FROM (
+ SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5
+ )
+ }
+} {{}}
+
+# If there is a NULL in an aggregate max() or min(), ignore it. An
+# aggregate min() or max() will only return NULL if all values are NULL.
+#
+do_test minmax-10.1 {
+ execsql {
+ CREATE TABLE t6(x);
+ INSERT INTO t6 VALUES(1);
+ INSERT INTO t6 VALUES(2);
+ INSERT INTO t6 VALUES(NULL);
+ SELECT coalesce(min(x),-1) FROM t6;
+ }
+} {1}
+do_test minmax-10.2 {
+ execsql {
+ SELECT max(x) FROM t6;
+ }
+} {2}
+do_test minmax-10.3 {
+ execsql {
+ CREATE INDEX i6 ON t6(x);
+ SELECT coalesce(min(x),-1) FROM t6;
+ }
+} {1}
+do_test minmax-10.4 {
+ execsql {
+ SELECT max(x) FROM t6;
+ }
+} {2}
+do_test minmax-10.5 {
+ execsql {
+ DELETE FROM t6 WHERE x NOT NULL;
+ SELECT count(*) FROM t6;
+ }
+} 1
+do_test minmax-10.6 {
+ execsql {
+ SELECT count(x) FROM t6;
+ }
+} 0
+do_test minmax-10.7 {
+ execsql {
+ SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6);
+ }
+} {{} {}}
+do_test minmax-10.8 {
+ execsql {
+ SELECT min(x), max(x) FROM t6;
+ }
+} {{} {}}
+do_test minmax-10.9 {
+ execsql {
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ INSERT INTO t6 SELECT * FROM t6;
+ SELECT count(*) FROM t6;
+ }
+} 1024
+do_test minmax-10.10 {
+ execsql {
+ SELECT count(x) FROM t6;
+ }
+} 0
+do_test minmax-10.11 {
+ execsql {
+ SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6);
+ }
+} {{} {}}
+do_test minmax-10.12 {
+ execsql {
+ SELECT min(x), max(x) FROM t6;
+ }
+} {{} {}}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/misc1.test b/usr/src/lib/libsqlite/test/misc1.test
new file mode 100644
index 0000000000..9e75a087b2
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/misc1.test
@@ -0,0 +1,543 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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.
+#
+# This file implements tests for miscellanous features that were
+# left out of other test files.
+#
+# $Id: misc1.test,v 1.23 2003/08/05 13:13:39 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Test the creation and use of tables that have a large number
+# of columns.
+#
+do_test misc1-1.1 {
+ set cmd "CREATE TABLE manycol(x0 text"
+ for {set i 1} {$i<=99} {incr i} {
+ append cmd ",x$i text"
+ }
+ append cmd ")";
+ execsql $cmd
+ set cmd "INSERT INTO manycol VALUES(0"
+ for {set i 1} {$i<=99} {incr i} {
+ append cmd ",$i"
+ }
+ append cmd ")";
+ execsql $cmd
+ execsql "SELECT x99 FROM manycol"
+} 99
+do_test misc1-1.2 {
+ execsql {SELECT x0, x10, x25, x50, x75 FROM manycol}
+} {0 10 25 50 75}
+do_test misc1-1.3.1 {
+ for {set j 100} {$j<=1000} {incr j 100} {
+ set cmd "INSERT INTO manycol VALUES($j"
+ for {set i 1} {$i<=99} {incr i} {
+ append cmd ",[expr {$i+$j}]"
+ }
+ append cmd ")"
+ execsql $cmd
+ }
+ execsql {SELECT x50 FROM manycol ORDER BY x80+0}
+} {50 150 250 350 450 550 650 750 850 950 1050}
+do_test misc1-1.3.2 {
+ execsql {SELECT x50 FROM manycol ORDER BY x80}
+} {1050 150 250 350 450 550 650 750 50 850 950}
+do_test misc1-1.4 {
+ execsql {SELECT x75 FROM manycol WHERE x50=350}
+} 375
+do_test misc1-1.5 {
+ execsql {SELECT x50 FROM manycol WHERE x99=599}
+} 550
+do_test misc1-1.6 {
+ execsql {CREATE INDEX manycol_idx1 ON manycol(x99)}
+ execsql {SELECT x50 FROM manycol WHERE x99=899}
+} 850
+do_test misc1-1.7 {
+ execsql {SELECT count(*) FROM manycol}
+} 11
+do_test misc1-1.8 {
+ execsql {DELETE FROM manycol WHERE x98=1234}
+ execsql {SELECT count(*) FROM manycol}
+} 11
+do_test misc1-1.9 {
+ execsql {DELETE FROM manycol WHERE x98=998}
+ execsql {SELECT count(*) FROM manycol}
+} 10
+do_test misc1-1.10 {
+ execsql {DELETE FROM manycol WHERE x99=500}
+ execsql {SELECT count(*) FROM manycol}
+} 10
+do_test misc1-1.11 {
+ execsql {DELETE FROM manycol WHERE x99=599}
+ execsql {SELECT count(*) FROM manycol}
+} 9
+
+# Check GROUP BY expressions that name two or more columns.
+#
+do_test misc1-2.1 {
+ execsql {
+ BEGIN TRANSACTION;
+ CREATE TABLE agger(one text, two text, three text, four text);
+ INSERT INTO agger VALUES(1, 'one', 'hello', 'yes');
+ INSERT INTO agger VALUES(2, 'two', 'howdy', 'no');
+ INSERT INTO agger VALUES(3, 'thr', 'howareya', 'yes');
+ INSERT INTO agger VALUES(4, 'two', 'lothere', 'yes');
+ INSERT INTO agger VALUES(5, 'one', 'atcha', 'yes');
+ INSERT INTO agger VALUES(6, 'two', 'hello', 'no');
+ COMMIT
+ }
+ execsql {SELECT count(*) FROM agger}
+} 6
+do_test misc1-2.2 {
+ execsql {SELECT sum(one), two, four FROM agger
+ GROUP BY two, four ORDER BY sum(one) desc}
+} {8 two no 6 one yes 4 two yes 3 thr yes}
+do_test misc1-2.3 {
+ execsql {SELECT sum((one)), (two), (four) FROM agger
+ GROUP BY (two), (four) ORDER BY sum(one) desc}
+} {8 two no 6 one yes 4 two yes 3 thr yes}
+
+# Here's a test for a bug found by Joel Lucsy. The code below
+# was causing an assertion failure.
+#
+do_test misc1-3.1 {
+ set r [execsql {
+ CREATE TABLE t1(a);
+ INSERT INTO t1 VALUES('hi');
+ PRAGMA full_column_names=on;
+ SELECT rowid, * FROM t1;
+ }]
+ lindex $r 1
+} {hi}
+
+# Here's a test for yet another bug found by Joel Lucsy. The code
+# below was causing an assertion failure.
+#
+do_test misc1-4.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t2(a);
+ INSERT INTO t2 VALUES('This is a long string to use up a lot of disk -');
+ UPDATE t2 SET a=a||a||a||a;
+ INSERT INTO t2 SELECT '1 - ' || a FROM t2;
+ INSERT INTO t2 SELECT '2 - ' || a FROM t2;
+ INSERT INTO t2 SELECT '3 - ' || a FROM t2;
+ INSERT INTO t2 SELECT '4 - ' || a FROM t2;
+ INSERT INTO t2 SELECT '5 - ' || a FROM t2;
+ INSERT INTO t2 SELECT '6 - ' || a FROM t2;
+ COMMIT;
+ SELECT count(*) FROM t2;
+ }
+} {64}
+
+# Make sure we actually see a semicolon or end-of-file in the SQL input
+# before executing a command. Thus if "WHERE" is misspelled on an UPDATE,
+# the user won't accidently update every record.
+#
+do_test misc1-5.1 {
+ catchsql {
+ CREATE TABLE t3(a,b);
+ INSERT INTO t3 VALUES(1,2);
+ INSERT INTO t3 VALUES(3,4);
+ UPDATE t3 SET a=0 WHEREwww b=2;
+ }
+} {1 {near "WHEREwww": syntax error}}
+do_test misc1-5.2 {
+ execsql {
+ SELECT * FROM t3 ORDER BY a;
+ }
+} {1 2 3 4}
+
+# Certain keywords (especially non-standard keywords like "REPLACE") can
+# also be used as identifiers. The way this works in the parser is that
+# the parser first detects a syntax error, the error handling routine
+# sees that the special keyword caused the error, then replaces the keyword
+# with "ID" and tries again.
+#
+# Check the operation of this logic.
+#
+do_test misc1-6.1 {
+ catchsql {
+ CREATE TABLE t4(
+ abort, asc, begin, cluster, conflict, copy, delimiters, desc, end,
+ explain, fail, ignore, key, offset, pragma, replace, temp,
+ vacuum, view
+ );
+ }
+} {0 {}}
+do_test misc1-6.2 {
+ catchsql {
+ INSERT INTO t4
+ VALUES(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19);
+ }
+} {0 {}}
+do_test misc1-6.3 {
+ execsql {
+ SELECT * FROM t4
+ }
+} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19}
+do_test misc1-6.4 {
+ execsql {
+ SELECT abort+asc,max(key,pragma,temp) FROM t4
+ }
+} {3 17}
+
+# Test for multi-column primary keys, and for multiple primary keys.
+#
+do_test misc1-7.1 {
+ catchsql {
+ CREATE TABLE error1(
+ a TYPE PRIMARY KEY,
+ b TYPE PRIMARY KEY
+ );
+ }
+} {1 {table "error1" has more than one primary key}}
+do_test misc1-7.2 {
+ catchsql {
+ CREATE TABLE error1(
+ a INTEGER PRIMARY KEY,
+ b TYPE PRIMARY KEY
+ );
+ }
+} {1 {table "error1" has more than one primary key}}
+do_test misc1-7.3 {
+ execsql {
+ CREATE TABLE t5(a,b,c,PRIMARY KEY(a,b));
+ INSERT INTO t5 VALUES(1,2,3);
+ SELECT * FROM t5 ORDER BY a;
+ }
+} {1 2 3}
+do_test misc1-7.4 {
+ catchsql {
+ INSERT INTO t5 VALUES(1,2,4);
+ }
+} {1 {columns a, b are not unique}}
+do_test misc1-7.5 {
+ catchsql {
+ INSERT INTO t5 VALUES(0,2,4);
+ }
+} {0 {}}
+do_test misc1-7.6 {
+ execsql {
+ SELECT * FROM t5 ORDER BY a;
+ }
+} {0 2 4 1 2 3}
+
+do_test misc1-8.1 {
+ catchsql {
+ SELECT *;
+ }
+} {1 {no tables specified}}
+do_test misc1-8.2 {
+ catchsql {
+ SELECT t1.*;
+ }
+} {1 {no such table: t1}}
+
+execsql {
+ DROP TABLE t1;
+ DROP TABLE t2;
+ DROP TABLE t3;
+ DROP TABLE t4;
+}
+
+# If an integer is too big to be represented as a 32-bit machine integer,
+# then treat it as a string.
+#
+do_test misc1-9.1 {
+ catchsql {
+ CREATE TABLE t1(a unique not null, b unique not null);
+ INSERT INTO t1 VALUES('a',12345678901234567890);
+ INSERT INTO t1 VALUES('b',12345678911234567890);
+ INSERT INTO t1 VALUES('c',12345678921234567890);
+ SELECT * FROM t1;
+ }
+} {0 {a 12345678901234567890 b 12345678911234567890 c 12345678921234567890}}
+
+# A WHERE clause is not allowed to contain more than 99 terms. Check to
+# make sure this limit is enforced.
+#
+do_test misc1-10.0 {
+ execsql {SELECT count(*) FROM manycol}
+} {9}
+do_test misc1-10.1 {
+ set ::where {WHERE x0>=0}
+ for {set i 1} {$i<=99} {incr i} {
+ append ::where " AND x$i<>0"
+ }
+ catchsql "SELECT count(*) FROM manycol $::where"
+} {0 9}
+do_test misc1-10.2 {
+ catchsql "SELECT count(*) FROM manycol $::where AND rowid>0"
+} {1 {WHERE clause too complex - no more than 100 terms allowed}}
+do_test misc1-10.3 {
+ regsub "x0>=0" $::where "x0=0" ::where
+ catchsql "DELETE FROM manycol $::where"
+} {0 {}}
+do_test misc1-10.4 {
+ execsql {SELECT count(*) FROM manycol}
+} {8}
+do_test misc1-10.5 {
+ catchsql "DELETE FROM manycol $::where AND rowid>0"
+} {1 {WHERE clause too complex - no more than 100 terms allowed}}
+do_test misc1-10.6 {
+ execsql {SELECT x1 FROM manycol WHERE x0=100}
+} {101}
+do_test misc1-10.7 {
+ regsub "x0=0" $::where "x0=100" ::where
+ catchsql "UPDATE manycol SET x1=x1+1 $::where"
+} {0 {}}
+do_test misc1-10.8 {
+ execsql {SELECT x1 FROM manycol WHERE x0=100}
+} {102}
+do_test misc1-10.9 {
+ catchsql "UPDATE manycol SET x1=x1+1 $::where AND rowid>0"
+} {1 {WHERE clause too complex - no more than 100 terms allowed}}
+do_test misc1-10.10 {
+ execsql {SELECT x1 FROM manycol WHERE x0=100}
+} {102}
+
+# Make sure the initialization works even if a database is opened while
+# another process has the database locked.
+#
+do_test misc1-11.1 {
+ execsql {BEGIN}
+ sqlite db2 test.db
+ set rc [catch {db2 eval {SELECT count(*) FROM t1}} msg]
+ lappend rc $msg
+} {1 {database is locked}}
+do_test misc1-11.2 {
+ execsql {COMMIT}
+ set rc [catch {db2 eval {SELECT count(*) FROM t1}} msg]
+ db2 close
+ lappend rc $msg
+} {0 3}
+
+# Make sure string comparisons really do compare strings in format4+.
+# Similar tests in the format3.test file show that for format3 and earlier
+# all comparisions where numeric if either operand looked like a number.
+#
+do_test misc1-12.1 {
+ execsql {SELECT '0'=='0.0'}
+} {0}
+do_test misc1-12.2 {
+ execsql {SELECT '0'==0.0}
+} {1}
+do_test misc1-12.3 {
+ execsql {SELECT '12345678901234567890'=='12345678901234567891'}
+} {0}
+do_test misc1-12.4 {
+ execsql {
+ CREATE TABLE t6(a INT UNIQUE, b TEXT UNIQUE);
+ INSERT INTO t6 VALUES('0','0.0');
+ SELECT * FROM t6;
+ }
+} {0 0.0}
+do_test misc1-12.5 {
+ execsql {
+ INSERT OR IGNORE INTO t6 VALUES(0.0,'x');
+ SELECT * FROM t6;
+ }
+} {0 0.0}
+do_test misc1-12.6 {
+ execsql {
+ INSERT OR IGNORE INTO t6 VALUES('y',0);
+ SELECT * FROM t6;
+ }
+} {0 0.0 y 0}
+do_test misc1-12.7 {
+ execsql {
+ CREATE TABLE t7(x INTEGER, y TEXT, z);
+ INSERT INTO t7 VALUES(0,0,1);
+ INSERT INTO t7 VALUES(0.0,0,2);
+ INSERT INTO t7 VALUES(0,0.0,3);
+ INSERT INTO t7 VALUES(0.0,0.0,4);
+ SELECT DISTINCT x, y FROM t7 ORDER BY z;
+ }
+} {0 0 0 0.0}
+do_test misc1-12.8 {
+ execsql {
+ SELECT min(z), max(z), count(z) FROM t7 GROUP BY x ORDER BY 1;
+ }
+} {1 4 4}
+do_test misc1-12.9 {
+ execsql {
+ SELECT min(z), max(z), count(z) FROM t7 GROUP BY y ORDER BY 1;
+ }
+} {1 2 2 3 4 2}
+
+# This used to be an error. But we changed the code so that arbitrary
+# identifiers can be used as a collating sequence. Collation is by text
+# if the identifier contains "text", "blob", or "clob" and is numeric
+# otherwise.
+do_test misc1-12.10 {
+ catchsql {
+ SELECT * FROM t6 ORDER BY a COLLATE unknown;
+ }
+} {0 {0 0.0 y 0}}
+do_test misc1-12.11 {
+ execsql {
+ CREATE TABLE t8(x TEXT COLLATE numeric, y INTEGER COLLATE text, z);
+ INSERT INTO t8 VALUES(0,0,1);
+ INSERT INTO t8 VALUES(0.0,0,2);
+ INSERT INTO t8 VALUES(0,0.0,3);
+ INSERT INTO t8 VALUES(0.0,0.0,4);
+ SELECT DISTINCT x, y FROM t8 ORDER BY z;
+ }
+} {0 0 0 0.0}
+do_test misc1-12.12 {
+ execsql {
+ SELECT min(z), max(z), count(z) FROM t8 GROUP BY x ORDER BY 1;
+ }
+} {1 4 4}
+do_test misc1-12.13 {
+ execsql {
+ SELECT min(z), max(z), count(z) FROM t8 GROUP BY y ORDER BY 1;
+ }
+} {1 2 2 3 4 2}
+
+# There was a problem with realloc() in the OP_MemStore operation of
+# the VDBE. A buffer was being reallocated but some pointers into
+# the old copy of the buffer were not being moved over to the new copy.
+# The following code tests for the problem.
+#
+do_test misc1-13.1 {
+ execsql {
+ CREATE TABLE t9(x,y);
+ INSERT INTO t9 VALUES('one',1);
+ INSERT INTO t9 VALUES('two',2);
+ INSERT INTO t9 VALUES('three',3);
+ INSERT INTO t9 VALUES('four',4);
+ INSERT INTO t9 VALUES('five',5);
+ INSERT INTO t9 VALUES('six',6);
+ INSERT INTO t9 VALUES('seven',7);
+ INSERT INTO t9 VALUES('eight',8);
+ INSERT INTO t9 VALUES('nine',9);
+ INSERT INTO t9 VALUES('ten',10);
+ INSERT INTO t9 VALUES('eleven',11);
+ SELECT y FROM t9
+ WHERE x=(SELECT x FROM t9 WHERE y=1)
+ OR x=(SELECT x FROM t9 WHERE y=2)
+ OR x=(SELECT x FROM t9 WHERE y=3)
+ OR x=(SELECT x FROM t9 WHERE y=4)
+ OR x=(SELECT x FROM t9 WHERE y=5)
+ OR x=(SELECT x FROM t9 WHERE y=6)
+ OR x=(SELECT x FROM t9 WHERE y=7)
+ OR x=(SELECT x FROM t9 WHERE y=8)
+ OR x=(SELECT x FROM t9 WHERE y=9)
+ OR x=(SELECT x FROM t9 WHERE y=10)
+ OR x=(SELECT x FROM t9 WHERE y=11)
+ OR x=(SELECT x FROM t9 WHERE y=12)
+ OR x=(SELECT x FROM t9 WHERE y=13)
+ OR x=(SELECT x FROM t9 WHERE y=14)
+ ;
+ }
+} {1 2 3 4 5 6 7 8 9 10 11}
+
+# Make sure a database connection still works after changing the
+# working directory.
+#
+do_test misc1-14.1 {
+ file mkdir tempdir
+ cd tempdir
+ execsql {BEGIN}
+ file exists ./test.db-journal
+} {0}
+do_test misc1-14.2 {
+ file exists ../test.db-journal
+} {1}
+do_test misc1-14.3 {
+ cd ..
+ file delete tempdir
+ execsql {COMMIT}
+ file exists ./test.db-journal
+} {0}
+
+# A failed create table should not leave the table in the internal
+# data structures. Ticket #238.
+#
+do_test misc1-15.1 {
+ catchsql {
+ CREATE TABLE t10 AS SELECT c1;
+ }
+} {1 {no such column: c1}}
+do_test misc1-15.2 {
+ catchsql {
+ CREATE TABLE t10 AS SELECT 1;
+ }
+ # The bug in ticket #238 causes the statement above to fail with
+ # the error "table t10 alread exists"
+} {0 {}}
+
+# Test for memory leaks when a CREATE TABLE containing a primary key
+# fails. Ticket #249.
+#
+do_test misc1-16.1 {
+ catchsql {SELECT name FROM sqlite_master LIMIT 1}
+ catchsql {
+ CREATE TABLE test(a integer, primary key(a));
+ }
+} {0 {}}
+do_test misc1-16.2 {
+ catchsql {
+ CREATE TABLE test(a integer, primary key(a));
+ }
+} {1 {table test already exists}}
+do_test misc1-16.3 {
+ catchsql {
+ CREATE TABLE test2(a text primary key, b text, primary key(a,b));
+ }
+} {1 {table "test2" has more than one primary key}}
+do_test misc1-16.4 {
+ execsql {
+ INSERT INTO test VALUES(1);
+ SELECT rowid, a FROM test;
+ }
+} {1 1}
+do_test misc1-16.5 {
+ execsql {
+ INSERT INTO test VALUES(5);
+ SELECT rowid, a FROM test;
+ }
+} {1 1 5 5}
+do_test misc1-16.6 {
+ execsql {
+ INSERT INTO test VALUES(NULL);
+ SELECT rowid, a FROM test;
+ }
+} {1 1 5 5 6 6}
+
+# Ticket #333: Temp triggers that modify persistent tables.
+#
+do_test misc1-17.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE RealTable(TestID INTEGER PRIMARY KEY, TestString TEXT);
+ CREATE TEMP TABLE TempTable(TestID INTEGER PRIMARY KEY, TestString TEXT);
+ CREATE TEMP TRIGGER trigTest_1 AFTER UPDATE ON TempTable BEGIN
+ INSERT INTO RealTable(TestString)
+ SELECT new.TestString FROM TempTable LIMIT 1;
+ END;
+ INSERT INTO TempTable(TestString) VALUES ('1');
+ INSERT INTO TempTable(TestString) VALUES ('2');
+ UPDATE TempTable SET TestString = TestString + 1 WHERE TestID IN (1, 2);
+ COMMIT;
+ SELECT TestString FROM RealTable ORDER BY 1;
+ }
+} {2 3}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/misc2.test b/usr/src/lib/libsqlite/test/misc2.test
new file mode 100644
index 0000000000..23ddc3dfef
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/misc2.test
@@ -0,0 +1,238 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2003 June 21
+#
+# 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.
+#
+# This file implements tests for miscellanous features that were
+# left out of other test files.
+#
+# $Id: misc2.test,v 1.11 2003/12/17 23:57:36 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Test for ticket #360
+#
+do_test misc2-1.1 {
+ catchsql {
+ CREATE TABLE FOO(bar integer);
+ CREATE TRIGGER foo_insert BEFORE INSERT ON foo BEGIN
+ SELECT CASE WHEN (NOT new.bar BETWEEN 0 AND 20)
+ THEN raise(rollback, 'aiieee') END;
+ END;
+ INSERT INTO foo(bar) VALUES (1);
+ }
+} {0 {}}
+do_test misc2-1.2 {
+ catchsql {
+ INSERT INTO foo(bar) VALUES (111);
+ }
+} {1 aiieee}
+
+# Make sure ROWID works on a view and a subquery. Ticket #364
+#
+do_test misc2-2.1 {
+ execsql {
+ CREATE TABLE t1(a,b,c);
+ INSERT INTO t1 VALUES(1,2,3);
+ CREATE TABLE t2(a,b,c);
+ INSERT INTO t2 VALUES(7,8,9);
+ SELECT rowid, * FROM (SELECT * FROM t1, t2);
+ }
+} {{} 1 2 3 7 8 9}
+do_test misc2-2.2 {
+ execsql {
+ CREATE VIEW v1 AS SELECT * FROM t1, t2;
+ SELECT rowid, * FROM v1;
+ }
+} {{} 1 2 3 7 8 9}
+
+# Check name binding precedence. Ticket #387
+#
+do_test misc2-3.1 {
+ catchsql {
+ SELECT t1.b+t2.b AS a, t1.a, t2.a FROM t1, t2 WHERE a==10
+ }
+} {1 {ambiguous column name: a}}
+
+# Make sure 32-bit integer overflow is handled properly in queries.
+# ticket #408
+#
+do_test misc2-4.1 {
+ execsql {
+ INSERT INTO t1 VALUES(4000000000,'a','b');
+ SELECT a FROM t1 WHERE a>1;
+ }
+} {4000000000}
+do_test misc2-4.2 {
+ execsql {
+ INSERT INTO t1 VALUES(2147483648,'b2','c2');
+ INSERT INTO t1 VALUES(2147483647,'b3','c3');
+ SELECT a FROM t1 WHERE a>2147483647;
+ }
+} {4000000000 2147483648}
+do_test misc2-4.3 {
+ execsql {
+ SELECT a FROM t1 WHERE a<2147483648;
+ }
+} {1 2147483647}
+do_test misc2-4.4 {
+ execsql {
+ SELECT a FROM t1 WHERE a<=2147483648;
+ }
+} {1 2147483648 2147483647}
+do_test misc2-4.5 {
+ execsql {
+ SELECT a FROM t1 WHERE a<10000000000;
+ }
+} {1 4000000000 2147483648 2147483647}
+do_test misc2-4.6 {
+ execsql {
+ SELECT a FROM t1 WHERE a<1000000000000 ORDER BY 1;
+ }
+} {1 2147483647 2147483648 4000000000}
+
+# There were some issues with expanding a SrcList object using a call
+# to sqliteSrcListAppend() if the SrcList had previously been duplicated
+# using a call to sqliteSrcListDup(). Ticket #416. The following test
+# makes sure the problem has been fixed.
+#
+do_test misc2-5.1 {
+ execsql {
+ CREATE TABLE x(a,b);
+ CREATE VIEW y AS
+ SELECT x1.b AS p, x2.b AS q FROM x AS x1, x AS x2 WHERE x1.a=x2.a;
+ CREATE VIEW z AS
+ SELECT y1.p, y2.p FROM y AS y1, y AS y2 WHERE y1.q=y2.q;
+ SELECT * from z;
+ }
+} {}
+
+# Make sure we can open a database with an empty filename. What this
+# does is store the database in a temporary file that is deleted when
+# the database is closed. Ticket #432.
+#
+do_test misc2-6.1 {
+ db close
+ sqlite db {}
+ execsql {
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1 VALUES(1,2);
+ SELECT * FROM t1;
+ }
+} {1 2}
+
+# Make sure we get an error message (not a segfault) on an attempt to
+# update a table from within the callback of a select on that same
+# table.
+#
+do_test misc2-7.1 {
+ db close
+ file delete -force test.db
+ sqlite db test.db
+ execsql {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(1);
+ }
+ set rc [catch {
+ db eval {SELECT rowid FROM t1} {} {
+ db eval "DELETE FROM t1 WHERE rowid=$rowid"
+ }
+ } msg]
+ lappend rc $msg
+} {1 {database table is locked}}
+do_test misc2-7.2 {
+ set rc [catch {
+ db eval {SELECT rowid FROM t1} {} {
+ db eval "INSERT INTO t1 VALUES(3)"
+ }
+ } msg]
+ lappend rc $msg
+} {1 {database table is locked}}
+do_test misc2-7.3 {
+ db close
+ file delete -force test.db
+ sqlite db :memory:
+ execsql {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(1);
+ }
+ set rc [catch {
+ db eval {SELECT rowid FROM t1} {} {
+ db eval "DELETE FROM t1 WHERE rowid=$rowid"
+ }
+ } msg]
+ lappend rc $msg
+} {1 {database table is locked}}
+do_test misc2-7.4 {
+ set rc [catch {
+ db eval {SELECT rowid FROM t1} {} {
+ db eval "INSERT INTO t1 VALUES(3)"
+ }
+ } msg]
+ lappend rc $msg
+} {1 {database table is locked}}
+
+# Ticket #453. If the SQL ended with "-", the tokenizer was calling that
+# an incomplete token, which caused problem. The solution was to just call
+# it a minus sign.
+#
+do_test misc2-8.1 {
+ catchsql {-}
+} {1 {near "-": syntax error}}
+
+# Ticket #513. Make sure the VDBE stack does not grow on a 3-way join.
+#
+do_test misc2-9.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE counts(n INTEGER PRIMARY KEY);
+ INSERT INTO counts VALUES(0);
+ INSERT INTO counts VALUES(1);
+ INSERT INTO counts SELECT n+2 FROM counts;
+ INSERT INTO counts SELECT n+4 FROM counts;
+ INSERT INTO counts SELECT n+8 FROM counts;
+ COMMIT;
+
+ CREATE TEMP TABLE x AS
+ SELECT dim1.n, dim2.n, dim3.n
+ FROM counts AS dim1, counts AS dim2, counts AS dim3
+ WHERE dim1.n<10 AND dim2.n<10 AND dim3.n<10;
+
+ SELECT count(*) FROM x;
+ }
+} {1000}
+do_test misc2-9.2 {
+ execsql {
+ DROP TABLE x;
+ CREATE TEMP TABLE x AS
+ SELECT dim1.n, dim2.n, dim3.n
+ FROM counts AS dim1, counts AS dim2, counts AS dim3
+ WHERE dim1.n>=6 AND dim2.n>=6 AND dim3.n>=6;
+
+ SELECT count(*) FROM x;
+ }
+} {1000}
+do_test misc2-9.3 {
+ execsql {
+ DROP TABLE x;
+ CREATE TEMP TABLE x AS
+ SELECT dim1.n, dim2.n, dim3.n, dim4.n
+ FROM counts AS dim1, counts AS dim2, counts AS dim3, counts AS dim4
+ WHERE dim1.n<5 AND dim2.n<5 AND dim3.n<5 AND dim4.n<5;
+
+ SELECT count(*) FROM x;
+ }
+} [expr 5*5*5*5]
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/misc3.test b/usr/src/lib/libsqlite/test/misc3.test
new file mode 100644
index 0000000000..a91da5feb9
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/misc3.test
@@ -0,0 +1,307 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2003 December 17
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+# This file implements tests for miscellanous features that were
+# left out of other test files.
+#
+# $Id: misc3.test,v 1.10 2004/03/17 23:32:08 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Ticket #529. Make sure an ABORT does not damage the in-memory cache
+# that will be used by subsequent statements in the same transaction.
+#
+do_test misc3-1.1 {
+ execsql {
+ CREATE TABLE t1(a UNIQUE,b);
+ INSERT INTO t1
+ VALUES(1,'a23456789_b23456789_c23456789_d23456789_e23456789_');
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ UPDATE t1 SET b=b||b;
+ INSERT INTO t1 VALUES(2,'x');
+ UPDATE t1 SET b=substr(b,1,500);
+ BEGIN;
+ }
+ catchsql {UPDATE t1 SET a=CASE a WHEN 2 THEN 1 ELSE a END, b='y';}
+ execsql {
+ CREATE TABLE t2(x,y);
+ COMMIT;
+ PRAGMA integrity_check;
+ }
+} ok
+do_test misc3-1.2 {
+ execsql {
+ DROP TABLE t1;
+ DROP TABLE t2;
+ VACUUM;
+ CREATE TABLE t1(a UNIQUE,b);
+ INSERT INTO t1
+ VALUES(1,'a23456789_b23456789_c23456789_d23456789_e23456789_');
+ INSERT INTO t1 SELECT a+1, b||b FROM t1;
+ INSERT INTO t1 SELECT a+2, b||b FROM t1;
+ INSERT INTO t1 SELECT a+4, b FROM t1;
+ INSERT INTO t1 SELECT a+8, b FROM t1;
+ INSERT INTO t1 SELECT a+16, b FROM t1;
+ INSERT INTO t1 SELECT a+32, b FROM t1;
+ INSERT INTO t1 SELECT a+64, b FROM t1;
+
+ BEGIN;
+ }
+ catchsql {UPDATE t1 SET a=CASE a WHEN 128 THEN 127 ELSE a END, b='';}
+ execsql {
+ INSERT INTO t1 VALUES(200,'hello out there');
+ COMMIT;
+ PRAGMA integrity_check;
+ }
+} ok
+
+# Tests of the sqliteAtoF() function in util.c
+#
+do_test misc3-2.1 {
+ execsql {SELECT 2e-25*0.5e25}
+} 1
+do_test misc3-2.2 {
+ execsql {SELECT 2.0e-25*000000.500000000000000000000000000000e+00025}
+} 1
+do_test misc3-2.3 {
+ execsql {SELECT 000000000002e-0000000025*0.5e25}
+} 1
+do_test misc3-2.4 {
+ execsql {SELECT 2e-25*0.5e250}
+} 1e+225
+do_test misc3-2.5 {
+ execsql {SELECT 2.0e-250*0.5e25}
+} 1e-225
+do_test misc3-2.6 {
+ execsql {SELECT '-2.0e-127' * '-0.5e27'}
+} 1e-100
+do_test misc3-2.7 {
+ execsql {SELECT '+2.0e-127' * '-0.5e27'}
+} -1e-100
+do_test misc3-2.8 {
+ execsql {SELECT 2.0e-27 * '+0.5e+127'}
+} 1e+100
+do_test misc3-2.9 {
+ execsql {SELECT 2.0e-27 * '+0.000005e+132'}
+} 1e+100
+
+# Ticket #522. Make sure integer overflow is handled properly in
+# indices.
+#
+do_test misc3-3.1 {
+ execsql {PRAGMA integrity_check}
+} ok
+do_test misc3-3.2 {
+ execsql {
+ CREATE TABLE t2(a INT UNIQUE);
+ PRAGMA integrity_check;
+ }
+} ok
+do_test misc3-3.3 {
+ execsql {
+ INSERT INTO t2 VALUES(2147483648);
+ PRAGMA integrity_check;
+ }
+} ok
+do_test misc3-3.4 {
+ execsql {
+ INSERT INTO t2 VALUES(-2147483649);
+ PRAGMA integrity_check;
+ }
+} ok
+do_test misc3-3.5 {
+ execsql {
+ INSERT INTO t2 VALUES(+2147483649);
+ PRAGMA integrity_check;
+ }
+} ok
+do_test misc3-3.6 {
+ execsql {
+ INSERT INTO t2 VALUES(+2147483647);
+ INSERT INTO t2 VALUES(-2147483648);
+ INSERT INTO t2 VALUES(-2147483647);
+ INSERT INTO t2 VALUES(2147483646);
+ SELECT * FROM t2 ORDER BY a;
+ }
+} {-2147483649 -2147483648 -2147483647 2147483646 2147483647 2147483648 2147483649}
+do_test misc3-3.7 {
+ execsql {
+ SELECT * FROM t2 WHERE a>=-2147483648 ORDER BY a;
+ }
+} {-2147483648 -2147483647 2147483646 2147483647 2147483648 2147483649}
+do_test misc3-3.8 {
+ execsql {
+ SELECT * FROM t2 WHERE a>-2147483648 ORDER BY a;
+ }
+} {-2147483647 2147483646 2147483647 2147483648 2147483649}
+do_test misc3-3.9 {
+ execsql {
+ SELECT * FROM t2 WHERE a>-2147483649 ORDER BY a;
+ }
+} {-2147483648 -2147483647 2147483646 2147483647 2147483648 2147483649}
+do_test misc3-3.10 {
+ execsql {
+ SELECT * FROM t2 WHERE a>=0 AND a<2147483649 ORDER BY a DESC;
+ }
+} {2147483648 2147483647 2147483646}
+do_test misc3-3.11 {
+ execsql {
+ SELECT * FROM t2 WHERE a>=0 AND a<=2147483648 ORDER BY a DESC;
+ }
+} {2147483648 2147483647 2147483646}
+do_test misc3-3.12 {
+ execsql {
+ SELECT * FROM t2 WHERE a>=0 AND a<2147483648 ORDER BY a DESC;
+ }
+} {2147483647 2147483646}
+do_test misc3-3.13 {
+ execsql {
+ SELECT * FROM t2 WHERE a>=0 AND a<=2147483647 ORDER BY a DESC;
+ }
+} {2147483647 2147483646}
+do_test misc3-3.14 {
+ execsql {
+ SELECT * FROM t2 WHERE a>=0 AND a<2147483647 ORDER BY a DESC;
+ }
+} {2147483646}
+
+# Ticket #565. A stack overflow is occurring when the subquery to the
+# right of an IN operator contains many NULLs
+#
+do_test misc3-4.1 {
+ execsql {
+ CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
+ INSERT INTO t3(b) VALUES('abc');
+ INSERT INTO t3(b) VALUES('xyz');
+ INSERT INTO t3(b) VALUES(NULL);
+ INSERT INTO t3(b) VALUES(NULL);
+ INSERT INTO t3(b) SELECT b||'d' FROM t3;
+ INSERT INTO t3(b) SELECT b||'e' FROM t3;
+ INSERT INTO t3(b) SELECT b||'f' FROM t3;
+ INSERT INTO t3(b) SELECT b||'g' FROM t3;
+ INSERT INTO t3(b) SELECT b||'h' FROM t3;
+ SELECT count(a), count(b) FROM t3;
+ }
+} {128 64}
+do_test misc3-4.2 {
+ execsql {
+ SELECT count(a) FROM t3 WHERE b IN (SELECT b FROM t3);
+ }
+} {64}
+do_test misc3-4.3 {
+ execsql {
+ SELECT count(a) FROM t3 WHERE b IN (SELECT b FROM t3 ORDER BY a+1);
+ }
+} {64}
+
+# Ticket #601: Putting a left join inside "SELECT * FROM (<join-here>)"
+# gives different results that if the outer "SELECT * FROM ..." is omitted.
+#
+do_test misc3-5.1 {
+ execsql {
+ CREATE TABLE x1 (b, c);
+ INSERT INTO x1 VALUES('dog',3);
+ INSERT INTO x1 VALUES('cat',1);
+ INSERT INTO x1 VALUES('dog',4);
+ CREATE TABLE x2 (c, e);
+ INSERT INTO x2 VALUES(1,'one');
+ INSERT INTO x2 VALUES(2,'two');
+ INSERT INTO x2 VALUES(3,'three');
+ INSERT INTO x2 VALUES(4,'four');
+ SELECT x2.c AS c, e, b FROM x2 LEFT JOIN
+ (SELECT b, max(c) AS c FROM x1 GROUP BY b)
+ USING(c);
+ }
+} {1 one cat 2 two {} 3 three {} 4 four dog}
+do_test misc4-5.2 {
+ execsql {
+ SELECT * FROM (
+ SELECT x2.c AS c, e, b FROM x2 LEFT JOIN
+ (SELECT b, max(c) AS c FROM x1 GROUP BY b)
+ USING(c)
+ );
+ }
+} {1 one cat 2 two {} 3 three {} 4 four dog}
+
+# Ticket #626: make sure EXPLAIN prevents BEGIN and COMMIT from working.
+#
+do_test misc3-6.1 {
+ execsql {EXPLAIN BEGIN}
+ catchsql {BEGIN}
+} {0 {}}
+do_test misc3-6.2 {
+ execsql {EXPLAIN COMMIT}
+ catchsql {COMMIT}
+} {0 {}}
+do_test misc3-6.3 {
+ execsql {BEGIN; EXPLAIN ROLLBACK}
+ catchsql {ROLLBACK}
+} {0 {}}
+
+# Ticket #640: vdbe stack overflow with a LIMIT clause on a SELECT inside
+# of a trigger.
+#
+do_test misc3-7.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE y1(a);
+ CREATE TABLE y2(b);
+ CREATE TABLE y3(c);
+ CREATE TRIGGER r1 AFTER DELETE ON y1 FOR EACH ROW BEGIN
+ INSERT INTO y3(c) SELECT b FROM y2 ORDER BY b LIMIT 1;
+ END;
+ INSERT INTO y1 VALUES(1);
+ INSERT INTO y1 VALUES(2);
+ INSERT INTO y1 SELECT a+2 FROM y1;
+ INSERT INTO y1 SELECT a+4 FROM y1;
+ INSERT INTO y1 SELECT a+8 FROM y1;
+ INSERT INTO y1 SELECT a+16 FROM y1;
+ INSERT INTO y2 SELECT a FROM y1;
+ COMMIT;
+ SELECT count(*) FROM y1;
+ }
+} 32
+do_test misc3-7.2 {
+ execsql {
+ DELETE FROM y1;
+ SELECT count(*) FROM y1;
+ }
+} 0
+do_test misc3-7.3 {
+ execsql {
+ SELECT count(*) FROM y3;
+ }
+} 32
+
+# Ticket #668: VDBE stack overflow occurs when the left-hand side
+# of an IN expression is NULL and the result is used as an integer, not
+# as a jump.
+#
+do_test misc-8.1 {
+ execsql {
+ SELECT count(CASE WHEN b IN ('abc','xyz') THEN 'x' END) FROM t3
+ }
+} {2}
+do_test misc-8.2 {
+ execsql {
+ SELECT count(*) FROM t3 WHERE 1+(b IN ('abc','xyz'))==2
+ }
+} {2}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/misuse.test b/usr/src/lib/libsqlite/test/misuse.test
new file mode 100644
index 0000000000..f4d15be304
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/misuse.test
@@ -0,0 +1,169 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 May 10
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+# This file implements tests for the SQLITE_MISUSE detection logic.
+# This test file leaks memory and file descriptors.
+#
+# $Id: misuse.test,v 1.4 2004/01/07 19:24:48 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Make sure the test logic works
+#
+do_test misuse-1.1 {
+ db close
+ catch {file delete -force test2.db}
+ set ::DB [sqlite db test2.db]
+ execsql {
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1 VALUES(1,2);
+ }
+ sqlite_exec_printf $::DB {SELECT * FROM t1} {}
+} {0 {a b 1 2}}
+do_test misuse-1.2 {
+ sqlite_exec_printf $::DB {SELECT x_coalesce(NULL,a) AS 'xyz' FROM t1} {}
+} {1 {no such function: x_coalesce}}
+do_test misuse-1.3 {
+ sqlite_create_function $::DB
+ sqlite_exec_printf $::DB {SELECT x_coalesce(NULL,a) AS 'xyz' FROM t1} {}
+} {0 {xyz 1}}
+
+# Use the x_sqlite_exec() SQL function to simulate the effect of two
+# threads trying to use the same database at the same time.
+#
+# It used to be prohibited to invoke sqlite_exec() from within a function,
+# but that has changed. The following tests used to cause errors but now
+# they do not.
+#
+do_test misuse-1.4 {
+ sqlite_exec_printf $::DB {
+ SELECT x_sqlite_exec('SELECT * FROM t1') AS xyz;
+ } {}
+} {0 {xyz {1 2}}}
+do_test misuse-1.5 {
+ sqlite_exec_printf $::DB {SELECT * FROM t1} {}
+} {0 {a b 1 2}}
+do_test misuse-1.6 {
+ catchsql {
+ SELECT * FROM t1
+ }
+} {0 {1 2}}
+
+# Attempt to register a new SQL function while an sqlite_exec() is active.
+#
+do_test misuse-2.1 {
+ db close
+ set ::DB [sqlite db test2.db]
+ execsql {
+ SELECT * FROM t1
+ }
+} {1 2}
+do_test misuse-2.2 {
+ sqlite_exec_printf $::DB {SELECT * FROM t1} {}
+} {0 {a b 1 2}}
+do_test misuse-2.3 {
+ set v [catch {
+ db eval {SELECT * FROM t1} {} {
+ sqlite_create_function $::DB
+ }
+ } msg]
+ lappend v $msg
+} {1 {library routine called out of sequence}}
+do_test misuse-2.4 {
+ sqlite_exec_printf $::DB {SELECT * FROM t1} {}
+} {21 {library routine called out of sequence}}
+do_test misuse-2.5 {
+ catchsql {
+ SELECT * FROM t1
+ }
+} {1 {library routine called out of sequence}}
+
+# Attempt to register a new SQL aggregate while an sqlite_exec() is active.
+#
+do_test misuse-3.1 {
+ db close
+ set ::DB [sqlite db test2.db]
+ execsql {
+ SELECT * FROM t1
+ }
+} {1 2}
+do_test misuse-3.2 {
+ sqlite_exec_printf $::DB {SELECT * FROM t1} {}
+} {0 {a b 1 2}}
+do_test misuse-3.3 {
+ set v [catch {
+ db eval {SELECT * FROM t1} {} {
+ sqlite_create_aggregate $::DB
+ }
+ } msg]
+ lappend v $msg
+} {1 {library routine called out of sequence}}
+do_test misuse-3.4 {
+ sqlite_exec_printf $::DB {SELECT * FROM t1} {}
+} {21 {library routine called out of sequence}}
+do_test misuse-3.5 {
+ catchsql {
+ SELECT * FROM t1
+ }
+} {1 {library routine called out of sequence}}
+
+# Attempt to close the database from an sqlite_exec callback.
+#
+do_test misuse-4.1 {
+ db close
+ set ::DB [sqlite db test2.db]
+ execsql {
+ SELECT * FROM t1
+ }
+} {1 2}
+do_test misuse-4.2 {
+ sqlite_exec_printf $::DB {SELECT * FROM t1} {}
+} {0 {a b 1 2}}
+do_test misuse-4.3 {
+ set v [catch {
+ db eval {SELECT * FROM t1} {} {
+ sqlite_close $::DB
+ }
+ } msg]
+ lappend v $msg
+} {1 {library routine called out of sequence}}
+do_test misuse-4.4 {
+ sqlite_exec_printf $::DB {SELECT * FROM t1} {}
+} {21 {library routine called out of sequence}}
+do_test misuse-4.5 {
+ catchsql {
+ SELECT * FROM t1
+ }
+} {1 {library routine called out of sequence}}
+
+# Attempt to use a database after it has been closed.
+#
+do_test misuse-5.1 {
+ db close
+ set ::DB [sqlite db test2.db]
+ execsql {
+ SELECT * FROM t1
+ }
+} {1 2}
+do_test misuse-5.2 {
+ sqlite_exec_printf $::DB {SELECT * FROM t1} {}
+} {0 {a b 1 2}}
+do_test misuse-5.3 {
+ db close
+ sqlite_exec_printf $::DB {SELECT * FROM t1} {}
+} {21 {library routine called out of sequence}}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/notnull.test b/usr/src/lib/libsqlite/test/notnull.test
new file mode 100644
index 0000000000..cd2691a084
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/notnull.test
@@ -0,0 +1,503 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 January 29
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+# This file implements tests for the NOT NULL constraint.
+#
+# $Id: notnull.test,v 1.3 2003/01/29 18:46:54 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test notnull-1.0 {
+ execsql {
+ CREATE TABLE t1 (
+ a NOT NULL,
+ b NOT NULL DEFAULT 5,
+ c NOT NULL ON CONFLICT REPLACE DEFAULT 6,
+ d NOT NULL ON CONFLICT IGNORE DEFAULT 7,
+ e NOT NULL ON CONFLICT ABORT DEFAULT 8
+ );
+ SELECT * FROM t1;
+ }
+} {}
+do_test notnull-1.1 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 2 3 4 5}}
+do_test notnull-1.2 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(b,c,d,e) VALUES(2,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-1.3 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {}}
+do_test notnull-1.4 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-1.5 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-1.6 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,c,d,e) VALUES(1,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 5 3 4 5}}
+do_test notnull-1.7 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 5 3 4 5}}
+do_test notnull-1.8 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 5 3 4 5}}
+do_test notnull-1.9 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 5 3 4 5}}
+do_test notnull-1.10 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.b may not be NULL}}
+do_test notnull-1.11 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {}}
+do_test notnull-1.12 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 5 3 4 5}}
+do_test notnull-1.13 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 2 6 4 5}}
+do_test notnull-1.14 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {}}
+do_test notnull-1.15 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 2 6 4 5}}
+do_test notnull-1.16 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.c may not be NULL}}
+do_test notnull-1.17 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.d may not be NULL}}
+do_test notnull-1.18 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 2 3 7 5}}
+do_test notnull-1.19 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c,d) VALUES(1,2,3,4);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 2 3 4 8}}
+do_test notnull-1.20 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,null);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.e may not be NULL}}
+do_test notnull-1.21 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {5 5 3 2 1}}
+
+do_test notnull-2.1 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE t1 SET a=null;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-2.2 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE OR REPLACE t1 SET a=null;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-2.3 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE OR IGNORE t1 SET a=null;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {0 {1 2 3 4 5}}
+do_test notnull-2.4 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE OR ABORT t1 SET a=null;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-2.5 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE t1 SET b=null;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {t1.b may not be NULL}}
+do_test notnull-2.6 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE OR REPLACE t1 SET b=null, d=e, e=d;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {0 {1 5 3 5 4}}
+do_test notnull-2.7 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE OR IGNORE t1 SET b=null, d=e, e=d;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {0 {1 2 3 4 5}}
+do_test notnull-2.8 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE t1 SET c=null, d=e, e=d;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {0 {1 2 6 5 4}}
+do_test notnull-2.9 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE t1 SET d=null, a=b, b=a;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {0 {1 2 3 4 5}}
+do_test notnull-2.10 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE t1 SET e=null, a=b, b=a;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {t1.e may not be NULL}}
+
+do_test notnull-3.0 {
+ execsql {
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1b ON t1(b);
+ CREATE INDEX t1c ON t1(c);
+ CREATE INDEX t1d ON t1(d);
+ CREATE INDEX t1e ON t1(e);
+ CREATE INDEX t1abc ON t1(a,b,c);
+ }
+} {}
+do_test notnull-3.1 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 2 3 4 5}}
+do_test notnull-3.2 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(b,c,d,e) VALUES(2,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-3.3 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {}}
+do_test notnull-3.4 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-3.5 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-3.6 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,c,d,e) VALUES(1,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 5 3 4 5}}
+do_test notnull-3.7 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 5 3 4 5}}
+do_test notnull-3.8 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 5 3 4 5}}
+do_test notnull-3.9 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 5 3 4 5}}
+do_test notnull-3.10 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.b may not be NULL}}
+do_test notnull-3.11 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {}}
+do_test notnull-3.12 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 5 3 4 5}}
+do_test notnull-3.13 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 2 6 4 5}}
+do_test notnull-3.14 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {}}
+do_test notnull-3.15 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 2 6 4 5}}
+do_test notnull-3.16 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.c may not be NULL}}
+do_test notnull-3.17 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.d may not be NULL}}
+do_test notnull-3.18 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 2 3 7 5}}
+do_test notnull-3.19 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c,d) VALUES(1,2,3,4);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {1 2 3 4 8}}
+do_test notnull-3.20 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,null);
+ SELECT * FROM t1 order by a;
+ }
+} {1 {t1.e may not be NULL}}
+do_test notnull-3.21 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT OR REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
+ SELECT * FROM t1 order by a;
+ }
+} {0 {5 5 3 2 1}}
+
+do_test notnull-4.1 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE t1 SET a=null;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-4.2 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE OR REPLACE t1 SET a=null;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-4.3 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE OR IGNORE t1 SET a=null;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {0 {1 2 3 4 5}}
+do_test notnull-4.4 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE OR ABORT t1 SET a=null;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {t1.a may not be NULL}}
+do_test notnull-4.5 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE t1 SET b=null;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {t1.b may not be NULL}}
+do_test notnull-4.6 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE OR REPLACE t1 SET b=null, d=e, e=d;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {0 {1 5 3 5 4}}
+do_test notnull-4.7 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE OR IGNORE t1 SET b=null, d=e, e=d;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {0 {1 2 3 4 5}}
+do_test notnull-4.8 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE t1 SET c=null, d=e, e=d;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {0 {1 2 6 5 4}}
+do_test notnull-4.9 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE t1 SET d=null, a=b, b=a;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {0 {1 2 3 4 5}}
+do_test notnull-4.10 {
+ catchsql {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,3,4,5);
+ UPDATE t1 SET e=null, a=b, b=a;
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 {t1.e may not be NULL}}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/null.test b/usr/src/lib/libsqlite/test/null.test
new file mode 100644
index 0000000000..6c816d8584
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/null.test
@@ -0,0 +1,240 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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.
+#
+# This file implements tests for proper treatment of the special
+# value NULL.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a table and some data to work with.
+#
+do_test null-1.0 {
+ execsql {
+ begin;
+ create table t1(a,b,c);
+ insert into t1 values(1,0,0);
+ insert into t1 values(2,0,1);
+ insert into t1 values(3,1,0);
+ insert into t1 values(4,1,1);
+ insert into t1 values(5,null,0);
+ insert into t1 values(6,null,1);
+ insert into t1 values(7,null,null);
+ commit;
+ select * from t1;
+ }
+} {1 0 0 2 0 1 3 1 0 4 1 1 5 {} 0 6 {} 1 7 {} {}}
+
+# Check for how arithmetic expressions handle NULL
+#
+do_test null-1.1 {
+ execsql {
+ select ifnull(a+b,99) from t1;
+ }
+} {1 2 4 5 99 99 99}
+do_test null-1.2 {
+ execsql {
+ select ifnull(b*c,99) from t1;
+ }
+} {0 0 0 1 99 99 99}
+
+# Check to see how the CASE expression handles NULL values. The
+# first WHEN for which the test expression is TRUE is selected.
+# FALSE and UNKNOWN test expressions are skipped.
+#
+do_test null-2.1 {
+ execsql {
+ select ifnull(case when b<>0 then 1 else 0 end, 99) from t1;
+ }
+} {0 0 1 1 0 0 0}
+do_test null-2.2 {
+ execsql {
+ select ifnull(case when not b<>0 then 1 else 0 end, 99) from t1;
+ }
+} {1 1 0 0 0 0 0}
+do_test null-2.3 {
+ execsql {
+ select ifnull(case when b<>0 and c<>0 then 1 else 0 end, 99) from t1;
+ }
+} {0 0 0 1 0 0 0}
+do_test null-2.4 {
+ execsql {
+ select ifnull(case when not (b<>0 and c<>0) then 1 else 0 end, 99) from t1;
+ }
+} {1 1 1 0 1 0 0}
+do_test null-2.5 {
+ execsql {
+ select ifnull(case when b<>0 or c<>0 then 1 else 0 end, 99) from t1;
+ }
+} {0 1 1 1 0 1 0}
+do_test null-2.6 {
+ execsql {
+ select ifnull(case when not (b<>0 or c<>0) then 1 else 0 end, 99) from t1;
+ }
+} {1 0 0 0 0 0 0}
+do_test null-2.7 {
+ execsql {
+ select ifnull(case b when c then 1 else 0 end, 99) from t1;
+ }
+} {1 0 0 1 0 0 0}
+do_test null-2.8 {
+ execsql {
+ select ifnull(case c when b then 1 else 0 end, 99) from t1;
+ }
+} {1 0 0 1 0 0 0}
+
+# Check to see that NULL values are ignored in aggregate functions.
+# (except for min().)
+#
+do_test null-3.1 {
+ execsql {
+ select count(*), count(b), count(c), sum(b), sum(c),
+ avg(b), avg(c), min(b), max(b) from t1;
+ }
+} {7 4 6 2 3 0.5 0.5 0 1}
+
+# Check to see how WHERE clauses handle NULL values. A NULL value
+# is the same as UNKNOWN. The WHERE clause should only select those
+# rows that are TRUE. FALSE and UNKNOWN rows are rejected.
+#
+do_test null-4.1 {
+ execsql {
+ select a from t1 where b<10
+ }
+} {1 2 3 4}
+do_test null-4.2 {
+ execsql {
+ select a from t1 where not b>10
+ }
+} {1 2 3 4}
+do_test null-4.3 {
+ execsql {
+ select a from t1 where b<10 or c=1;
+ }
+} {1 2 3 4 6}
+do_test null-4.4 {
+ execsql {
+ select a from t1 where b<10 and c=1;
+ }
+} {2 4}
+do_test null-4.5 {
+ execsql {
+ select a from t1 where not (b<10 and c=1);
+ }
+} {1 3 5}
+
+# The DISTINCT keyword on a SELECT statement should treat NULL values
+# as distinct
+#
+do_test null-5.1 {
+ execsql {
+ select distinct b from t1 order by b;
+ }
+} {{} 0 1}
+
+# A UNION to two queries should treat NULL values
+# as distinct
+#
+do_test null-6.1 {
+ execsql {
+ select b from t1 union select c from t1 order by c;
+ }
+} {{} 0 1}
+
+# The UNIQUE constraint only applies to non-null values
+#
+do_test null-7.1 {
+ execsql {
+ create table t2(a, b unique on conflict ignore);
+ insert into t2 values(1,1);
+ insert into t2 values(2,null);
+ insert into t2 values(3,null);
+ insert into t2 values(4,1);
+ select a from t2;
+ }
+} {1 2 3}
+do_test null-7.2 {
+ execsql {
+ create table t3(a, b, c, unique(b,c) on conflict ignore);
+ insert into t3 values(1,1,1);
+ insert into t3 values(2,null,1);
+ insert into t3 values(3,null,1);
+ insert into t3 values(4,1,1);
+ select a from t3;
+ }
+} {1 2 3}
+
+# Ticket #461 - Make sure nulls are handled correctly when doing a
+# lookup using an index.
+#
+do_test null-8.1 {
+ execsql {
+ CREATE TABLE t4(x,y);
+ INSERT INTO t4 VALUES(1,11);
+ INSERT INTO t4 VALUES(2,NULL);
+ SELECT x FROM t4 WHERE y=NULL;
+ }
+} {}
+do_test null-8.2 {
+ execsql {
+ SELECT x FROM t4 WHERE y IN (33,NULL);
+ }
+} {}
+do_test null-8.3 {
+ execsql {
+ SELECT x FROM t4 WHERE y<33 ORDER BY x;
+ }
+} {1}
+do_test null-8.4 {
+ execsql {
+ SELECT x FROM t4 WHERE y>6 ORDER BY x;
+ }
+} {1}
+do_test null-8.5 {
+ execsql {
+ SELECT x FROM t4 WHERE y!=33 ORDER BY x;
+ }
+} {1}
+do_test null-8.11 {
+ execsql {
+ CREATE INDEX t4i1 ON t4(y);
+ SELECT x FROM t4 WHERE y=NULL;
+ }
+} {}
+do_test null-8.12 {
+ execsql {
+ SELECT x FROM t4 WHERE y IN (33,NULL);
+ }
+} {}
+do_test null-8.13 {
+ execsql {
+ SELECT x FROM t4 WHERE y<33 ORDER BY x;
+ }
+} {1}
+do_test null-8.14 {
+ execsql {
+ SELECT x FROM t4 WHERE y>6 ORDER BY x;
+ }
+} {1}
+do_test null-8.15 {
+ execsql {
+ SELECT x FROM t4 WHERE y!=33 ORDER BY x;
+ }
+} {1}
+
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/pager.test b/usr/src/lib/libsqlite/test/pager.test
new file mode 100644
index 0000000000..3f68719e34
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/pager.test
@@ -0,0 +1,426 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 page cache subsystem.
+#
+# $Id: pager.test,v 1.14 2004/02/25 02:20:42 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+if {[info commands pager_open]!=""} {
+db close
+
+# Basic sanity check. Open and close a pager.
+#
+do_test pager-1.0 {
+ catch {file delete -force ptf1.db}
+ catch {file delete -force ptf1.db-journal}
+ set v [catch {
+ set ::p1 [pager_open ptf1.db 10]
+ } msg]
+} {0}
+do_test pager-1.1 {
+ pager_stats $::p1
+} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 0 ovfl 0}
+do_test pager-1.2 {
+ pager_pagecount $::p1
+} {0}
+do_test pager-1.3 {
+ pager_stats $::p1
+} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 0 ovfl 0}
+do_test pager-1.4 {
+ pager_close $::p1
+} {}
+
+# Try to write a few pages.
+#
+do_test pager-2.1 {
+ set v [catch {
+ set ::p1 [pager_open ptf1.db 10]
+ } msg]
+} {0}
+#do_test pager-2.2 {
+# set v [catch {
+# set ::g1 [page_get $::p1 0]
+# } msg]
+# lappend v $msg
+#} {1 SQLITE_ERROR}
+do_test pager-2.3.1 {
+ set ::gx [page_lookup $::p1 1]
+} {}
+do_test pager-2.3.2 {
+ pager_stats $::p1
+} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 0 ovfl 0}
+do_test pager-2.3.3 {
+ set v [catch {
+ set ::g1 [page_get $::p1 1]
+ } msg]
+ if {$v} {lappend v $msg}
+ set v
+} {0}
+do_test pager-2.3.3 {
+ pager_stats $::p1
+} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
+do_test pager-2.3.4 {
+ set ::gx [page_lookup $::p1 1]
+ expr {$::gx!=""}
+} {1}
+do_test pager-2.3.5 {
+ pager_stats $::p1
+} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
+do_test pager-2.3.6 {
+ expr $::g1==$::gx
+} {1}
+do_test pager-2.3.7 {
+ page_unref $::gx
+ pager_stats $::p1
+} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
+do_test pager-2.4 {
+ pager_stats $::p1
+} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
+do_test pager-2.5 {
+ pager_pagecount $::p1
+} {0}
+do_test pager-2.6 {
+ pager_stats $::p1
+} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
+do_test pager-2.7 {
+ page_number $::g1
+} {1}
+do_test pager-2.8 {
+ page_read $::g1
+} {}
+do_test pager-2.9 {
+ page_unref $::g1
+} {}
+do_test pager-2.10 {
+ pager_stats $::p1
+} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 1 ovfl 0}
+do_test pager-2.11 {
+ set ::g1 [page_get $::p1 1]
+ expr {$::g1!=0}
+} {1}
+do_test pager-2.12 {
+ page_number $::g1
+} {1}
+do_test pager-2.13 {
+ pager_stats $::p1
+} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 2 ovfl 0}
+do_test pager-2.14 {
+ set v [catch {
+ page_write $::g1 "Page-One"
+ } msg]
+ lappend v $msg
+} {0 {}}
+do_test pager-2.15 {
+ pager_stats $::p1
+} {ref 1 page 1 max 10 size 1 state 2 err 0 hit 0 miss 2 ovfl 0}
+do_test pager-2.16 {
+ page_read $::g1
+} {Page-One}
+do_test pager-2.17 {
+ set v [catch {
+ pager_commit $::p1
+ } msg]
+ lappend v $msg
+} {0 {}}
+do_test pager-2.20 {
+ pager_stats $::p1
+} {ref 1 page 1 max 10 size -1 state 1 err 0 hit 0 miss 2 ovfl 0}
+do_test pager-2.19 {
+ pager_pagecount $::p1
+} {1}
+do_test pager-2.21 {
+ pager_stats $::p1
+} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 0 miss 2 ovfl 0}
+do_test pager-2.22 {
+ page_unref $::g1
+} {}
+do_test pager-2.23 {
+ pager_stats $::p1
+} {ref 0 page 0 max 10 size -1 state 0 err 0 hit 0 miss 2 ovfl 0}
+do_test pager-2.24 {
+ set v [catch {
+ page_get $::p1 1
+ } ::g1]
+ if {$v} {lappend v $::g1}
+ set v
+} {0}
+do_test pager-2.25 {
+ page_read $::g1
+} {Page-One}
+do_test pager-2.26 {
+ set v [catch {
+ page_write $::g1 {page-one}
+ } msg]
+ lappend v $msg
+} {0 {}}
+do_test pager-2.27 {
+ page_read $::g1
+} {page-one}
+do_test pager-2.28 {
+ set v [catch {
+ pager_rollback $::p1
+ } msg]
+ lappend v $msg
+} {0 {}}
+do_test pager-2.29 {
+ page_unref $::g1
+ set ::g1 [page_get $::p1 1]
+ page_read $::g1
+} {Page-One}
+do_test pager-2.99 {
+ pager_close $::p1
+} {}
+
+do_test pager-3.1 {
+ set v [catch {
+ set ::p1 [pager_open ptf1.db 15]
+ } msg]
+ if {$v} {lappend v $msg}
+ set v
+} {0}
+do_test pager-3.2 {
+ pager_pagecount $::p1
+} {1}
+do_test pager-3.3 {
+ set v [catch {
+ set ::g(1) [page_get $::p1 1]
+ } msg]
+ if {$v} {lappend v $msg}
+ set v
+} {0}
+do_test pager-3.4 {
+ page_read $::g(1)
+} {Page-One}
+do_test pager-3.5 {
+ for {set i 2} {$i<=20} {incr i} {
+ set gx [page_get $::p1 $i]
+ page_write $gx "Page-$i"
+ page_unref $gx
+ }
+ pager_commit $::p1
+} {}
+for {set i 2} {$i<=20} {incr i} {
+ do_test pager-3.6.[expr {$i-1}] [subst {
+ set gx \[page_get $::p1 $i\]
+ set v \[page_read \$gx\]
+ page_unref \$gx
+ set v
+ }] "Page-$i"
+}
+for {set i 1} {$i<=20} {incr i} {
+ regsub -all CNT {
+ set ::g1 [page_get $::p1 CNT]
+ set ::g2 [page_get $::p1 CNT]
+ set ::vx [page_read $::g2]
+ expr {$::g1==$::g2}
+ } $i body;
+ do_test pager-3.7.$i.1 $body {1}
+ regsub -all CNT {
+ page_unref $::g2
+ set vy [page_read $::g1]
+ expr {$vy==$::vx}
+ } $i body;
+ do_test pager-3.7.$i.2 $body {1}
+ regsub -all CNT {
+ page_unref $::g1
+ set gx [page_get $::p1 CNT]
+ set vy [page_read $gx]
+ page_unref $gx
+ expr {$vy==$::vx}
+ } $i body;
+ do_test pager-3.7.$i.3 $body {1}
+}
+do_test pager-3.99 {
+ pager_close $::p1
+} {}
+
+# tests of the checkpoint mechanism and api
+#
+do_test pager-4.0 {
+ set v [catch {
+ file delete -force ptf1.db
+ set ::p1 [pager_open ptf1.db 15]
+ } msg]
+ if {$v} {lappend v $msg}
+ set v
+} {0}
+do_test pager-4.1 {
+ set g1 [page_get $::p1 1]
+ page_write $g1 "Page-1 v0"
+ for {set i 2} {$i<=20} {incr i} {
+ set gx [page_get $::p1 $i]
+ page_write $gx "Page-$i v0"
+ page_unref $gx
+ }
+ pager_commit $::p1
+} {}
+for {set i 1} {$i<=20} {incr i} {
+ do_test pager-4.2.$i {
+ set gx [page_get $p1 $i]
+ set v [page_read $gx]
+ page_unref $gx
+ set v
+ } "Page-$i v0"
+}
+do_test pager-4.3 {
+ lrange [pager_stats $::p1] 0 1
+} {ref 1}
+do_test pager-4.4 {
+ lrange [pager_stats $::p1] 8 9
+} {state 1}
+
+for {set i 1} {$i<20} {incr i} {
+ do_test pager-4.5.$i.0 {
+ set res {}
+ for {set j 2} {$j<=20} {incr j} {
+ set gx [page_get $p1 $j]
+ set value [page_read $gx]
+ page_unref $gx
+ set shouldbe "Page-$j v[expr {$i-1}]"
+ if {$value!=$shouldbe} {
+ lappend res $value $shouldbe
+ }
+ }
+ set res
+ } {}
+ do_test pager-4.5.$i.1 {
+ page_write $g1 "Page-1 v$i"
+ lrange [pager_stats $p1] 8 9
+ } {state 2}
+ do_test pager-4.5.$i.2 {
+ for {set j 2} {$j<=20} {incr j} {
+ set gx [page_get $p1 $j]
+ page_write $gx "Page-$j v$i"
+ page_unref $gx
+ if {$j==$i} {
+ pager_ckpt_begin $p1
+ }
+ }
+ } {}
+ do_test pager-4.5.$i.3 {
+ set res {}
+ for {set j 2} {$j<=20} {incr j} {
+ set gx [page_get $p1 $j]
+ set value [page_read $gx]
+ page_unref $gx
+ set shouldbe "Page-$j v$i"
+ if {$value!=$shouldbe} {
+ lappend res $value $shouldbe
+ }
+ }
+ set res
+ } {}
+ do_test pager-4.5.$i.4 {
+ pager_rollback $p1
+ set res {}
+ for {set j 2} {$j<=20} {incr j} {
+ set gx [page_get $p1 $j]
+ set value [page_read $gx]
+ page_unref $gx
+ set shouldbe "Page-$j v[expr {$i-1}]"
+ if {$value!=$shouldbe} {
+ lappend res $value $shouldbe
+ }
+ }
+ set res
+ } {}
+ do_test pager-4.5.$i.5 {
+ page_write $g1 "Page-1 v$i"
+ lrange [pager_stats $p1] 8 9
+ } {state 2}
+ do_test pager-4.5.$i.6 {
+ for {set j 2} {$j<=20} {incr j} {
+ set gx [page_get $p1 $j]
+ page_write $gx "Page-$j v$i"
+ page_unref $gx
+ if {$j==$i} {
+ pager_ckpt_begin $p1
+ }
+ }
+ } {}
+ do_test pager-4.5.$i.7 {
+ pager_ckpt_rollback $p1
+ for {set j 2} {$j<=20} {incr j} {
+ set gx [page_get $p1 $j]
+ set value [page_read $gx]
+ page_unref $gx
+ if {$j<=$i || $i==1} {
+ set shouldbe "Page-$j v$i"
+ } else {
+ set shouldbe "Page-$j v[expr {$i-1}]"
+ }
+ if {$value!=$shouldbe} {
+ lappend res $value $shouldbe
+ }
+ }
+ set res
+ } {}
+ do_test pager-4.5.$i.8 {
+ for {set j 2} {$j<=20} {incr j} {
+ set gx [page_get $p1 $j]
+ page_write $gx "Page-$j v$i"
+ page_unref $gx
+ if {$j==$i} {
+ pager_ckpt_begin $p1
+ }
+ }
+ } {}
+ do_test pager-4.5.$i.9 {
+ pager_ckpt_commit $p1
+ for {set j 2} {$j<=20} {incr j} {
+ set gx [page_get $p1 $j]
+ set value [page_read $gx]
+ page_unref $gx
+ set shouldbe "Page-$j v$i"
+ if {$value!=$shouldbe} {
+ lappend res $value $shouldbe
+ }
+ }
+ set res
+ } {}
+ do_test pager-4.5.$i.10 {
+ pager_commit $p1
+ lrange [pager_stats $p1] 8 9
+ } {state 1}
+}
+
+do_test pager-4.99 {
+ pager_close $::p1
+} {}
+
+
+
+ file delete -force ptf1.db
+
+} ;# end if( not mem: and has pager_open command );
+
+# Ticket #615: an assertion fault inside the pager. It is a benign
+# fault, but we might as well test for it.
+#
+do_test pager-5.1 {
+ sqlite db test.db
+ execsql {
+ BEGIN;
+ CREATE TABLE t1(x);
+ PRAGMA synchronous=off;
+ COMMIT;
+ }
+} {}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/pragma.test b/usr/src/lib/libsqlite/test/pragma.test
new file mode 100644
index 0000000000..f7cf3fa6a3
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/pragma.test
@@ -0,0 +1,420 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 March 6
+#
+# 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.
+#
+# This file implements tests for the PRAGMA command.
+#
+# $Id: pragma.test,v 1.9 2004/04/23 17:04:45 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Delete the preexisting database to avoid the special setup
+# that the "all.test" script does.
+#
+db close
+file delete test.db
+set DB [sqlite db test.db]
+
+do_test pragma-1.1 {
+ execsql {
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {2000 2000 1 1}
+do_test pragma-1.2 {
+ execsql {
+ PRAGMA cache_size=1234;
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {1234 2000 1 1}
+do_test pragma-1.3 {
+ db close
+ sqlite db test.db
+ execsql {
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {2000 2000 1 1}
+do_test pragma-1.4 {
+ execsql {
+ PRAGMA synchronous=OFF;
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {2000 2000 0 1}
+do_test pragma-1.5 {
+ execsql {
+ PRAGMA cache_size=4321;
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {4321 2000 0 1}
+do_test pragma-1.6 {
+ execsql {
+ PRAGMA synchronous=ON;
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {4321 2000 1 1}
+do_test pragma-1.7 {
+ db close
+ sqlite db test.db
+ execsql {
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {2000 2000 1 1}
+do_test pragma-1.8 {
+ execsql {
+ PRAGMA default_synchronous=OFF;
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {2000 2000 0 0}
+do_test pragma-1.9 {
+ execsql {
+ PRAGMA default_cache_size=123;
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {123 123 0 0}
+do_test pragma-1.10 {
+ db close
+ set ::DB [sqlite db test.db]
+ execsql {
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {123 123 0 0}
+do_test pragma-1.11 {
+ execsql {
+ PRAGMA synchronous=NORMAL;
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {123 123 1 0}
+do_test pragma-1.12 {
+ execsql {
+ PRAGMA synchronous=FULL;
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {123 123 2 0}
+do_test pragma-1.13 {
+ db close
+ set ::DB [sqlite db test.db]
+ execsql {
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {123 123 0 0}
+do_test pragma-1.14 {
+ execsql {
+ PRAGMA default_synchronous=FULL;
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {123 123 2 2}
+do_test pragma-1.15 {
+ db close
+ set ::DB [sqlite db test.db]
+ execsql {
+ PRAGMA cache_size;
+ PRAGMA default_cache_size;
+ PRAGMA synchronous;
+ PRAGMA default_synchronous;
+ }
+} {123 123 2 2}
+
+do_test pragma-2.1 {
+ execsql {
+ PRAGMA show_datatypes=on;
+ PRAGMA empty_result_callbacks=off;
+ }
+ sqlite_datatypes $::DB {SELECT * FROM sqlite_master}
+} {}
+do_test pragma-2.2 {
+ execsql {
+ PRAGMA empty_result_callbacks=on;
+ }
+ sqlite_datatypes $::DB {SELECT * FROM sqlite_master}
+} {text text text integer text}
+
+# Make sure we can read the schema when empty_result_callbacks are
+# turned on. Ticket #406
+do_test pragma-2.2.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE tabx(a,b,c,d);
+ ROLLBACK;
+ SELECT count(*) FROM sqlite_master;
+ }
+} {0}
+
+do_test pragma-2.3 {
+ execsql {
+ CREATE TABLE t1(
+ a INTEGER,
+ b TEXT,
+ c WHATEVER,
+ d CLOB,
+ e BLOB,
+ f VARCHAR(123),
+ g nVaRcHaR(432)
+ );
+ }
+ sqlite_datatypes $::DB {SELECT * FROM t1}
+} {INTEGER TEXT WHATEVER CLOB BLOB VARCHAR(123) nVaRcHaR(432)}
+do_test pragma-2.4 {
+ sqlite_datatypes $::DB {
+ SELECT 1, 'hello', NULL
+ }
+} {NUMERIC TEXT TEXT}
+do_test pragma-2.5 {
+ sqlite_datatypes $::DB {
+ SELECT 1+2 AS X, 'hello' || 5 AS Y, NULL AS Z
+ }
+} {NUMERIC TEXT TEXT}
+do_test pragma-2.6 {
+ execsql {
+ CREATE VIEW v1 AS SELECT a+b, b||c, * FROM t1;
+ }
+ sqlite_datatypes $::DB {SELECT * FROM v1}
+} {NUMERIC TEXT INTEGER TEXT WHATEVER CLOB BLOB VARCHAR(123) nVaRcHaR(432)}
+do_test pragma-2.7 {
+ sqlite_datatypes $::DB {
+ SELECT d,e FROM t1 UNION SELECT a,c FROM t1
+ }
+} {INTEGER WHATEVER}
+do_test pragma-2.8 {
+ sqlite_datatypes $::DB {
+ SELECT d,e FROM t1 EXCEPT SELECT c,e FROM t1
+ }
+} {WHATEVER BLOB}
+do_test pragma-2.9 {
+ sqlite_datatypes $::DB {
+ SELECT d,e FROM t1 INTERSECT SELECT c,e FROM t1
+ }
+} {WHATEVER BLOB}
+do_test pragma-2.10 {
+ sqlite_datatypes $::DB {
+ SELECT d,e FROM t1 INTERSECT SELECT c,e FROM v1
+ }
+} {WHATEVER BLOB}
+
+# Construct a corrupted index and make sure the integrity_check
+# pragma finds it.
+#
+if {![sqlite -has-codec]} {
+do_test pragma-3.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t2(a,b,c);
+ CREATE INDEX i2 ON t2(a);
+ INSERT INTO t2 VALUES(11,2,3);
+ INSERT INTO t2 VALUES(22,3,4);
+ COMMIT;
+ SELECT rowid, * from t2;
+ }
+} {1 11 2 3 2 22 3 4}
+do_test pragma-3.2 {
+ set rootpage [execsql {SELECT rootpage FROM sqlite_master WHERE name='i2'}]
+ set db [btree_open test.db]
+ btree_begin_transaction $db
+ set c [btree_cursor $db $rootpage 1]
+ btree_first $c
+ btree_delete $c
+ btree_commit $db
+ btree_close $db
+ execsql {PRAGMA integrity_check}
+} {{rowid 1 missing from index i2} {wrong # of entries in index i2}}
+}; # endif has-codec
+
+# Test the temp_store and default_temp_store pragmas
+#
+do_test pragma-4.2 {
+ execsql {
+ PRAGMA temp_store='default';
+ PRAGMA temp_store;
+ }
+} {0}
+do_test pragma-4.3 {
+ execsql {
+ PRAGMA temp_store='file';
+ PRAGMA temp_store;
+ }
+} {1}
+do_test pragma-4.4 {
+ execsql {
+ PRAGMA temp_store='memory';
+ PRAGMA temp_store;
+ }
+} {2}
+do_test pragma-4.5 {
+ execsql {
+ PRAGMA default_temp_store='default';
+ PRAGMA default_temp_store;
+ }
+} {0}
+do_test pragma-4.6 {
+ execsql {
+ PRAGMA temp_store;
+ }
+} {2}
+do_test pragma-4.7 {
+ db close
+ sqlite db test.db
+ execsql {
+ PRAGMA temp_store;
+ }
+} {0}
+do_test pragma-4.8 {
+ execsql {
+ PRAGMA default_temp_store;
+ }
+} {0}
+do_test pragma-4.9 {
+ execsql {
+ PRAGMA default_temp_store='file';
+ PRAGMA default_temp_store;
+ }
+} {1}
+do_test pragma-4.10 {
+ execsql {
+ PRAGMA temp_store;
+ }
+} {0}
+do_test pragma-4.11 {
+ db close
+ sqlite db test.db
+ execsql {
+ PRAGMA temp_store;
+ }
+} {1}
+do_test pragma-4.12 {
+ execsql {
+ PRAGMA default_temp_store;
+ }
+} {1}
+do_test pragma-4.13 {
+ execsql {
+ PRAGMA default_temp_store='memory';
+ PRAGMA default_temp_store;
+ }
+} {2}
+do_test pragma-4.14 {
+ execsql {
+ PRAGMA temp_store;
+ }
+} {1}
+do_test pragma-4.15 {
+ db close
+ sqlite db test.db
+ execsql {
+ PRAGMA temp_store;
+ }
+} {2}
+do_test pragma-4.16 {
+ execsql {
+ PRAGMA default_temp_store;
+ }
+} {2}
+do_test pragma-4.17 {
+ execsql {
+ PRAGMA temp_store='file';
+ PRAGMA temp_store
+ }
+} {1}
+do_test pragma-4.18 {
+ execsql {
+ PRAGMA default_temp_store
+ }
+} {2}
+do_test pragma-4.19 {
+ db close
+ sqlite db test.db
+ execsql {
+ PRAGMA temp_store
+ }
+} {2}
+
+# Changing the TEMP_STORE deletes any existing temporary tables
+#
+do_test pragma-4.20 {
+ execsql {SELECT name FROM sqlite_temp_master}
+} {}
+do_test pragma-4.21 {
+ execsql {
+ CREATE TEMP TABLE test1(a,b,c);
+ SELECT name FROM sqlite_temp_master;
+ }
+} {test1}
+do_test pragma-4.22 {
+ execsql {
+ PRAGMA temp_store='file';
+ SELECT name FROM sqlite_temp_master;
+ }
+} {}
+do_test pragma-4.23 {
+ execsql {
+ CREATE TEMP TABLE test1(a,b,c);
+ SELECT name FROM sqlite_temp_master;
+ }
+} {test1}
+do_test pragma-4.24 {
+ execsql {
+ PRAGMA temp_store='memory';
+ SELECT name FROM sqlite_temp_master;
+ }
+} {}
+do_test pragma-4.25 {
+ catchsql {
+ BEGIN;
+ PRAGMA temp_store='default';
+ COMMIT;
+ }
+} {1 {temporary storage cannot be changed from within a transaction}}
+catchsql {COMMIT}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/printf.test b/usr/src/lib/libsqlite/test/printf.test
new file mode 100644
index 0000000000..a0adc72435
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/printf.test
@@ -0,0 +1,129 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 sqlite_*_printf() interface.
+#
+# $Id: printf.test,v 1.8 2004/02/21 19:41:05 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+set n 1
+foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} {
+ do_test printf-1.$n.1 [subst {
+ sqlite_mprintf_int {Three integers: %d %x %o} $v $v $v
+ }] [format {Three integers: %d %x %o} $v $v $v]
+ do_test printf-1.$n.2 [subst {
+ sqlite_mprintf_int {Three integers: (%6d) (%6x) (%6o)} $v $v $v
+ }] [format {Three integers: (%6d) (%6x) (%6o)} $v $v $v]
+ do_test printf-1.$n.3 [subst {
+ sqlite_mprintf_int {Three integers: (%-6d) (%-6x) (%-6o)} $v $v $v
+ }] [format {Three integers: (%-6d) (%-6x) (%-6o)} $v $v $v]
+ do_test printf-1.$n.4 [subst {
+ sqlite_mprintf_int {Three integers: (%+6d) (%+6x) (%+6o)} $v $v $v
+ }] [format {Three integers: (%+6d) (%+6x) (%+6o)} $v $v $v]
+ do_test printf-1.$n.5 [subst {
+ sqlite_mprintf_int {Three integers: (%06d) (%06x) (%06o)} $v $v $v
+ }] [format {Three integers: (%06d) (%06x) (%06o)} $v $v $v]
+ do_test printf-1.$n.6 [subst {
+ sqlite_mprintf_int {Three integers: (% 6d) (% 6x) (% 6o)} $v $v $v
+ }] [format {Three integers: (% 6d) (% 6x) (% 6o)} $v $v $v]
+ incr n
+}
+
+
+if {$::tcl_platform(platform)!="windows"} {
+
+set m 1
+foreach {a b} {1 1 5 5 10 10 10 5} {
+ set n 1
+ foreach x {0.001 1.0e-20 1.0 0.0 100.0 9.99999 -0.00543 -1.0 -99.99999} {
+ do_test printf-2.$m.$n.1 [subst {
+ sqlite_mprintf_double {A double: %*.*f} $a $b $x
+ }] [format {A double: %*.*f} $a $b $x]
+ do_test printf-2.$m.$n.2 [subst {
+ sqlite_mprintf_double {A double: %*.*e} $a $b $x
+ }] [format {A double: %*.*e} $a $b $x]
+ do_test printf-2.$m.$n.3 [subst {
+ sqlite_mprintf_double {A double: %*.*g} $a $b $x
+ }] [format {A double: %*.*g} $a $b $x]
+ do_test printf-2.$m.$n.4 [subst {
+ sqlite_mprintf_double {A double: %d %d %g} $a $b $x
+ }] [format {A double: %d %d %g} $a $b $x]
+ do_test printf-2.$m.$n.5 [subst {
+ sqlite_mprintf_double {A double: %d %d %#g} $a $b $x
+ }] [format {A double: %d %d %#g} $a $b $x]
+ incr n
+ }
+ incr m
+}
+
+}
+
+do_test printf-3.1 {
+ sqlite_mprintf_str {A String: (%*.*s)} 10 10 {This is the string}
+} [format {A String: (%*.*s)} 10 10 {This is the string}]
+do_test printf-3.2 {
+ sqlite_mprintf_str {A String: (%*.*s)} 10 5 {This is the string}
+} [format {A String: (%*.*s)} 10 5 {This is the string}]
+do_test printf-3.3 {
+ sqlite_mprintf_str {A String: (%*.*s)} -10 5 {This is the string}
+} [format {A String: (%*.*s)} -10 5 {This is the string}]
+do_test printf-3.4 {
+ sqlite_mprintf_str {%d %d A String: (%s)} 1 2 {This is the string}
+} [format {%d %d A String: (%s)} 1 2 {This is the string}]
+do_test printf-3.5 {
+ sqlite_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.6 {
+ sqlite_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-4.1 {
+ sqlite_mprintf_str {%d %d A quoted string: '%q'} 1 2 {Hi Y'all}
+} {1 2 A quoted string: 'Hi Y''all'}
+do_test printf-4.2 {
+ sqlite_mprintf_str {%d %d A NULL pointer in %%q: '%q'} 1 2
+} {1 2 A NULL pointer in %q: '(NULL)'}
+do_test printf-4.3 {
+ sqlite_mprintf_str {%d %d A quoted string: %Q} 1 2 {Hi Y'all}
+} {1 2 A quoted string: 'Hi Y''all'}
+do_test printf-4.4 {
+ sqlite_mprintf_str {%d %d A NULL pointer in %%Q: %Q} 1 2
+} {1 2 A NULL pointer in %Q: NULL}
+
+do_test printf-5.1 {
+ set x [sqlite_mprintf_str {%d %d %100000s} 0 0 {Hello}]
+ string length $x
+} {994}
+do_test printf-5.2 {
+ sqlite_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello}
+} {-9 -10 (HelloHello) %}
+
+do_test printf-6.1 {
+ sqlite_mprintf_z_test , one two three four five six
+} {,one,two,three,four,five,six}
+
+
+do_test printf-7.1 {
+ sqlite_mprintf_scaled {A double: %g} 1.0e307 1.0
+} {A double: 1e+307}
+do_test printf-7.2 {
+ sqlite_mprintf_scaled {A double: %g} 1.0e307 10.0
+} {A double: 1e+308}
+do_test printf-7.3 {
+ sqlite_mprintf_scaled {A double: %g} 1.0e307 100.0
+} {A double: NaN}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/progress.test b/usr/src/lib/libsqlite/test/progress.test
new file mode 100644
index 0000000000..4d94239a04
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/progress.test
@@ -0,0 +1,121 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 'progress callback'.
+#
+# $Id: progress.test,v 1.1 2003/10/18 09:37:27 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Build some test data
+#
+execsql {
+ BEGIN;
+ CREATE TABLE t1(a);
+ INSERT INTO t1 VALUES(1);
+ INSERT INTO t1 VALUES(2);
+ INSERT INTO t1 VALUES(3);
+ INSERT INTO t1 VALUES(4);
+ INSERT INTO t1 VALUES(5);
+ INSERT INTO t1 VALUES(6);
+ INSERT INTO t1 VALUES(7);
+ INSERT INTO t1 VALUES(8);
+ INSERT INTO t1 VALUES(9);
+ INSERT INTO t1 VALUES(10);
+ COMMIT;
+}
+
+
+# Test that the progress callback is invoked.
+do_test progress-1.0 {
+ set counter 0
+ db progress 1 "[namespace code {incr counter}] ; expr 0"
+ execsql {
+ SELECT * FROM t1
+ }
+ expr $counter > 1
+} 1
+
+# Test that the query is abandoned when the progress callback returns non-zero
+do_test progress1.1 {
+ set counter 0
+ db progress 1 "[namespace code {incr counter}] ; expr 1"
+ execsql {
+ SELECT * FROM t1
+ }
+ set counter
+} 1
+
+# Test that the query is rolled back when the progress callback returns
+# non-zero.
+do_test progress1.2 {
+
+ # This figures out how many opcodes it takes to copy 5 extra rows into t1.
+ db progress 1 "[namespace code {incr five_rows}] ; expr 0"
+ set five_rows 0
+ execsql {
+ INSERT INTO t1 SELECT a+10 FROM t1 WHERE a < 6
+ }
+ db progress 0 ""
+ execsql {
+ DELETE FROM t1 WHERE a > 10
+ }
+
+ # Now set up the progress callback to abandon the query after the number of
+ # opcodes to copy 5 rows. That way, when we try to copy 6 rows, we know
+ # some data will have been inserted into the table by the time the progress
+ # callback abandons the query.
+ db progress $five_rows "expr 1"
+ execsql {
+ INSERT INTO t1 SELECT a+10 FROM t1 WHERE a < 7
+ }
+ execsql {
+ SELECT count(*) FROM t1
+ }
+} 10
+
+# Test that an active transaction remains active and not rolled back after the
+# progress query abandons a query.
+do_test progress1.3 {
+
+ db progress 0 ""
+ execsql BEGIN
+ execsql {
+ INSERT INTO t1 VALUES(11)
+ }
+ db progress 1 "expr 1"
+ execsql {
+ INSERT INTO t1 VALUES(12)
+ }
+ db progress 0 ""
+ execsql COMMIT
+ execsql {
+ SELECT count(*) FROM t1
+ }
+} 11
+
+# Check that a value of 0 for N means no progress callback
+do_test progress1.4 {
+ set counter 0
+ db progress 0 "[namespace code {incr counter}] ; expr 0"
+ execsql {
+ SELECT * FROM t1;
+ }
+ set counter
+} 0
+
+db progress 0 ""
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/quick.test b/usr/src/lib/libsqlite/test/quick.test
new file mode 100644
index 0000000000..5faf95a466
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/quick.test
@@ -0,0 +1,56 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 runs all tests.
+#
+# $Id: quick.test,v 1.6 2004/02/11 02:18:07 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+rename finish_test really_finish_test
+proc finish_test {} {}
+set ISQUICK 1
+
+set EXCLUDE {
+ all.test
+ quick.test
+ btree2.test
+ malloc.test
+ memleak.test
+ misuse.test
+}
+
+if {[sqlite -has-codec]} {
+ lappend EXCLUDE \
+ attach.test \
+ attach2.test \
+ auth.test \
+ format3.test \
+ version.test
+}
+
+foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
+ set tail [file tail $testfile]
+ if {[lsearch -exact $EXCLUDE $tail]>=0} continue
+ source $testfile
+ catch {db close}
+ if {$sqlite_open_file_count>0} {
+ puts "$tail did not close all files: $sqlite_open_file_count"
+ incr nErr
+ lappend ::failList $tail
+ }
+}
+source $testdir/misuse.test
+
+set sqlite_open_file_count 0
+really_finish_test
diff --git a/usr/src/lib/libsqlite/test/quote.test b/usr/src/lib/libsqlite/test/quote.test
new file mode 100644
index 0000000000..5fb9e85736
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/quote.test
@@ -0,0 +1,91 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 the ability to specify table and column names
+# as quoted strings.
+#
+# $Id: quote.test,v 1.3 2002/05/21 13:43:04 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a table with a strange name and with strange column names.
+#
+do_test quote-1.0 {
+ set r [catch {
+ execsql {CREATE TABLE '@abc' ( '#xyz' int, '!pqr' text );}
+ } msg]
+ lappend r $msg
+} {0 {}}
+
+# Insert, update and query the table.
+#
+do_test quote-1.1 {
+ set r [catch {
+ execsql {INSERT INTO '@abc' VALUES(5,'hello')}
+ } msg]
+ lappend r $msg
+} {0 {}}
+do_test quote-1.2 {
+ set r [catch {
+ execsql {SELECT * FROM '@abc'}
+ } msg ]
+ lappend r $msg
+} {0 {5 hello}}
+do_test quote-1.3 {
+ set r [catch {
+ execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
+ } msg ]
+ lappend r $msg
+} {0 {hello 10}}
+do_test quote-1.3.1 {
+ catchsql {
+ SELECT '!pqr', '#xyz'+5 FROM '@abc'
+ }
+} {0 {!pqr 5}}
+do_test quote-1.3.2 {
+ catchsql {
+ SELECT "!pqr", "#xyz"+5 FROM '@abc'
+ }
+} {0 {hello 10}}
+do_test quote-1.3 {
+ set r [catch {
+ execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
+ } msg ]
+ lappend r $msg
+} {0 {hello 10}}
+do_test quote-1.4 {
+ set r [catch {
+ execsql {UPDATE '@abc' SET '#xyz'=11}
+ } msg ]
+ lappend r $msg
+} {0 {}}
+do_test quote-1.5 {
+ set r [catch {
+ execsql {SELECT '@abc'.'!pqr', '@abc'.'#xyz'+5 FROM '@abc'}
+ } msg ]
+ lappend r $msg
+} {0 {hello 16}}
+
+# Drop the table with the strange name.
+#
+do_test quote-1.6 {
+ set r [catch {
+ execsql {DROP TABLE '@abc'}
+ } msg ]
+ lappend r $msg
+} {0 {}}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/rowid.test b/usr/src/lib/libsqlite/test/rowid.test
new file mode 100644
index 0000000000..7cb5dc57c8
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/rowid.test
@@ -0,0 +1,636 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 magic ROWID column that is
+# found on all tables.
+#
+# $Id: rowid.test,v 1.13 2004/01/14 21:59:24 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Basic ROWID functionality tests.
+#
+do_test rowid-1.1 {
+ execsql {
+ CREATE TABLE t1(x int, y int);
+ INSERT INTO t1 VALUES(1,2);
+ INSERT INTO t1 VALUES(3,4);
+ SELECT x FROM t1 ORDER BY y;
+ }
+} {1 3}
+do_test rowid-1.2 {
+ set r [execsql {SELECT rowid FROM t1 ORDER BY x}]
+ global x2rowid rowid2x
+ set x2rowid(1) [lindex $r 0]
+ set x2rowid(3) [lindex $r 1]
+ set rowid2x($x2rowid(1)) 1
+ set rowid2x($x2rowid(3)) 3
+ llength $r
+} {2}
+do_test rowid-1.3 {
+ global x2rowid
+ set sql "SELECT x FROM t1 WHERE rowid==$x2rowid(1)"
+ execsql $sql
+} {1}
+do_test rowid-1.4 {
+ global x2rowid
+ set sql "SELECT x FROM t1 WHERE rowid==$x2rowid(3)"
+ execsql $sql
+} {3}
+do_test rowid-1.5 {
+ global x2rowid
+ set sql "SELECT x FROM t1 WHERE oid==$x2rowid(1)"
+ execsql $sql
+} {1}
+do_test rowid-1.6 {
+ global x2rowid
+ set sql "SELECT x FROM t1 WHERE OID==$x2rowid(3)"
+ execsql $sql
+} {3}
+do_test rowid-1.7 {
+ global x2rowid
+ set sql "SELECT x FROM t1 WHERE _rowid_==$x2rowid(1)"
+ execsql $sql
+} {1}
+do_test rowid-1.7.1 {
+ while 1 {
+ set norow [expr {int(rand()*1000000)}]
+ if {$norow!=$x2rowid(1) && $norow!=$x2rowid(3)} break
+ }
+ execsql "SELECT x FROM t1 WHERE rowid=$norow"
+} {}
+do_test rowid-1.8 {
+ global x2rowid
+ set v [execsql {SELECT x, oid FROM t1 order by x}]
+ set v2 [list 1 $x2rowid(1) 3 $x2rowid(3)]
+ expr {$v==$v2}
+} {1}
+do_test rowid-1.9 {
+ global x2rowid
+ set v [execsql {SELECT x, RowID FROM t1 order by x}]
+ set v2 [list 1 $x2rowid(1) 3 $x2rowid(3)]
+ expr {$v==$v2}
+} {1}
+do_test rowid-1.9 {
+ global x2rowid
+ set v [execsql {SELECT x, _rowid_ FROM t1 order by x}]
+ set v2 [list 1 $x2rowid(1) 3 $x2rowid(3)]
+ expr {$v==$v2}
+} {1}
+
+# We can insert or update the ROWID column.
+#
+do_test rowid-2.1 {
+ catchsql {
+ INSERT INTO t1(rowid,x,y) VALUES(1234,5,6);
+ SELECT rowid, * FROM t1;
+ }
+} {0 {1 1 2 2 3 4 1234 5 6}}
+do_test rowid-2.2 {
+ catchsql {
+ UPDATE t1 SET rowid=12345 WHERE x==1;
+ SELECT rowid, * FROM t1
+ }
+} {0 {2 3 4 1234 5 6 12345 1 2}}
+do_test rowid-2.3 {
+ catchsql {
+ INSERT INTO t1(y,x,oid) VALUES(8,7,1235);
+ SELECT rowid, * FROM t1 WHERE rowid>1000;
+ }
+} {0 {1234 5 6 1235 7 8 12345 1 2}}
+do_test rowid-2.4 {
+ catchsql {
+ UPDATE t1 SET oid=12346 WHERE x==1;
+ SELECT rowid, * FROM t1;
+ }
+} {0 {2 3 4 1234 5 6 1235 7 8 12346 1 2}}
+do_test rowid-2.5 {
+ catchsql {
+ INSERT INTO t1(x,_rowid_,y) VALUES(9,1236,10);
+ SELECT rowid, * FROM t1 WHERE rowid>1000;
+ }
+} {0 {1234 5 6 1235 7 8 1236 9 10 12346 1 2}}
+do_test rowid-2.6 {
+ catchsql {
+ UPDATE t1 SET _rowid_=12347 WHERE x==1;
+ SELECT rowid, * FROM t1 WHERE rowid>1000;
+ }
+} {0 {1234 5 6 1235 7 8 1236 9 10 12347 1 2}}
+
+# But we can use ROWID in the WHERE clause of an UPDATE that does not
+# change the ROWID.
+#
+do_test rowid-2.7 {
+ global x2rowid
+ set sql "UPDATE t1 SET x=2 WHERE OID==$x2rowid(3)"
+ execsql $sql
+ execsql {SELECT x FROM t1 ORDER BY x}
+} {1 2 5 7 9}
+do_test rowid-2.8 {
+ global x2rowid
+ set sql "UPDATE t1 SET x=3 WHERE _rowid_==$x2rowid(3)"
+ execsql $sql
+ execsql {SELECT x FROM t1 ORDER BY x}
+} {1 3 5 7 9}
+
+# We cannot index by ROWID
+#
+do_test rowid-2.9 {
+ set v [catch {execsql {CREATE INDEX idxt1 ON t1(rowid)}} msg]
+ lappend v $msg
+} {1 {table t1 has no column named rowid}}
+do_test rowid-2.10 {
+ set v [catch {execsql {CREATE INDEX idxt1 ON t1(_rowid_)}} msg]
+ lappend v $msg
+} {1 {table t1 has no column named _rowid_}}
+do_test rowid-2.11 {
+ set v [catch {execsql {CREATE INDEX idxt1 ON t1(oid)}} msg]
+ lappend v $msg
+} {1 {table t1 has no column named oid}}
+do_test rowid-2.12 {
+ set v [catch {execsql {CREATE INDEX idxt1 ON t1(x, rowid)}} msg]
+ lappend v $msg
+} {1 {table t1 has no column named rowid}}
+
+# Columns defined in the CREATE statement override the buildin ROWID
+# column names.
+#
+do_test rowid-3.1 {
+ execsql {
+ CREATE TABLE t2(rowid int, x int, y int);
+ INSERT INTO t2 VALUES(0,2,3);
+ INSERT INTO t2 VALUES(4,5,6);
+ INSERT INTO t2 VALUES(7,8,9);
+ SELECT * FROM t2 ORDER BY x;
+ }
+} {0 2 3 4 5 6 7 8 9}
+do_test rowid-3.2 {
+ execsql {SELECT * FROM t2 ORDER BY rowid}
+} {0 2 3 4 5 6 7 8 9}
+do_test rowid-3.3 {
+ execsql {SELECT rowid, x, y FROM t2 ORDER BY rowid}
+} {0 2 3 4 5 6 7 8 9}
+do_test rowid-3.4 {
+ set r1 [execsql {SELECT _rowid_, rowid FROM t2 ORDER BY rowid}]
+ foreach {a b c d e f} $r1 {}
+ set r2 [execsql {SELECT _rowid_, rowid FROM t2 ORDER BY x DESC}]
+ foreach {u v w x y z} $r2 {}
+ expr {$u==$e && $w==$c && $y==$a}
+} {1}
+do_probtest rowid-3.5 {
+ set r1 [execsql {SELECT _rowid_, rowid FROM t2 ORDER BY rowid}]
+ foreach {a b c d e f} $r1 {}
+ expr {$a!=$b && $c!=$d && $e!=$f}
+} {1}
+
+# Let's try some more complex examples, including some joins.
+#
+do_test rowid-4.1 {
+ execsql {
+ DELETE FROM t1;
+ DELETE FROM t2;
+ }
+ for {set i 1} {$i<=50} {incr i} {
+ execsql "INSERT INTO t1(x,y) VALUES($i,[expr {$i*$i}])"
+ }
+ execsql {INSERT INTO t2 SELECT _rowid_, x*y, y*y FROM t1}
+ execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1.rowid==t2.rowid}
+} {256}
+do_test rowid-4.2 {
+ execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1.rowid==t2.rowid}
+} {256}
+do_test rowid-4.2.1 {
+ execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1.oid==t2.rowid}
+} {256}
+do_test rowid-4.2.2 {
+ execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
+} {256}
+do_test rowid-4.2.3 {
+ execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t2.rowid==t1.rowid}
+} {256}
+do_test rowid-4.2.4 {
+ execsql {SELECT t2.y FROM t2, t1 WHERE t2.rowid==t1.oid AND t1.x==4}
+} {256}
+do_test rowid-4.2.5 {
+ execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
+} {256}
+do_test rowid-4.2.6 {
+ execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t2.rowid==t1.rowid}
+} {256}
+do_test rowid-4.2.7 {
+ execsql {SELECT t2.y FROM t1, t2 WHERE t2.rowid==t1.oid AND t1.x==4}
+} {256}
+do_test rowid-4.3 {
+ execsql {CREATE INDEX idxt1 ON t1(x)}
+ execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1.rowid==t2.rowid}
+} {256}
+do_test rowid-4.3.1 {
+ execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
+} {256}
+do_test rowid-4.3.2 {
+ execsql {SELECT t2.y FROM t1, t2 WHERE t2.rowid==t1.oid AND 4==t1.x}
+} {256}
+do_test rowid-4.4 {
+ execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1.rowid==t2.rowid}
+} {256}
+do_test rowid-4.4.1 {
+ execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
+} {256}
+do_test rowid-4.4.2 {
+ execsql {SELECT t2.y FROM t2, t1 WHERE t2.rowid==t1.oid AND 4==t1.x}
+} {256}
+do_test rowid-4.5 {
+ execsql {CREATE INDEX idxt2 ON t2(y)}
+ set sqlite_search_count 0
+ concat [execsql {
+ SELECT t1.x FROM t2, t1
+ WHERE t2.y==256 AND t1.rowid==t2.rowid
+ }] $sqlite_search_count
+} {4 3}
+do_test rowid-4.5.1 {
+ set sqlite_search_count 0
+ concat [execsql {
+ SELECT t1.x FROM t2, t1
+ WHERE t1.OID==t2.rowid AND t2.y==81
+ }] $sqlite_search_count
+} {3 3}
+do_test rowid-4.6 {
+ execsql {
+ SELECT t1.x FROM t1, t2
+ WHERE t2.y==256 AND t1.rowid==t2.rowid
+ }
+} {4}
+
+do_test rowid-5.1 {
+ execsql {DELETE FROM t1 WHERE _rowid_ IN (SELECT oid FROM t1 WHERE x>8)}
+ execsql {SELECT max(x) FROM t1}
+} {8}
+
+# Make sure a "WHERE rowid=X" clause works when there is no ROWID of X.
+#
+do_test rowid-6.1 {
+ execsql {
+ SELECT x FROM t1
+ }
+} {1 2 3 4 5 6 7 8}
+do_test rowid-6.2 {
+ for {set ::norow 1} {1} {incr ::norow} {
+ if {[execsql "SELECT x FROM t1 WHERE rowid=$::norow"]==""} break
+ }
+ execsql [subst {
+ DELETE FROM t1 WHERE rowid=$::norow
+ }]
+} {}
+do_test rowid-6.3 {
+ execsql {
+ SELECT x FROM t1
+ }
+} {1 2 3 4 5 6 7 8}
+
+# Beginning with version 2.3.4, SQLite computes rowids of new rows by
+# finding the maximum current rowid and adding one. It falls back to
+# the old random algorithm if the maximum rowid is the largest integer.
+# The following tests are for this new behavior.
+#
+do_test rowid-7.0 {
+ execsql {
+ DELETE FROM t1;
+ DROP TABLE t2;
+ DROP INDEX idxt1;
+ INSERT INTO t1 VALUES(1,2);
+ SELECT rowid, * FROM t1;
+ }
+} {1 1 2}
+do_test rowid-7.1 {
+ execsql {
+ INSERT INTO t1 VALUES(99,100);
+ SELECT rowid,* FROM t1
+ }
+} {1 1 2 2 99 100}
+do_test rowid-7.2 {
+ execsql {
+ CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
+ INSERT INTO t2(b) VALUES(55);
+ SELECT * FROM t2;
+ }
+} {1 55}
+do_test rowid-7.3 {
+ execsql {
+ INSERT INTO t2(b) VALUES(66);
+ SELECT * FROM t2;
+ }
+} {1 55 2 66}
+do_test rowid-7.4 {
+ execsql {
+ INSERT INTO t2(a,b) VALUES(1000000,77);
+ INSERT INTO t2(b) VALUES(88);
+ SELECT * FROM t2;
+ }
+} {1 55 2 66 1000000 77 1000001 88}
+do_test rowid-7.5 {
+ execsql {
+ INSERT INTO t2(a,b) VALUES(2147483647,99);
+ INSERT INTO t2(b) VALUES(11);
+ SELECT b FROM t2 ORDER BY b;
+ }
+} {11 55 66 77 88 99}
+do_test rowid-7.6 {
+ execsql {
+ SELECT b FROM t2 WHERE a NOT IN(1,2,1000000,1000001,2147483647);
+ }
+} {11}
+do_test rowid-7.7 {
+ execsql {
+ INSERT INTO t2(b) VALUES(22);
+ INSERT INTO t2(b) VALUES(33);
+ INSERT INTO t2(b) VALUES(44);
+ INSERT INTO t2(b) VALUES(55);
+ SELECT b FROM t2 WHERE a NOT IN(1,2,1000000,1000001,2147483647) ORDER BY b;
+ }
+} {11 22 33 44 55}
+do_test rowid-7.8 {
+ execsql {
+ DELETE FROM t2 WHERE a!=2;
+ INSERT INTO t2(b) VALUES(111);
+ SELECT * FROM t2;
+ }
+} {2 66 3 111}
+
+# Make sure AFTER triggers that do INSERTs do not change the last_insert_rowid.
+# Ticket #290
+#
+do_test rowid-8.1 {
+ execsql {
+ CREATE TABLE t3(a integer primary key);
+ CREATE TABLE t4(x);
+ INSERT INTO t4 VALUES(1);
+ CREATE TRIGGER r3 AFTER INSERT on t3 FOR EACH ROW BEGIN
+ INSERT INTO t4 VALUES(NEW.a+10);
+ END;
+ SELECT * FROM t3;
+ }
+} {}
+do_test rowid-8.2 {
+ execsql {
+ SELECT rowid, * FROM t4;
+ }
+} {1 1}
+do_test rowid-8.3 {
+ execsql {
+ INSERT INTO t3 VALUES(123);
+ SELECT last_insert_rowid();
+ }
+} {123}
+do_test rowid-8.4 {
+ execsql {
+ SELECT * FROM t3;
+ }
+} {123}
+do_test rowid-8.5 {
+ execsql {
+ SELECT rowid, * FROM t4;
+ }
+} {1 1 2 133}
+do_test rowid-8.6 {
+ execsql {
+ INSERT INTO t3 VALUES(NULL);
+ SELECT last_insert_rowid();
+ }
+} {124}
+do_test rowid-8.7 {
+ execsql {
+ SELECT * FROM t3;
+ }
+} {123 124}
+do_test rowid-8.8 {
+ execsql {
+ SELECT rowid, * FROM t4;
+ }
+} {1 1 2 133 3 134}
+
+# ticket #377: Comparison between integer primiary key and floating point
+# values.
+#
+do_test rowid-9.1 {
+ execsql {
+ SELECT * FROM t3 WHERE a<123.5
+ }
+} {123}
+do_test rowid-9.2 {
+ execsql {
+ SELECT * FROM t3 WHERE a<124.5
+ }
+} {123 124}
+do_test rowid-9.3 {
+ execsql {
+ SELECT * FROM t3 WHERE a>123.5
+ }
+} {124}
+do_test rowid-9.4 {
+ execsql {
+ SELECT * FROM t3 WHERE a>122.5
+ }
+} {123 124}
+do_test rowid-9.5 {
+ execsql {
+ SELECT * FROM t3 WHERE a==123.5
+ }
+} {}
+do_test rowid-9.6 {
+ execsql {
+ SELECT * FROM t3 WHERE a==123.000
+ }
+} {123}
+do_test rowid-9.7 {
+ execsql {
+ SELECT * FROM t3 WHERE a>100.5 AND a<200.5
+ }
+} {123 124}
+do_test rowid-9.8 {
+ execsql {
+ SELECT * FROM t3 WHERE a>'xyz';
+ }
+} {}
+do_test rowid-9.9 {
+ execsql {
+ SELECT * FROM t3 WHERE a<'xyz';
+ }
+} {123 124}
+do_test rowid-9.10 {
+ execsql {
+ SELECT * FROM t3 WHERE a>=122.9 AND a<=123.1
+ }
+} {123}
+
+# Ticket #567. Comparisons of ROWID or integery primary key against
+# floating point numbers still do not always work.
+#
+do_test rowid-10.1 {
+ execsql {
+ CREATE TABLE t5(a);
+ INSERT INTO t5 VALUES(1);
+ INSERT INTO t5 VALUES(2);
+ INSERT INTO t5 SELECT a+2 FROM t5;
+ INSERT INTO t5 SELECT a+4 FROM t5;
+ SELECT rowid, * FROM t5;
+ }
+} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}
+do_test rowid-10.2 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid>=5.5}
+} {6 6 7 7 8 8}
+do_test rowid-10.3 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid>=5.0}
+} {5 5 6 6 7 7 8 8}
+do_test rowid-10.4 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid>5.5}
+} {6 6 7 7 8 8}
+do_test rowid-10.3.2 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid>5.0}
+} {6 6 7 7 8 8}
+do_test rowid-10.5 {
+ execsql {SELECT rowid, a FROM t5 WHERE 5.5<=rowid}
+} {6 6 7 7 8 8}
+do_test rowid-10.6 {
+ execsql {SELECT rowid, a FROM t5 WHERE 5.5<rowid}
+} {6 6 7 7 8 8}
+do_test rowid-10.7 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid<=5.5}
+} {1 1 2 2 3 3 4 4 5 5}
+do_test rowid-10.8 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid<5.5}
+} {1 1 2 2 3 3 4 4 5 5}
+do_test rowid-10.9 {
+ execsql {SELECT rowid, a FROM t5 WHERE 5.5>=rowid}
+} {1 1 2 2 3 3 4 4 5 5}
+do_test rowid-10.10 {
+ execsql {SELECT rowid, a FROM t5 WHERE 5.5>rowid}
+} {1 1 2 2 3 3 4 4 5 5}
+do_test rowid-10.11 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid>=5.5 ORDER BY rowid DESC}
+} {8 8 7 7 6 6}
+do_test rowid-10.11.2 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid>=5.0 ORDER BY rowid DESC}
+} {8 8 7 7 6 6 5 5}
+do_test rowid-10.12 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid>5.5 ORDER BY rowid DESC}
+} {8 8 7 7 6 6}
+do_test rowid-10.12.2 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid>5.0 ORDER BY rowid DESC}
+} {8 8 7 7 6 6}
+do_test rowid-10.13 {
+ execsql {SELECT rowid, a FROM t5 WHERE 5.5<=rowid ORDER BY rowid DESC}
+} {8 8 7 7 6 6}
+do_test rowid-10.14 {
+ execsql {SELECT rowid, a FROM t5 WHERE 5.5<rowid ORDER BY rowid DESC}
+} {8 8 7 7 6 6}
+do_test rowid-10.15 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid<=5.5 ORDER BY rowid DESC}
+} {5 5 4 4 3 3 2 2 1 1}
+do_test rowid-10.16 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid<5.5 ORDER BY rowid DESC}
+} {5 5 4 4 3 3 2 2 1 1}
+do_test rowid-10.17 {
+ execsql {SELECT rowid, a FROM t5 WHERE 5.5>=rowid ORDER BY rowid DESC}
+} {5 5 4 4 3 3 2 2 1 1}
+do_test rowid-10.18 {
+ execsql {SELECT rowid, a FROM t5 WHERE 5.5>rowid ORDER BY rowid DESC}
+} {5 5 4 4 3 3 2 2 1 1}
+
+do_test rowid-10.30 {
+ execsql {
+ CREATE TABLE t6(a);
+ INSERT INTO t6(rowid,a) SELECT -a,a FROM t5;
+ SELECT rowid, * FROM t6;
+ }
+} {-8 8 -7 7 -6 6 -5 5 -4 4 -3 3 -2 2 -1 1}
+do_test rowid-10.31.1 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid>=-5.5}
+} {-5 5 -4 4 -3 3 -2 2 -1 1}
+do_test rowid-10.31.2 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid>=-5.0}
+} {-5 5 -4 4 -3 3 -2 2 -1 1}
+do_test rowid-10.32.1 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid>=-5.5 ORDER BY rowid DESC}
+} {-1 1 -2 2 -3 3 -4 4 -5 5}
+do_test rowid-10.32.1 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid>=-5.0 ORDER BY rowid DESC}
+} {-1 1 -2 2 -3 3 -4 4 -5 5}
+do_test rowid-10.33 {
+ execsql {SELECT rowid, a FROM t6 WHERE -5.5<=rowid}
+} {-5 5 -4 4 -3 3 -2 2 -1 1}
+do_test rowid-10.34 {
+ execsql {SELECT rowid, a FROM t6 WHERE -5.5<=rowid ORDER BY rowid DESC}
+} {-1 1 -2 2 -3 3 -4 4 -5 5}
+do_test rowid-10.35.1 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid>-5.5}
+} {-5 5 -4 4 -3 3 -2 2 -1 1}
+do_test rowid-10.35.2 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid>-5.0}
+} {-4 4 -3 3 -2 2 -1 1}
+do_test rowid-10.36.1 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid>-5.5 ORDER BY rowid DESC}
+} {-1 1 -2 2 -3 3 -4 4 -5 5}
+do_test rowid-10.36.2 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid>-5.0 ORDER BY rowid DESC}
+} {-1 1 -2 2 -3 3 -4 4}
+do_test rowid-10.37 {
+ execsql {SELECT rowid, a FROM t6 WHERE -5.5<rowid}
+} {-5 5 -4 4 -3 3 -2 2 -1 1}
+do_test rowid-10.38 {
+ execsql {SELECT rowid, a FROM t6 WHERE -5.5<rowid ORDER BY rowid DESC}
+} {-1 1 -2 2 -3 3 -4 4 -5 5}
+do_test rowid-10.39 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid<=-5.5}
+} {-8 8 -7 7 -6 6}
+do_test rowid-10.40 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid<=-5.5 ORDER BY rowid DESC}
+} {-6 6 -7 7 -8 8}
+do_test rowid-10.41 {
+ execsql {SELECT rowid, a FROM t6 WHERE -5.5>=rowid}
+} {-8 8 -7 7 -6 6}
+do_test rowid-10.42 {
+ execsql {SELECT rowid, a FROM t6 WHERE -5.5>=rowid ORDER BY rowid DESC}
+} {-6 6 -7 7 -8 8}
+do_test rowid-10.43 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid<-5.5}
+} {-8 8 -7 7 -6 6}
+do_test rowid-10.44 {
+ execsql {SELECT rowid, a FROM t6 WHERE rowid<-5.5 ORDER BY rowid DESC}
+} {-6 6 -7 7 -8 8}
+do_test rowid-10.44 {
+ execsql {SELECT rowid, a FROM t6 WHERE -5.5>rowid}
+} {-8 8 -7 7 -6 6}
+do_test rowid-10.46 {
+ execsql {SELECT rowid, a FROM t6 WHERE -5.5>rowid ORDER BY rowid DESC}
+} {-6 6 -7 7 -8 8}
+
+# Comparison of rowid against string values.
+#
+do_test rowid-11.1 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid>'abc'}
+} {}
+do_test rowid-11.2 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid>='abc'}
+} {}
+do_test rowid-11.3 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid<'abc'}
+} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}
+do_test rowid-11.4 {
+ execsql {SELECT rowid, a FROM t5 WHERE rowid<='abc'}
+} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}
+
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/select1.test b/usr/src/lib/libsqlite/test/select1.test
new file mode 100644
index 0000000000..0d770adec7
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/select1.test
@@ -0,0 +1,744 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 SELECT statement.
+#
+# $Id: select1.test,v 1.30.2.3 2004/07/20 01:45:49 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Try to select on a non-existant table.
+#
+do_test select1-1.1 {
+ set v [catch {execsql {SELECT * FROM test1}} msg]
+ lappend v $msg
+} {1 {no such table: test1}}
+
+execsql {CREATE TABLE test1(f1 int, f2 int)}
+
+do_test select1-1.2 {
+ set v [catch {execsql {SELECT * FROM test1, test2}} msg]
+ lappend v $msg
+} {1 {no such table: test2}}
+do_test select1-1.3 {
+ set v [catch {execsql {SELECT * FROM test2, test1}} msg]
+ lappend v $msg
+} {1 {no such table: test2}}
+
+execsql {INSERT INTO test1(f1,f2) VALUES(11,22)}
+
+
+# Make sure the columns are extracted correctly.
+#
+do_test select1-1.4 {
+ execsql {SELECT f1 FROM test1}
+} {11}
+do_test select1-1.5 {
+ execsql {SELECT f2 FROM test1}
+} {22}
+do_test select1-1.6 {
+ execsql {SELECT f2, f1 FROM test1}
+} {22 11}
+do_test select1-1.7 {
+ execsql {SELECT f1, f2 FROM test1}
+} {11 22}
+do_test select1-1.8 {
+ execsql {SELECT * FROM test1}
+} {11 22}
+do_test select1-1.8.1 {
+ execsql {SELECT *, * FROM test1}
+} {11 22 11 22}
+do_test select1-1.8.2 {
+ execsql {SELECT *, min(f1,f2), max(f1,f2) FROM test1}
+} {11 22 11 22}
+do_test select1-1.8.3 {
+ execsql {SELECT 'one', *, 'two', * FROM test1}
+} {one 11 22 two 11 22}
+
+execsql {CREATE TABLE test2(r1 real, r2 real)}
+execsql {INSERT INTO test2(r1,r2) VALUES(1.1,2.2)}
+
+do_test select1-1.9 {
+ execsql {SELECT * FROM test1, test2}
+} {11 22 1.1 2.2}
+do_test select1-1.9.1 {
+ execsql {SELECT *, 'hi' FROM test1, test2}
+} {11 22 1.1 2.2 hi}
+do_test select1-1.9.2 {
+ execsql {SELECT 'one', *, 'two', * FROM test1, test2}
+} {one 11 22 1.1 2.2 two 11 22 1.1 2.2}
+do_test select1-1.10 {
+ execsql {SELECT test1.f1, test2.r1 FROM test1, test2}
+} {11 1.1}
+do_test select1-1.11 {
+ execsql {SELECT test1.f1, test2.r1 FROM test2, test1}
+} {11 1.1}
+do_test select1-1.11.1 {
+ execsql {SELECT * FROM test2, test1}
+} {1.1 2.2 11 22}
+do_test select1-1.11.2 {
+ execsql {SELECT * FROM test1 AS a, test1 AS b}
+} {11 22 11 22}
+do_test select1-1.12 {
+ execsql {SELECT max(test1.f1,test2.r1), min(test1.f2,test2.r2)
+ FROM test2, test1}
+} {11 2.2}
+do_test select1-1.13 {
+ execsql {SELECT min(test1.f1,test2.r1), max(test1.f2,test2.r2)
+ FROM test1, test2}
+} {1.1 22}
+
+set long {This is a string that is too big to fit inside a NBFS buffer}
+do_test select1-2.0 {
+ execsql "
+ DROP TABLE test2;
+ DELETE FROM test1;
+ INSERT INTO test1 VALUES(11,22);
+ INSERT INTO test1 VALUES(33,44);
+ CREATE TABLE t3(a,b);
+ INSERT INTO t3 VALUES('abc',NULL);
+ INSERT INTO t3 VALUES(NULL,'xyz');
+ INSERT INTO t3 SELECT * FROM test1;
+ CREATE TABLE t4(a,b);
+ INSERT INTO t4 VALUES(NULL,'$long');
+ SELECT * FROM t3;
+ "
+} {abc {} {} xyz 11 22 33 44}
+
+# Error messges from sqliteExprCheck
+#
+do_test select1-2.1 {
+ set v [catch {execsql {SELECT count(f1,f2) FROM test1}} msg]
+ lappend v $msg
+} {1 {wrong number of arguments to function count()}}
+do_test select1-2.2 {
+ set v [catch {execsql {SELECT count(f1) FROM test1}} msg]
+ lappend v $msg
+} {0 2}
+do_test select1-2.3 {
+ set v [catch {execsql {SELECT Count() FROM test1}} msg]
+ lappend v $msg
+} {0 2}
+do_test select1-2.4 {
+ set v [catch {execsql {SELECT COUNT(*) FROM test1}} msg]
+ lappend v $msg
+} {0 2}
+do_test select1-2.5 {
+ set v [catch {execsql {SELECT COUNT(*)+1 FROM test1}} msg]
+ lappend v $msg
+} {0 3}
+do_test select1-2.5.1 {
+ execsql {SELECT count(*),count(a),count(b) FROM t3}
+} {4 3 3}
+do_test select1-2.5.2 {
+ execsql {SELECT count(*),count(a),count(b) FROM t4}
+} {1 0 1}
+do_test select1-2.5.3 {
+ execsql {SELECT count(*),count(a),count(b) FROM t4 WHERE b=5}
+} {0 0 0}
+do_test select1-2.6 {
+ set v [catch {execsql {SELECT min(*) FROM test1}} msg]
+ lappend v $msg
+} {1 {wrong number of arguments to function min()}}
+do_test select1-2.7 {
+ set v [catch {execsql {SELECT Min(f1) FROM test1}} msg]
+ lappend v $msg
+} {0 11}
+do_test select1-2.8 {
+ set v [catch {execsql {SELECT MIN(f1,f2) FROM test1}} msg]
+ lappend v [lsort $msg]
+} {0 {11 33}}
+do_test select1-2.8.1 {
+ execsql {SELECT coalesce(min(a),'xyzzy') FROM t3}
+} {11}
+do_test select1-2.8.2 {
+ execsql {SELECT min(coalesce(a,'xyzzy')) FROM t3}
+} {11}
+do_test select1-2.8.3 {
+ execsql {SELECT min(b), min(b) FROM t4}
+} [list $long $long]
+do_test select1-2.9 {
+ set v [catch {execsql {SELECT MAX(*) FROM test1}} msg]
+ lappend v $msg
+} {1 {wrong number of arguments to function MAX()}}
+do_test select1-2.10 {
+ set v [catch {execsql {SELECT Max(f1) FROM test1}} msg]
+ lappend v $msg
+} {0 33}
+do_test select1-2.11 {
+ set v [catch {execsql {SELECT max(f1,f2) FROM test1}} msg]
+ lappend v [lsort $msg]
+} {0 {22 44}}
+do_test select1-2.12 {
+ set v [catch {execsql {SELECT MAX(f1,f2)+1 FROM test1}} msg]
+ lappend v [lsort $msg]
+} {0 {23 45}}
+do_test select1-2.13 {
+ set v [catch {execsql {SELECT MAX(f1)+1 FROM test1}} msg]
+ lappend v $msg
+} {0 34}
+do_test select1-2.13.1 {
+ execsql {SELECT coalesce(max(a),'xyzzy') FROM t3}
+} {abc}
+do_test select1-2.13.2 {
+ execsql {SELECT max(coalesce(a,'xyzzy')) FROM t3}
+} {xyzzy}
+do_test select1-2.14 {
+ set v [catch {execsql {SELECT SUM(*) FROM test1}} msg]
+ lappend v $msg
+} {1 {wrong number of arguments to function SUM()}}
+do_test select1-2.15 {
+ set v [catch {execsql {SELECT Sum(f1) FROM test1}} msg]
+ lappend v $msg
+} {0 44}
+do_test select1-2.16 {
+ set v [catch {execsql {SELECT sum(f1,f2) FROM test1}} msg]
+ lappend v $msg
+} {1 {wrong number of arguments to function sum()}}
+do_test select1-2.17 {
+ set v [catch {execsql {SELECT SUM(f1)+1 FROM test1}} msg]
+ lappend v $msg
+} {0 45}
+do_test select1-2.17.1 {
+ execsql {SELECT sum(a) FROM t3}
+} {44}
+do_test select1-2.18 {
+ set v [catch {execsql {SELECT XYZZY(f1) FROM test1}} msg]
+ lappend v $msg
+} {1 {no such function: XYZZY}}
+do_test select1-2.19 {
+ set v [catch {execsql {SELECT SUM(min(f1,f2)) FROM test1}} msg]
+ lappend v $msg
+} {0 44}
+do_test select1-2.20 {
+ set v [catch {execsql {SELECT SUM(min(f1)) FROM test1}} msg]
+ lappend v $msg
+} {1 {misuse of aggregate function min()}}
+
+# WHERE clause expressions
+#
+do_test select1-3.1 {
+ set v [catch {execsql {SELECT f1 FROM test1 WHERE f1<11}} msg]
+ lappend v $msg
+} {0 {}}
+do_test select1-3.2 {
+ set v [catch {execsql {SELECT f1 FROM test1 WHERE f1<=11}} msg]
+ lappend v $msg
+} {0 11}
+do_test select1-3.3 {
+ set v [catch {execsql {SELECT f1 FROM test1 WHERE f1=11}} msg]
+ lappend v $msg
+} {0 11}
+do_test select1-3.4 {
+ set v [catch {execsql {SELECT f1 FROM test1 WHERE f1>=11}} msg]
+ lappend v [lsort $msg]
+} {0 {11 33}}
+do_test select1-3.5 {
+ set v [catch {execsql {SELECT f1 FROM test1 WHERE f1>11}} msg]
+ lappend v [lsort $msg]
+} {0 33}
+do_test select1-3.6 {
+ set v [catch {execsql {SELECT f1 FROM test1 WHERE f1!=11}} msg]
+ lappend v [lsort $msg]
+} {0 33}
+do_test select1-3.7 {
+ set v [catch {execsql {SELECT f1 FROM test1 WHERE min(f1,f2)!=11}} msg]
+ lappend v [lsort $msg]
+} {0 33}
+do_test select1-3.8 {
+ set v [catch {execsql {SELECT f1 FROM test1 WHERE max(f1,f2)!=11}} msg]
+ lappend v [lsort $msg]
+} {0 {11 33}}
+do_test select1-3.9 {
+ set v [catch {execsql {SELECT f1 FROM test1 WHERE count(f1,f2)!=11}} msg]
+ lappend v $msg
+} {1 {wrong number of arguments to function count()}}
+
+# ORDER BY expressions
+#
+do_test select1-4.1 {
+ set v [catch {execsql {SELECT f1 FROM test1 ORDER BY f1}} msg]
+ lappend v $msg
+} {0 {11 33}}
+do_test select1-4.2 {
+ set v [catch {execsql {SELECT f1 FROM test1 ORDER BY -f1}} msg]
+ lappend v $msg
+} {0 {33 11}}
+do_test select1-4.3 {
+ set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1,f2)}} msg]
+ lappend v $msg
+} {0 {11 33}}
+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 function min()}}
+do_test select1-4.5 {
+ catchsql {
+ SELECT f1 FROM test1 ORDER BY 8.4;
+ }
+} {1 {ORDER BY terms must not be non-integer constants}}
+do_test select1-4.6 {
+ catchsql {
+ SELECT f1 FROM test1 ORDER BY '8.4';
+ }
+} {1 {ORDER BY terms must not be non-integer constants}}
+do_test select1-4.7 {
+ catchsql {
+ SELECT f1 FROM test1 ORDER BY 'xyz';
+ }
+} {1 {ORDER BY terms must not be non-integer constants}}
+do_test select1-4.8 {
+ execsql {
+ CREATE TABLE t5(a,b);
+ INSERT INTO t5 VALUES(1,10);
+ INSERT INTO t5 VALUES(2,9);
+ SELECT * FROM t5 ORDER BY 1;
+ }
+} {1 10 2 9}
+do_test select1-4.9 {
+ execsql {
+ SELECT * FROM t5 ORDER BY 2;
+ }
+} {2 9 1 10}
+do_test select1-4.10 {
+ catchsql {
+ SELECT * FROM t5 ORDER BY 3;
+ }
+} {1 {ORDER BY column number 3 out of range - should be between 1 and 2}}
+do_test select1-4.11 {
+ execsql {
+ INSERT INTO t5 VALUES(3,10);
+ SELECT * FROM t5 ORDER BY 2, 1 DESC;
+ }
+} {2 9 3 10 1 10}
+do_test select1-4.12 {
+ execsql {
+ SELECT * FROM t5 ORDER BY 1 DESC, b;
+ }
+} {3 10 2 9 1 10}
+do_test select1-4.13 {
+ execsql {
+ SELECT * FROM t5 ORDER BY b DESC, 1;
+ }
+} {1 10 3 10 2 9}
+
+
+# ORDER BY ignored on an aggregate query
+#
+do_test select1-5.1 {
+ set v [catch {execsql {SELECT max(f1) FROM test1 ORDER BY f2}} msg]
+ lappend v $msg
+} {0 33}
+
+execsql {CREATE TABLE test2(t1 test, t2 text)}
+execsql {INSERT INTO test2 VALUES('abc','xyz')}
+
+# Check for column naming
+#
+do_test select1-6.1 {
+ set v [catch {execsql2 {SELECT f1 FROM test1 ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {f1 11 f1 33}}
+do_test select1-6.1.1 {
+ execsql {PRAGMA full_column_names=on}
+ set v [catch {execsql2 {SELECT f1 FROM test1 ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {test1.f1 11 test1.f1 33}}
+do_test select1-6.1.2 {
+ set v [catch {execsql2 {SELECT f1 as 'f1' FROM test1 ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {f1 11 f1 33}}
+do_test select1-6.1.3 {
+ set v [catch {execsql2 {SELECT * FROM test1 WHERE f1==11}} msg]
+ lappend v $msg
+} {0 {test1.f1 11 test1.f2 22}}
+do_test select1-6.1.4 {
+ set v [catch {execsql2 {SELECT DISTINCT * FROM test1 WHERE f1==11}} msg]
+ execsql {PRAGMA full_column_names=off}
+ lappend v $msg
+} {0 {test1.f1 11 test1.f2 22}}
+do_test select1-6.1.5 {
+ set v [catch {execsql2 {SELECT * FROM test1 WHERE f1==11}} msg]
+ lappend v $msg
+} {0 {f1 11 f2 22}}
+do_test select1-6.1.6 {
+ set v [catch {execsql2 {SELECT DISTINCT * FROM test1 WHERE f1==11}} msg]
+ lappend v $msg
+} {0 {f1 11 f2 22}}
+do_test select1-6.2 {
+ set v [catch {execsql2 {SELECT f1 as xyzzy FROM test1 ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {xyzzy 11 xyzzy 33}}
+do_test select1-6.3 {
+ set v [catch {execsql2 {SELECT f1 as "xyzzy" FROM test1 ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {xyzzy 11 xyzzy 33}}
+do_test select1-6.3.1 {
+ set v [catch {execsql2 {SELECT f1 as 'xyzzy ' FROM test1 ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {{xyzzy } 11 {xyzzy } 33}}
+do_test select1-6.4 {
+ set v [catch {execsql2 {SELECT f1+F2 as xyzzy FROM test1 ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {xyzzy 33 xyzzy 77}}
+do_test select1-6.4a {
+ set v [catch {execsql2 {SELECT f1+F2 FROM test1 ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {f1+F2 33 f1+F2 77}}
+do_test select1-6.5 {
+ set v [catch {execsql2 {SELECT test1.f1+F2 FROM test1 ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {test1.f1+F2 33 test1.f1+F2 77}}
+do_test select1-6.5.1 {
+ execsql2 {PRAGMA full_column_names=on}
+ set v [catch {execsql2 {SELECT test1.f1+F2 FROM test1 ORDER BY f2}} msg]
+ execsql2 {PRAGMA full_column_names=off}
+ lappend v $msg
+} {0 {test1.f1+F2 33 test1.f1+F2 77}}
+do_test select1-6.6 {
+ set v [catch {execsql2 {SELECT test1.f1+F2, t1 FROM test1, test2
+ ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {test1.f1+F2 33 t1 abc test1.f1+F2 77 t1 abc}}
+do_test select1-6.7 {
+ set v [catch {execsql2 {SELECT A.f1, t1 FROM test1 as A, test2
+ ORDER BY f2}} msg]
+ lappend v $msg
+} {0 {A.f1 11 t1 abc A.f1 33 t1 abc}}
+do_test select1-6.8 {
+ set v [catch {execsql2 {SELECT A.f1, f1 FROM test1 as A, test1 as B
+ ORDER BY f2}} msg]
+ lappend v $msg
+} {1 {ambiguous column name: f1}}
+do_test select1-6.8b {
+ set v [catch {execsql2 {SELECT A.f1, B.f1 FROM test1 as A, test1 as B
+ ORDER BY f2}} msg]
+ lappend v $msg
+} {1 {ambiguous column name: f2}}
+do_test select1-6.8c {
+ set v [catch {execsql2 {SELECT A.f1, f1 FROM test1 as A, test1 as A
+ ORDER BY f2}} msg]
+ lappend v $msg
+} {1 {ambiguous column name: A.f1}}
+do_test select1-6.9 {
+ set v [catch {execsql2 {SELECT A.f1, B.f1 FROM test1 as A, test1 as B
+ ORDER BY A.f1, B.f1}} msg]
+ lappend v $msg
+} {0 {A.f1 11 B.f1 11 A.f1 11 B.f1 33 A.f1 33 B.f1 11 A.f1 33 B.f1 33}}
+do_test select1-6.10 {
+ set v [catch {execsql2 {
+ SELECT f1 FROM test1 UNION SELECT f2 FROM test1
+ ORDER BY f2;
+ }} msg]
+ lappend v $msg
+} {0 {f2 11 f2 22 f2 33 f2 44}}
+do_test select1-6.11 {
+ set v [catch {execsql2 {
+ SELECT f1 FROM test1 UNION SELECT f2+100 FROM test1
+ ORDER BY f2+100;
+ }} msg]
+ lappend v $msg
+} {0 {f2+100 11 f2+100 33 f2+100 122 f2+100 144}}
+
+do_test select1-7.1 {
+ set v [catch {execsql {
+ SELECT f1 FROM test1 WHERE f2=;
+ }} msg]
+ lappend v $msg
+} {1 {near ";": syntax error}}
+do_test select1-7.2 {
+ set v [catch {execsql {
+ SELECT f1 FROM test1 UNION SELECT WHERE;
+ }} msg]
+ lappend v $msg
+} {1 {near "WHERE": syntax error}}
+do_test select1-7.3 {
+ set v [catch {execsql {SELECT f1 FROM test1 as 'hi', test2 as}} msg]
+ lappend v $msg
+} {1 {near "as": syntax error}}
+do_test select1-7.4 {
+ set v [catch {execsql {
+ SELECT f1 FROM test1 ORDER BY;
+ }} msg]
+ lappend v $msg
+} {1 {near ";": syntax error}}
+do_test select1-7.5 {
+ set v [catch {execsql {
+ SELECT f1 FROM test1 ORDER BY f1 desc, f2 where;
+ }} msg]
+ lappend v $msg
+} {1 {near "where": syntax error}}
+do_test select1-7.6 {
+ set v [catch {execsql {
+ SELECT count(f1,f2 FROM test1;
+ }} msg]
+ lappend v $msg
+} {1 {near "FROM": syntax error}}
+do_test select1-7.7 {
+ set v [catch {execsql {
+ SELECT count(f1,f2+) FROM test1;
+ }} msg]
+ lappend v $msg
+} {1 {near ")": syntax error}}
+do_test select1-7.8 {
+ set v [catch {execsql {
+ SELECT f1 FROM test1 ORDER BY f2, f1+;
+ }} msg]
+ lappend v $msg
+} {1 {near ";": syntax error}}
+
+do_test select1-8.1 {
+ execsql {SELECT f1 FROM test1 WHERE 4.3+2.4 OR 1 ORDER BY f1}
+} {11 33}
+do_test select1-8.2 {
+ execsql {
+ SELECT f1 FROM test1 WHERE ('x' || f1) BETWEEN 'x10' AND 'x20'
+ ORDER BY f1
+ }
+} {11}
+do_test select1-8.3 {
+ execsql {
+ SELECT f1 FROM test1 WHERE 5-3==2
+ ORDER BY f1
+ }
+} {11 33}
+do_test select1-8.4 {
+ execsql {
+ SELECT coalesce(f1/(f1-11),'x'),
+ coalesce(min(f1/(f1-11),5),'y'),
+ coalesce(max(f1/(f1-33),6),'z')
+ FROM test1 ORDER BY f1
+ }
+} {x y 6 1.5 1.5 z}
+do_test select1-8.5 {
+ execsql {
+ SELECT min(1,2,3), -max(1,2,3)
+ FROM test1 ORDER BY f1
+ }
+} {1 -3 1 -3}
+
+
+# Check the behavior when the result set is empty
+#
+do_test select1-9.1 {
+ catch {unset r}
+ set r(*) {}
+ db eval {SELECT * FROM test1 WHERE f1<0} r {}
+ set r(*)
+} {}
+do_test select1-9.2 {
+ execsql {PRAGMA empty_result_callbacks=on}
+ set r(*) {}
+ db eval {SELECT * FROM test1 WHERE f1<0} r {}
+ set r(*)
+} {f1 f2}
+do_test select1-9.3 {
+ set r(*) {}
+ db eval {SELECT * FROM test1 WHERE f1<(select count(*) from test2)} r {}
+ set r(*)
+} {f1 f2}
+do_test select1-9.4 {
+ set r(*) {}
+ db eval {SELECT * FROM test1 ORDER BY f1} r {}
+ set r(*)
+} {f1 f2}
+do_test select1-9.5 {
+ set r(*) {}
+ db eval {SELECT * FROM test1 WHERE f1<0 ORDER BY f1} r {}
+ set r(*)
+} {f1 f2}
+unset r
+
+# Check for ORDER BY clauses that refer to an AS name in the column list
+#
+do_test select1-10.1 {
+ execsql {
+ SELECT f1 AS x FROM test1 ORDER BY x
+ }
+} {11 33}
+do_test select1-10.2 {
+ execsql {
+ SELECT f1 AS x FROM test1 ORDER BY -x
+ }
+} {33 11}
+do_test select1-10.3 {
+ execsql {
+ SELECT f1-23 AS x FROM test1 ORDER BY abs(x)
+ }
+} {10 -12}
+do_test select1-10.4 {
+ execsql {
+ SELECT f1-23 AS x FROM test1 ORDER BY -abs(x)
+ }
+} {-12 10}
+do_test select1-10.5 {
+ execsql {
+ SELECT f1-22 AS x, f2-22 as y FROM test1
+ }
+} {-11 0 11 22}
+do_test select1-10.6 {
+ execsql {
+ SELECT f1-22 AS x, f2-22 as y FROM test1 WHERE x>0 AND y<50
+ }
+} {11 22}
+
+# Check the ability to specify "TABLE.*" in the result set of a SELECT
+#
+do_test select1-11.1 {
+ execsql {
+ DELETE FROM t3;
+ DELETE FROM t4;
+ INSERT INTO t3 VALUES(1,2);
+ INSERT INTO t4 VALUES(3,4);
+ SELECT * FROM t3, t4;
+ }
+} {1 2 3 4}
+do_test select1-11.2 {
+ execsql2 {
+ SELECT * FROM t3, t4;
+ }
+} {t3.a 1 t3.b 2 t4.a 3 t4.b 4}
+do_test select1-11.3 {
+ execsql2 {
+ SELECT * FROM t3 AS x, t4 AS y;
+ }
+} {x.a 1 x.b 2 y.a 3 y.b 4}
+do_test select1-11.4.1 {
+ execsql {
+ SELECT t3.*, t4.b FROM t3, t4;
+ }
+} {1 2 4}
+do_test select1-11.4.2 {
+ execsql {
+ SELECT "t3".*, t4.b FROM t3, t4;
+ }
+} {1 2 4}
+do_test select1-11.5 {
+ execsql2 {
+ SELECT t3.*, t4.b FROM t3, t4;
+ }
+} {t3.a 1 t3.b 2 t4.b 4}
+do_test select1-11.6 {
+ execsql2 {
+ SELECT x.*, y.b FROM t3 AS x, t4 AS y;
+ }
+} {x.a 1 x.b 2 y.b 4}
+do_test select1-11.7 {
+ execsql {
+ SELECT t3.b, t4.* FROM t3, t4;
+ }
+} {2 3 4}
+do_test select1-11.8 {
+ execsql2 {
+ SELECT t3.b, t4.* FROM t3, t4;
+ }
+} {t3.b 2 t4.a 3 t4.b 4}
+do_test select1-11.9 {
+ execsql2 {
+ SELECT x.b, y.* FROM t3 AS x, t4 AS y;
+ }
+} {x.b 2 y.a 3 y.b 4}
+do_test select1-11.10 {
+ catchsql {
+ SELECT t5.* FROM t3, t4;
+ }
+} {1 {no such table: t5}}
+do_test select1-11.11 {
+ catchsql {
+ SELECT t3.* FROM t3 AS x, t4;
+ }
+} {1 {no such table: t3}}
+do_test select1-11.12 {
+ execsql2 {
+ SELECT t3.* FROM t3, (SELECT max(a), max(b) FROM t4)
+ }
+} {t3.a 1 t3.b 2}
+do_test select1-11.13 {
+ execsql2 {
+ SELECT t3.* FROM (SELECT max(a), max(b) FROM t4), t3
+ }
+} {t3.a 1 t3.b 2}
+do_test select1-11.14 {
+ execsql2 {
+ SELECT * FROM t3, (SELECT max(a), max(b) FROM t4) AS 'tx'
+ }
+} {t3.a 1 t3.b 2 tx.max(a) 3 tx.max(b) 4}
+do_test select1-11.15 {
+ execsql2 {
+ SELECT y.*, t3.* FROM t3, (SELECT max(a), max(b) FROM t4) AS y
+ }
+} {y.max(a) 3 y.max(b) 4 t3.a 1 t3.b 2}
+do_test select1-11.16 {
+ execsql2 {
+ SELECT y.* FROM t3 as y, t4 as z
+ }
+} {y.a 1 y.b 2}
+
+# Tests of SELECT statements without a FROM clause.
+#
+do_test select1-12.1 {
+ execsql2 {
+ SELECT 1+2+3
+ }
+} {1+2+3 6}
+do_test select1-12.2 {
+ execsql2 {
+ SELECT 1,'hello',2
+ }
+} {1 1 'hello' hello 2 2}
+do_test select1-12.3 {
+ execsql2 {
+ SELECT 1 AS 'a','hello' AS 'b',2 AS 'c'
+ }
+} {a 1 b hello c 2}
+do_test select1-12.4 {
+ execsql {
+ DELETE FROM t3;
+ INSERT INTO t3 VALUES(1,2);
+ SELECT * FROM t3 UNION SELECT 3 AS 'a', 4 ORDER BY a;
+ }
+} {1 2 3 4}
+do_test select1-12.5 {
+ execsql {
+ SELECT 3, 4 UNION SELECT * FROM t3;
+ }
+} {1 2 3 4}
+do_test select1-12.6 {
+ execsql {
+ SELECT * FROM t3 WHERE a=(SELECT 1);
+ }
+} {1 2}
+do_test select1-12.7 {
+ execsql {
+ SELECT * FROM t3 WHERE a=(SELECT 2);
+ }
+} {}
+do_test select1-12.8 {
+ execsql2 {
+ SELECT x FROM (
+ SELECT a,b FROM t3 UNION SELECT a AS 'x', b AS 'y' FROM t4 ORDER BY a,b
+ ) ORDER BY x;
+ }
+} {x 1 x 3}
+do_test select1-12.9 {
+ execsql2 {
+ SELECT z.x FROM (
+ SELECT a,b FROM t3 UNION SELECT a AS 'x', b AS 'y' FROM t4 ORDER BY a,b
+ ) AS 'z' ORDER BY x;
+ }
+} {z.x 1 z.x 3}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/select2.test b/usr/src/lib/libsqlite/test/select2.test
new file mode 100644
index 0000000000..446f1b3e7b
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/select2.test
@@ -0,0 +1,165 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 SELECT statement.
+#
+# $Id: select2.test,v 1.18 2002/04/02 13:26:11 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a table with some data
+#
+execsql {CREATE TABLE tbl1(f1 int, f2 int)}
+set f [open ./testdata1.txt w]
+for {set i 0} {$i<=30} {incr i} {
+ puts $f "[expr {$i%9}]\t[expr {$i%10}]"
+}
+close $f
+execsql {COPY tbl1 FROM './testdata1.txt'}
+file delete -force ./testdata1.txt
+catch {unset data}
+
+# Do a second query inside a first.
+#
+do_test select2-1.1 {
+ set sql {SELECT DISTINCT f1 FROM tbl1 ORDER BY f1}
+ set r {}
+ db eval $sql data {
+ set f1 $data(f1)
+ lappend r $f1:
+ set sql2 "SELECT f2 FROM tbl1 WHERE f1=$f1 ORDER BY f2"
+ db eval $sql2 d2 {
+ lappend r $d2(f2)
+ }
+ }
+ set r
+} {0: 0 7 8 9 1: 0 1 8 9 2: 0 1 2 9 3: 0 1 2 3 4: 2 3 4 5: 3 4 5 6: 4 5 6 7: 5 6 7 8: 6 7 8}
+
+do_test select2-1.2 {
+ set sql {SELECT DISTINCT f1 FROM tbl1 WHERE f1>3 AND f1<5}
+ set r {}
+ db eval $sql data {
+ set f1 $data(f1)
+ lappend r $f1:
+ set sql2 "SELECT f2 FROM tbl1 WHERE f1=$f1 ORDER BY f2"
+ db eval $sql2 d2 {
+ lappend r $d2(f2)
+ }
+ }
+ set r
+} {4: 2 3 4}
+
+# Create a largish table
+#
+do_test select2-2.0 {
+ execsql {CREATE TABLE tbl2(f1 int, f2 int, f3 int)}
+ set f [open ./testdata1.txt w]
+ for {set i 1} {$i<=30000} {incr i} {
+ puts $f "$i\t[expr {$i*2}]\t[expr {$i*3}]"
+ }
+ close $f
+ # execsql {--vdbe-trace-on--}
+ execsql {COPY tbl2 FROM './testdata1.txt'}
+ file delete -force ./testdata1.txt
+} {}
+
+do_test select2-2.1 {
+ execsql {SELECT count(*) FROM tbl2}
+} {30000}
+do_test select2-2.2 {
+ execsql {SELECT count(*) FROM tbl2 WHERE f2>1000}
+} {29500}
+
+do_test select2-3.1 {
+ execsql {SELECT f1 FROM tbl2 WHERE 1000=f2}
+} {500}
+
+do_test select2-3.2a {
+ execsql {CREATE INDEX idx1 ON tbl2(f2)}
+} {}
+
+do_test select2-3.2b {
+ execsql {SELECT f1 FROM tbl2 WHERE 1000=f2}
+} {500}
+do_test select2-3.2c {
+ execsql {SELECT f1 FROM tbl2 WHERE f2=1000}
+} {500}
+do_test select2-3.2d {
+ set sqlite_search_count 0
+ execsql {SELECT * FROM tbl2 WHERE 1000=f2}
+ set sqlite_search_count
+} {3}
+do_test select2-3.2e {
+ set sqlite_search_count 0
+ execsql {SELECT * FROM tbl2 WHERE f2=1000}
+ set sqlite_search_count
+} {3}
+
+# Make sure queries run faster with an index than without
+#
+do_test select2-3.3 {
+ execsql {DROP INDEX idx1}
+ set sqlite_search_count 0
+ execsql {SELECT f1 FROM tbl2 WHERE f2==2000}
+ set sqlite_search_count
+} {29999}
+
+# Make sure we can optimize functions in the WHERE clause that
+# use fields from two or more different table. (Bug #6)
+#
+do_test select2-4.1 {
+ execsql {
+ CREATE TABLE aa(a);
+ CREATE TABLE bb(b);
+ INSERT INTO aa VALUES(1);
+ INSERT INTO aa VALUES(3);
+ INSERT INTO bb VALUES(2);
+ INSERT INTO bb VALUES(4);
+ SELECT * FROM aa, bb WHERE max(a,b)>2;
+ }
+} {1 4 3 2 3 4}
+do_test select2-4.2 {
+ execsql {
+ INSERT INTO bb VALUES(0);
+ SELECT * FROM aa, bb WHERE b;
+ }
+} {1 2 1 4 3 2 3 4}
+do_test select2-4.3 {
+ execsql {
+ SELECT * FROM aa, bb WHERE NOT b;
+ }
+} {1 0 3 0}
+do_test select2-4.4 {
+ execsql {
+ SELECT * FROM aa, bb WHERE min(a,b);
+ }
+} {1 2 1 4 3 2 3 4}
+do_test select2-4.5 {
+ execsql {
+ SELECT * FROM aa, bb WHERE NOT min(a,b);
+ }
+} {1 0 3 0}
+do_test select2-4.6 {
+ execsql {
+ SELECT * FROM aa, bb WHERE CASE WHEN a=b-1 THEN 1 END;
+ }
+} {1 2 3 4}
+do_test select2-4.7 {
+ execsql {
+ SELECT * FROM aa, bb WHERE CASE WHEN a=b-1 THEN 0 ELSE 1 END;
+ }
+} {1 4 1 0 3 2 3 0}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/select3.test b/usr/src/lib/libsqlite/test/select3.test
new file mode 100644
index 0000000000..c7a232d076
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/select3.test
@@ -0,0 +1,228 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 aggregate functions and the
+# GROUP BY and HAVING clauses of SELECT statements.
+#
+# $Id: select3.test,v 1.8 2003/01/31 17:16:37 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Build some test data
+#
+do_test select3-1.0 {
+ set fd [open data1.txt w]
+ for {set i 1} {$i<32} {incr i} {
+ for {set j 0} {pow(2,$j)<$i} {incr j} {}
+ puts $fd "$i\t$j"
+ }
+ close $fd
+ execsql {
+ CREATE TABLE t1(n int, log int);
+ COPY t1 FROM 'data1.txt'
+ }
+ file delete data1.txt
+ execsql {SELECT DISTINCT log FROM t1 ORDER BY log}
+} {0 1 2 3 4 5}
+
+# Basic aggregate functions.
+#
+do_test select3-1.1 {
+ execsql {SELECT count(*) FROM t1}
+} {31}
+do_test select3-1.2 {
+ execsql {
+ SELECT min(n),min(log),max(n),max(log),sum(n),sum(log),avg(n),avg(log)
+ FROM t1
+ }
+} {1 0 31 5 496 124 16 4}
+do_test select3-1.3 {
+ execsql {SELECT max(n)/avg(n), max(log)/avg(log) FROM t1}
+} {1.9375 1.25}
+
+# Try some basic GROUP BY clauses
+#
+do_test select3-2.1 {
+ execsql {SELECT log, count(*) FROM t1 GROUP BY log ORDER BY log}
+} {0 1 1 1 2 2 3 4 4 8 5 15}
+do_test select3-2.2 {
+ execsql {SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log}
+} {0 1 1 2 2 3 3 5 4 9 5 17}
+do_test select3-2.3 {
+ execsql {SELECT log, avg(n) FROM t1 GROUP BY log ORDER BY log}
+} {0 1 1 2 2 3.5 3 6.5 4 12.5 5 24}
+do_test select3-2.3 {
+ execsql {SELECT log, avg(n)+1 FROM t1 GROUP BY log ORDER BY log}
+} {0 2 1 3 2 4.5 3 7.5 4 13.5 5 25}
+do_test select3-2.4 {
+ execsql {SELECT log, avg(n)-min(n) FROM t1 GROUP BY log ORDER BY log}
+} {0 0 1 0 2 0.5 3 1.5 4 3.5 5 7}
+do_test select3-2.5 {
+ execsql {SELECT log*2+1, avg(n)-min(n) FROM t1 GROUP BY log ORDER BY log}
+} {1 0 3 0 5 0.5 7 1.5 9 3.5 11 7}
+do_test select3-2.6 {
+ execsql {
+ SELECT log*2+1 as x, count(*) FROM t1 GROUP BY x ORDER BY x
+ }
+} {1 1 3 1 5 2 7 4 9 8 11 15}
+do_test select3-2.7 {
+ execsql {
+ SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY y
+ }
+} {1 1 3 1 5 2 7 4 9 8 11 15}
+do_test select3-2.8 {
+ execsql {
+ SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY 10-(x+y)
+ }
+} {11 15 9 8 7 4 5 2 3 1 1 1}
+do_test select3-2.9 {
+ catchsql {
+ SELECT log, count(*) FROM t1 GROUP BY 'x' ORDER BY log;
+ }
+} {1 {GROUP BY terms must not be non-integer constants}}
+do_test select3-2.10 {
+ catchsql {
+ SELECT log, count(*) FROM t1 GROUP BY 0 ORDER BY log;
+ }
+} {1 {GROUP BY column number 0 out of range - should be between 1 and 2}}
+do_test select3-2.11 {
+ catchsql {
+ SELECT log, count(*) FROM t1 GROUP BY 3 ORDER BY log;
+ }
+} {1 {GROUP BY column number 3 out of range - should be between 1 and 2}}
+do_test select3-2.12 {
+ catchsql {
+ SELECT log, count(*) FROM t1 GROUP BY 1 ORDER BY log;
+ }
+} {0 {0 1 1 1 2 2 3 4 4 8 5 15}}
+#do_test select3-2.13 {
+# catchsql {
+# SELECT log, count(*) FROM t1 GROUP BY 2 ORDER BY log;
+# }
+#} {0 {0 1 1 1 2 2 3 4 4 8 5 15}}
+#do_test select3-2.14 {
+# catchsql {
+# SELECT log, count(*) FROM t1 GROUP BY count(*) ORDER BY log;
+# }
+#} {0 {0 1 1 1 2 2 3 4 4 8 5 15}}
+
+# Cannot have a HAVING without a GROUP BY
+#
+do_test select3-3.1 {
+ set v [catch {execsql {SELECT log, count(*) FROM t1 HAVING log>=4}} msg]
+ lappend v $msg
+} {1 {a GROUP BY clause is required before HAVING}}
+
+# Toss in some HAVING clauses
+#
+do_test select3-4.1 {
+ execsql {SELECT log, count(*) FROM t1 GROUP BY log HAVING log>=4 ORDER BY log}
+} {4 8 5 15}
+do_test select3-4.2 {
+ execsql {
+ SELECT log, count(*) FROM t1
+ GROUP BY log
+ HAVING count(*)>=4
+ ORDER BY log
+ }
+} {3 4 4 8 5 15}
+do_test select3-4.3 {
+ execsql {
+ SELECT log, count(*) FROM t1
+ GROUP BY log
+ HAVING count(*)>=4
+ ORDER BY max(n)
+ }
+} {3 4 4 8 5 15}
+do_test select3-4.4 {
+ execsql {
+ SELECT log AS x, count(*) AS y FROM t1
+ GROUP BY x
+ HAVING y>=4
+ ORDER BY max(n)
+ }
+} {3 4 4 8 5 15}
+do_test select3-4.5 {
+ execsql {
+ SELECT log AS x FROM t1
+ GROUP BY x
+ HAVING count(*)>=4
+ ORDER BY max(n)
+ }
+} {3 4 5}
+
+do_test select3-5.1 {
+ execsql {
+ SELECT log, count(*), avg(n), max(n+log*2) FROM t1
+ GROUP BY log
+ ORDER BY max(n+log*2), avg(n)
+ }
+} {0 1 1 1 1 1 2 4 2 2 3.5 8 3 4 6.5 14 4 8 12.5 24 5 15 24 41}
+do_test select3-5.2 {
+ execsql {
+ SELECT log, count(*), avg(n), max(n+log*2) FROM t1
+ GROUP BY log
+ ORDER BY max(n+log*2), min(log,avg(n))
+ }
+} {0 1 1 1 1 1 2 4 2 2 3.5 8 3 4 6.5 14 4 8 12.5 24 5 15 24 41}
+
+# Test sorting of GROUP BY results in the presence of an index
+# on the GROUP BY column.
+#
+do_test select3-6.1 {
+ execsql {
+ SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log;
+ }
+} {0 1 1 2 2 3 3 5 4 9 5 17}
+do_test select3-6.2 {
+ execsql {
+ SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log DESC;
+ }
+} {5 17 4 9 3 5 2 3 1 2 0 1}
+do_test select3-6.3 {
+ execsql {
+ SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1;
+ }
+} {0 1 1 2 2 3 3 5 4 9 5 17}
+do_test select3-6.4 {
+ execsql {
+ SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1 DESC;
+ }
+} {5 17 4 9 3 5 2 3 1 2 0 1}
+do_test select3-6.5 {
+ execsql {
+ CREATE INDEX i1 ON t1(log);
+ SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log;
+ }
+} {0 1 1 2 2 3 3 5 4 9 5 17}
+do_test select3-6.6 {
+ execsql {
+ SELECT log, min(n) FROM t1 GROUP BY log ORDER BY log DESC;
+ }
+} {5 17 4 9 3 5 2 3 1 2 0 1}
+do_test select3-6.7 {
+ execsql {
+ SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1;
+ }
+} {0 1 1 2 2 3 3 5 4 9 5 17}
+do_test select3-6.8 {
+ execsql {
+ SELECT log, min(n) FROM t1 GROUP BY log ORDER BY 1 DESC;
+ }
+} {5 17 4 9 3 5 2 3 1 2 0 1}
+
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/select4.test b/usr/src/lib/libsqlite/test/select4.test
new file mode 100644
index 0000000000..8fb34a2156
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/select4.test
@@ -0,0 +1,498 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 UNION, INTERSECT and EXCEPT operators
+# in SELECT statements.
+#
+# $Id: select4.test,v 1.13 2003/02/02 12:41:27 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Build some test data
+#
+set fd [open data1.txt w]
+for {set i 1} {$i<32} {incr i} {
+ for {set j 0} {pow(2,$j)<$i} {incr j} {}
+ puts $fd "$i\t$j"
+}
+close $fd
+execsql {
+ CREATE TABLE t1(n int, log int);
+ COPY t1 FROM 'data1.txt'
+}
+file delete data1.txt
+
+do_test select4-1.0 {
+ execsql {SELECT DISTINCT log FROM t1 ORDER BY log}
+} {0 1 2 3 4 5}
+
+# Union All operator
+#
+do_test select4-1.1a {
+ lsort [execsql {SELECT DISTINCT log FROM t1}]
+} {0 1 2 3 4 5}
+do_test select4-1.1b {
+ lsort [execsql {SELECT n FROM t1 WHERE log=3}]
+} {5 6 7 8}
+do_test select4-1.1c {
+ execsql {
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }
+} {0 1 2 3 4 5 5 6 7 8}
+do_test select4-1.1d {
+ execsql {
+ CREATE TABLE t2 AS
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ SELECT * FROM t2;
+ }
+} {0 1 2 3 4 5 5 6 7 8}
+execsql {DROP TABLE t2}
+do_test select4-1.1e {
+ execsql {
+ CREATE TABLE t2 AS
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log DESC;
+ SELECT * FROM t2;
+ }
+} {8 7 6 5 5 4 3 2 1 0}
+execsql {DROP TABLE t2}
+do_test select4-1.1f {
+ execsql {
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=2
+ }
+} {0 1 2 3 4 5 3 4}
+do_test select4-1.1g {
+ execsql {
+ CREATE TABLE t2 AS
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=2;
+ SELECT * FROM t2;
+ }
+} {0 1 2 3 4 5 3 4}
+execsql {DROP TABLE t2}
+do_test select4-1.2 {
+ execsql {
+ SELECT log FROM t1 WHERE n IN
+ (SELECT DISTINCT log FROM t1 UNION ALL
+ SELECT n FROM t1 WHERE log=3)
+ ORDER BY log;
+ }
+} {0 1 2 2 3 3 3 3}
+do_test select4-1.3 {
+ set v [catch {execsql {
+ SELECT DISTINCT log FROM t1 ORDER BY log
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }} msg]
+ lappend v $msg
+} {1 {ORDER BY clause should come after UNION ALL not before}}
+
+# Union operator
+#
+do_test select4-2.1 {
+ execsql {
+ SELECT DISTINCT log FROM t1
+ UNION
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }
+} {0 1 2 3 4 5 6 7 8}
+do_test select4-2.2 {
+ execsql {
+ SELECT log FROM t1 WHERE n IN
+ (SELECT DISTINCT log FROM t1 UNION
+ SELECT n FROM t1 WHERE log=3)
+ ORDER BY log;
+ }
+} {0 1 2 2 3 3 3 3}
+do_test select4-2.3 {
+ set v [catch {execsql {
+ SELECT DISTINCT log FROM t1 ORDER BY log
+ UNION
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }} msg]
+ lappend v $msg
+} {1 {ORDER BY clause should come after UNION not before}}
+
+# Except operator
+#
+do_test select4-3.1.1 {
+ execsql {
+ SELECT DISTINCT log FROM t1
+ EXCEPT
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }
+} {0 1 2 3 4}
+do_test select4-3.1.2 {
+ execsql {
+ CREATE TABLE t2 AS
+ SELECT DISTINCT log FROM t1
+ EXCEPT
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ SELECT * FROM t2;
+ }
+} {0 1 2 3 4}
+execsql {DROP TABLE t2}
+do_test select4-3.1.3 {
+ execsql {
+ CREATE TABLE t2 AS
+ SELECT DISTINCT log FROM t1
+ EXCEPT
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log DESC;
+ SELECT * FROM t2;
+ }
+} {4 3 2 1 0}
+execsql {DROP TABLE t2}
+do_test select4-3.2 {
+ execsql {
+ SELECT log FROM t1 WHERE n IN
+ (SELECT DISTINCT log FROM t1 EXCEPT
+ SELECT n FROM t1 WHERE log=3)
+ ORDER BY log;
+ }
+} {0 1 2 2}
+do_test select4-3.3 {
+ set v [catch {execsql {
+ SELECT DISTINCT log FROM t1 ORDER BY log
+ EXCEPT
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }} msg]
+ lappend v $msg
+} {1 {ORDER BY clause should come after EXCEPT not before}}
+
+# Intersect operator
+#
+do_test select4-4.1.1 {
+ execsql {
+ SELECT DISTINCT log FROM t1
+ INTERSECT
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }
+} {5}
+do_test select4-4.1.2 {
+ execsql {
+ SELECT DISTINCT log FROM t1 UNION ALL SELECT 6
+ INTERSECT
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }
+} {5 6}
+do_test select4-4.1.3 {
+ execsql {
+ CREATE TABLE t2 AS
+ SELECT DISTINCT log FROM t1 UNION ALL SELECT 6
+ INTERSECT
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ SELECT * FROM t2;
+ }
+} {5 6}
+execsql {DROP TABLE t2}
+do_test select4-4.1.4 {
+ execsql {
+ CREATE TABLE t2 AS
+ SELECT DISTINCT log FROM t1 UNION ALL SELECT 6
+ INTERSECT
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log DESC;
+ SELECT * FROM t2;
+ }
+} {6 5}
+execsql {DROP TABLE t2}
+do_test select4-4.2 {
+ execsql {
+ SELECT log FROM t1 WHERE n IN
+ (SELECT DISTINCT log FROM t1 INTERSECT
+ SELECT n FROM t1 WHERE log=3)
+ ORDER BY log;
+ }
+} {3}
+do_test select4-4.3 {
+ set v [catch {execsql {
+ SELECT DISTINCT log FROM t1 ORDER BY log
+ INTERSECT
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }} msg]
+ lappend v $msg
+} {1 {ORDER BY clause should come after INTERSECT not before}}
+
+# Various error messages while processing UNION or INTERSECT
+#
+do_test select4-5.1 {
+ set v [catch {execsql {
+ SELECT DISTINCT log FROM t2
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }} msg]
+ lappend v $msg
+} {1 {no such table: t2}}
+do_test select4-5.2 {
+ set v [catch {execsql {
+ SELECT DISTINCT log AS "xyzzy" FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY xyzzy;
+ }} msg]
+ lappend v $msg
+} {0 {0 1 2 3 4 5 5 6 7 8}}
+do_test select4-5.2b {
+ set v [catch {execsql {
+ SELECT DISTINCT log AS xyzzy FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY 'xyzzy';
+ }} msg]
+ lappend v $msg
+} {0 {0 1 2 3 4 5 5 6 7 8}}
+do_test select4-5.2c {
+ set v [catch {execsql {
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY 'xyzzy';
+ }} msg]
+ lappend v $msg
+} {1 {ORDER BY term number 1 does not match any result column}}
+do_test select4-5.2d {
+ set v [catch {execsql {
+ SELECT DISTINCT log FROM t1
+ INTERSECT
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY 'xyzzy';
+ }} msg]
+ lappend v $msg
+} {1 {ORDER BY term number 1 does not match any result column}}
+do_test select4-5.2e {
+ set v [catch {execsql {
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY n;
+ }} msg]
+ lappend v $msg
+} {0 {0 1 2 3 4 5 5 6 7 8}}
+do_test select4-5.2f {
+ catchsql {
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }
+} {0 {0 1 2 3 4 5 5 6 7 8}}
+do_test select4-5.2g {
+ catchsql {
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY 1;
+ }
+} {0 {0 1 2 3 4 5 5 6 7 8}}
+do_test select4-5.2h {
+ catchsql {
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY 2;
+ }
+} {1 {ORDER BY position 2 should be between 1 and 1}}
+do_test select4-5.2i {
+ catchsql {
+ SELECT DISTINCT 1, log FROM t1
+ UNION ALL
+ SELECT 2, n FROM t1 WHERE log=3
+ ORDER BY 2, 1;
+ }
+} {0 {1 0 1 1 1 2 1 3 1 4 1 5 2 5 2 6 2 7 2 8}}
+do_test select4-5.2j {
+ catchsql {
+ SELECT DISTINCT 1, log FROM t1
+ UNION ALL
+ SELECT 2, n FROM t1 WHERE log=3
+ ORDER BY 1, 2 DESC;
+ }
+} {0 {1 5 1 4 1 3 1 2 1 1 1 0 2 8 2 7 2 6 2 5}}
+do_test select4-5.2k {
+ catchsql {
+ SELECT DISTINCT 1, log FROM t1
+ UNION ALL
+ SELECT 2, n FROM t1 WHERE log=3
+ ORDER BY n, 1;
+ }
+} {0 {1 0 1 1 1 2 1 3 1 4 1 5 2 5 2 6 2 7 2 8}}
+do_test select4-5.3 {
+ set v [catch {execsql {
+ SELECT DISTINCT log, n FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }} msg]
+ lappend v $msg
+} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}}
+do_test select4-5.4 {
+ set v [catch {execsql {
+ SELECT log FROM t1 WHERE n=2
+ UNION ALL
+ SELECT log FROM t1 WHERE n=3
+ UNION ALL
+ SELECT log FROM t1 WHERE n=4
+ UNION ALL
+ SELECT log FROM t1 WHERE n=5
+ ORDER BY log;
+ }} msg]
+ lappend v $msg
+} {0 {1 2 2 3}}
+
+do_test select4-6.1 {
+ execsql {
+ SELECT log, count(*) as cnt FROM t1 GROUP BY log
+ UNION
+ SELECT log, n FROM t1 WHERE n=7
+ ORDER BY cnt, log;
+ }
+} {0 1 1 1 2 2 3 4 3 7 4 8 5 15}
+do_test select4-6.2 {
+ execsql {
+ SELECT log, count(*) FROM t1 GROUP BY log
+ UNION
+ SELECT log, n FROM t1 WHERE n=7
+ ORDER BY count(*), log;
+ }
+} {0 1 1 1 2 2 3 4 3 7 4 8 5 15}
+
+# NULLs are indistinct for the UNION operator.
+# Make sure the UNION operator recognizes this
+#
+do_test select4-6.3 {
+ execsql {
+ SELECT NULL UNION SELECT NULL UNION
+ SELECT 1 UNION SELECT 2 AS 'x'
+ ORDER BY x;
+ }
+} {{} 1 2}
+do_test select4-6.3.1 {
+ execsql {
+ SELECT NULL UNION ALL SELECT NULL UNION ALL
+ SELECT 1 UNION ALL SELECT 2 AS 'x'
+ ORDER BY x;
+ }
+} {{} {} 1 2}
+
+# Make sure the DISTINCT keyword treats NULLs as indistinct.
+#
+do_test select4-6.4 {
+ execsql {
+ SELECT * FROM (
+ SELECT NULL, 1 UNION ALL SELECT NULL, 1
+ );
+ }
+} {{} 1 {} 1}
+do_test select4-6.5 {
+ execsql {
+ SELECT DISTINCT * FROM (
+ SELECT NULL, 1 UNION ALL SELECT NULL, 1
+ );
+ }
+} {{} 1}
+do_test select4-6.6 {
+ execsql {
+ SELECT DISTINCT * FROM (
+ SELECT 1,2 UNION ALL SELECT 1,2
+ );
+ }
+} {1 2}
+
+# Test distinctness of NULL in other ways.
+#
+do_test select4-6.7 {
+ execsql {
+ SELECT NULL EXCEPT SELECT NULL
+ }
+} {}
+
+
+# Make sure column names are correct when a compound select appears as
+# an expression in the WHERE clause.
+#
+do_test select4-7.1 {
+ execsql {
+ CREATE TABLE t2 AS SELECT log AS 'x', count(*) AS 'y' FROM t1 GROUP BY log;
+ SELECT * FROM t2 ORDER BY x;
+ }
+} {0 1 1 1 2 2 3 4 4 8 5 15}
+do_test select4-7.2 {
+ execsql2 {
+ SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 INTERSECT SELECT x FROM t2)
+ ORDER BY n
+ }
+} {n 1 log 0 n 2 log 1 n 3 log 2 n 4 log 2 n 5 log 3}
+do_test select4-7.3 {
+ execsql2 {
+ SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 EXCEPT SELECT x FROM t2)
+ ORDER BY n LIMIT 2
+ }
+} {n 6 log 3 n 7 log 3}
+do_test select4-7.4 {
+ execsql2 {
+ SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 UNION SELECT x FROM t2)
+ ORDER BY n LIMIT 2
+ }
+} {n 1 log 0 n 2 log 1}
+
+# Make sure DISTINCT works appropriately on TEXT and NUMERIC columns.
+#
+do_test select4-8.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t3(a text, b float, c text);
+ INSERT INTO t3 VALUES(1, 1.1, '1.1');
+ INSERT INTO t3 VALUES(2, 1.10, '1.10');
+ INSERT INTO t3 VALUES(3, 1.10, '1.1');
+ INSERT INTO t3 VALUES(4, 1.1, '1.10');
+ INSERT INTO t3 VALUES(5, 1.2, '1.2');
+ INSERT INTO t3 VALUES(6, 1.3, '1.3');
+ COMMIT;
+ }
+ execsql {
+ SELECT DISTINCT b FROM t3 ORDER BY c;
+ }
+} {1.1 1.2 1.3}
+do_test select4-8.2 {
+ execsql {
+ SELECT DISTINCT c FROM t3 ORDER BY c;
+ }
+} {1.1 1.10 1.2 1.3}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/select5.test b/usr/src/lib/libsqlite/test/select5.test
new file mode 100644
index 0000000000..7db30d07db
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/select5.test
@@ -0,0 +1,122 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 aggregate functions and the
+# GROUP BY and HAVING clauses of SELECT statements.
+#
+# $Id: select5.test,v 1.6 2001/10/15 00:44:36 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Build some test data
+#
+set fd [open data1.txt w]
+for {set i 1} {$i<32} {incr i} {
+ for {set j 0} {pow(2,$j)<$i} {incr j} {}
+ puts $fd "[expr {32-$i}]\t[expr {10-$j}]"
+}
+close $fd
+execsql {
+ CREATE TABLE t1(x int, y int);
+ COPY t1 FROM 'data1.txt'
+}
+file delete data1.txt
+
+do_test select5-1.0 {
+ execsql {SELECT DISTINCT y FROM t1 ORDER BY y}
+} {5 6 7 8 9 10}
+
+# Sort by an aggregate function.
+#
+do_test select5-1.1 {
+ execsql {SELECT y, count(*) FROM t1 GROUP BY y ORDER BY y}
+} {5 15 6 8 7 4 8 2 9 1 10 1}
+do_test select5-1.2 {
+ execsql {SELECT y, count(*) FROM t1 GROUP BY y ORDER BY count(*), y}
+} {9 1 10 1 8 2 7 4 6 8 5 15}
+do_test select5-1.3 {
+ execsql {SELECT count(*), y FROM t1 GROUP BY y ORDER BY count(*), y}
+} {1 9 1 10 2 8 4 7 8 6 15 5}
+
+# Some error messages associated with aggregates and GROUP BY
+#
+do_test select5-2.1 {
+ set v [catch {execsql {
+ SELECT y, count(*) FROM t1 GROUP BY z ORDER BY y
+ }} msg]
+ lappend v $msg
+} {1 {no such column: z}}
+do_test select5-2.2 {
+ set v [catch {execsql {
+ SELECT y, count(*) FROM t1 GROUP BY z(y) ORDER BY y
+ }} msg]
+ lappend v $msg
+} {1 {no such function: z}}
+do_test select5-2.3 {
+ set v [catch {execsql {
+ SELECT y, count(*) FROM t1 GROUP BY y HAVING count(*)<3 ORDER BY y
+ }} msg]
+ lappend v $msg
+} {0 {8 2 9 1 10 1}}
+do_test select5-2.4 {
+ set v [catch {execsql {
+ SELECT y, count(*) FROM t1 GROUP BY y HAVING z(y)<3 ORDER BY y
+ }} msg]
+ lappend v $msg
+} {1 {no such function: z}}
+do_test select5-2.5 {
+ set v [catch {execsql {
+ SELECT y, count(*) FROM t1 GROUP BY y HAVING count(*)<z ORDER BY y
+ }} msg]
+ lappend v $msg
+} {1 {no such column: z}}
+
+# Get the Agg function to rehash in vdbe.c
+#
+do_test select5-3.1 {
+ execsql {
+ SELECT x, count(*), avg(y) FROM t1 GROUP BY x HAVING x<4 ORDER BY x
+ }
+} {1 1 5 2 1 5 3 1 5}
+
+# Run various aggregate functions when the count is zero.
+#
+do_test select5-4.1 {
+ execsql {
+ SELECT avg(x) FROM t1 WHERE x>100
+ }
+} {{}}
+do_test select5-4.2 {
+ execsql {
+ SELECT count(x) FROM t1 WHERE x>100
+ }
+} {0}
+do_test select5-4.3 {
+ execsql {
+ SELECT min(x) FROM t1 WHERE x>100
+ }
+} {{}}
+do_test select5-4.4 {
+ execsql {
+ SELECT max(x) FROM t1 WHERE x>100
+ }
+} {{}}
+do_test select5-4.5 {
+ execsql {
+ SELECT sum(x) FROM t1 WHERE x>100
+ }
+} {0}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/select6.test b/usr/src/lib/libsqlite/test/select6.test
new file mode 100644
index 0000000000..13ff398e98
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/select6.test
@@ -0,0 +1,438 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 SELECT statements that contain
+# subqueries in their FROM clause.
+#
+# $Id: select6.test,v 1.11 2004/01/24 20:18:13 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test select6-1.0 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t1(x, y);
+ INSERT INTO t1 VALUES(1,1);
+ INSERT INTO t1 VALUES(2,2);
+ INSERT INTO t1 VALUES(3,2);
+ INSERT INTO t1 VALUES(4,3);
+ INSERT INTO t1 VALUES(5,3);
+ INSERT INTO t1 VALUES(6,3);
+ INSERT INTO t1 VALUES(7,3);
+ INSERT INTO t1 VALUES(8,4);
+ INSERT INTO t1 VALUES(9,4);
+ INSERT INTO t1 VALUES(10,4);
+ INSERT INTO t1 VALUES(11,4);
+ INSERT INTO t1 VALUES(12,4);
+ INSERT INTO t1 VALUES(13,4);
+ INSERT INTO t1 VALUES(14,4);
+ INSERT INTO t1 VALUES(15,4);
+ INSERT INTO t1 VALUES(16,5);
+ INSERT INTO t1 VALUES(17,5);
+ INSERT INTO t1 VALUES(18,5);
+ INSERT INTO t1 VALUES(19,5);
+ INSERT INTO t1 VALUES(20,5);
+ COMMIT;
+ SELECT DISTINCT y FROM t1 ORDER BY y;
+ }
+} {1 2 3 4 5}
+
+do_test select6-1.1 {
+ execsql2 {SELECT * FROM (SELECT x, y FROM t1 WHERE x<2)}
+} {x 1 y 1}
+do_test select6-1.2 {
+ execsql {SELECT count(*) FROM (SELECT y FROM t1)}
+} {20}
+do_test select6-1.3 {
+ execsql {SELECT count(*) FROM (SELECT DISTINCT y FROM t1)}
+} {5}
+do_test select6-1.4 {
+ execsql {SELECT count(*) FROM (SELECT DISTINCT * FROM (SELECT y FROM t1))}
+} {5}
+do_test select6-1.5 {
+ execsql {SELECT count(*) FROM (SELECT * FROM (SELECT DISTINCT y FROM t1))}
+} {5}
+
+do_test select6-1.6 {
+ execsql {
+ SELECT *
+ FROM (SELECT count(*),y FROM t1 GROUP BY y) AS a,
+ (SELECT max(x),y FROM t1 GROUP BY y) as b
+ WHERE a.y=b.y ORDER BY a.y
+ }
+} {1 1 1 1 2 2 3 2 4 3 7 3 8 4 15 4 5 5 20 5}
+do_test select6-1.7 {
+ execsql {
+ SELECT a.y, a.[count(*)], [max(x)], [count(*)]
+ FROM (SELECT count(*),y FROM t1 GROUP BY y) AS a,
+ (SELECT max(x),y FROM t1 GROUP BY y) as b
+ WHERE a.y=b.y ORDER BY a.y
+ }
+} {1 1 1 1 2 2 3 2 3 4 7 4 4 8 15 8 5 5 20 5}
+do_test select6-1.8 {
+ execsql {
+ SELECT q, p, r
+ FROM (SELECT count(*) as p , y as q FROM t1 GROUP BY y) AS a,
+ (SELECT max(x) as r, y as s FROM t1 GROUP BY y) as b
+ WHERE q=s ORDER BY s
+ }
+} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
+do_test select6-1.9 {
+ execsql {
+ SELECT q, p, r, b.[min(x)+y]
+ FROM (SELECT count(*) as p , y as q FROM t1 GROUP BY y) AS a,
+ (SELECT max(x) as r, y as s, min(x)+y FROM t1 GROUP BY y) as b
+ WHERE q=s ORDER BY s
+ }
+} {1 1 1 2 2 2 3 4 3 4 7 7 4 8 15 12 5 5 20 21}
+
+do_test select6-2.0 {
+ execsql {
+ CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
+ INSERT INTO t2 SELECT * FROM t1;
+ SELECT DISTINCT b FROM t2 ORDER BY b;
+ }
+} {1 2 3 4 5}
+do_test select6-2.1 {
+ execsql2 {SELECT * FROM (SELECT a, b FROM t2 WHERE a<2)}
+} {a 1 b 1}
+do_test select6-2.2 {
+ execsql {SELECT count(*) FROM (SELECT b FROM t2)}
+} {20}
+do_test select6-2.3 {
+ execsql {SELECT count(*) FROM (SELECT DISTINCT b FROM t2)}
+} {5}
+do_test select6-2.4 {
+ execsql {SELECT count(*) FROM (SELECT DISTINCT * FROM (SELECT b FROM t2))}
+} {5}
+do_test select6-2.5 {
+ execsql {SELECT count(*) FROM (SELECT * FROM (SELECT DISTINCT b FROM t2))}
+} {5}
+
+do_test select6-2.6 {
+ execsql {
+ SELECT *
+ FROM (SELECT count(*),b FROM t2 GROUP BY b) AS a,
+ (SELECT max(a),b FROM t2 GROUP BY b) as b
+ WHERE a.b=b.b ORDER BY a.b
+ }
+} {1 1 1 1 2 2 3 2 4 3 7 3 8 4 15 4 5 5 20 5}
+do_test select6-2.7 {
+ execsql {
+ SELECT a.b, a.[count(*)], [max(a)], [count(*)]
+ FROM (SELECT count(*),b FROM t2 GROUP BY b) AS a,
+ (SELECT max(a),b FROM t2 GROUP BY b) as b
+ WHERE a.b=b.b ORDER BY a.b
+ }
+} {1 1 1 1 2 2 3 2 3 4 7 4 4 8 15 8 5 5 20 5}
+do_test select6-2.8 {
+ execsql {
+ SELECT q, p, r
+ FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY b) AS a,
+ (SELECT max(a) as r, b as s FROM t2 GROUP BY b) as b
+ WHERE q=s ORDER BY s
+ }
+} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
+do_test select6-2.9 {
+ execsql {
+ SELECT a.q, a.p, b.r
+ FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a,
+ (SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b
+ WHERE a.q=b.s ORDER BY a.q
+ }
+} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
+
+do_test sqlite6-3.1 {
+ execsql2 {
+ SELECT * FROM (SELECT * FROM (SELECT * FROM t1 WHERE x=3));
+ }
+} {x 3 y 2}
+do_test sqlite6-3.2 {
+ execsql {
+ SELECT * FROM
+ (SELECT a.q, a.p, b.r
+ FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a,
+ (SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b
+ WHERE a.q=b.s ORDER BY a.q)
+ ORDER BY q
+ }
+} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
+do_test select6-3.3 {
+ execsql {
+ SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1)
+ }
+} {10.5 3.7 14.2}
+do_test select6-3.4 {
+ execsql {
+ SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4)
+ }
+} {11.5 4 15.5}
+do_test select6-3.5 {
+ execsql {
+ SELECT x,y,x+y FROM (SELECT avg(a) as 'x', avg(b) as 'y' FROM t2 WHERE a=4)
+ }
+} {4 3 7}
+do_test select6-3.6 {
+ execsql {
+ SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1)
+ WHERE a>10
+ }
+} {10.5 3.7 14.2}
+do_test select6-3.7 {
+ execsql {
+ SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1)
+ WHERE a<10
+ }
+} {}
+do_test select6-3.8 {
+ execsql {
+ SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4)
+ WHERE a>10
+ }
+} {11.5 4 15.5}
+do_test select6-3.9 {
+ execsql {
+ SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4)
+ WHERE a<10
+ }
+} {}
+do_test select6-3.10 {
+ execsql {
+ SELECT a,b,a+b FROM (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b)
+ ORDER BY a
+ }
+} {1 1 2 2.5 2 4.5 5.5 3 8.5 11.5 4 15.5 18 5 23}
+do_test select6-3.11 {
+ execsql {
+ SELECT a,b,a+b FROM
+ (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b)
+ WHERE b<4 ORDER BY a
+ }
+} {1 1 2 2.5 2 4.5 5.5 3 8.5}
+do_test select6-3.12 {
+ execsql {
+ SELECT a,b,a+b FROM
+ (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b HAVING a>1)
+ WHERE b<4 ORDER BY a
+ }
+} {2.5 2 4.5 5.5 3 8.5}
+do_test select6-3.13 {
+ execsql {
+ SELECT a,b,a+b FROM
+ (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b HAVING a>1)
+ ORDER BY a
+ }
+} {2.5 2 4.5 5.5 3 8.5 11.5 4 15.5 18 5 23}
+do_test select6-3.14 {
+ execsql {
+ SELECT [count(*)],y FROM (SELECT count(*), y FROM t1 GROUP BY y)
+ ORDER BY [count(*)]
+ }
+} {1 1 2 2 4 3 5 5 8 4}
+do_test select6-3.15 {
+ execsql {
+ SELECT [count(*)],y FROM (SELECT count(*), y FROM t1 GROUP BY y)
+ ORDER BY y
+ }
+} {1 1 2 2 4 3 8 4 5 5}
+
+do_test select6-4.1 {
+ execsql {
+ SELECT a,b,c FROM
+ (SELECT x AS 'a', y AS 'b', x+y AS 'c' FROM t1 WHERE y=4)
+ WHERE a<10 ORDER BY a;
+ }
+} {8 4 12 9 4 13}
+do_test select6-4.2 {
+ execsql {
+ SELECT y FROM (SELECT DISTINCT y FROM t1) WHERE y<5 ORDER BY y
+ }
+} {1 2 3 4}
+do_test select6-4.3 {
+ execsql {
+ SELECT DISTINCT y FROM (SELECT y FROM t1) WHERE y<5 ORDER BY y
+ }
+} {1 2 3 4}
+do_test select6-4.4 {
+ execsql {
+ SELECT avg(y) FROM (SELECT DISTINCT y FROM t1) WHERE y<5 ORDER BY y
+ }
+} {2.5}
+do_test select6-4.5 {
+ execsql {
+ SELECT avg(y) FROM (SELECT DISTINCT y FROM t1 WHERE y<5) ORDER BY y
+ }
+} {2.5}
+
+do_test select6-5.1 {
+ execsql {
+ SELECT a,x,b FROM
+ (SELECT x+3 AS 'a', x FROM t1 WHERE y=3) AS 'p',
+ (SELECT x AS 'b' FROM t1 WHERE y=4) AS 'q'
+ WHERE a=b
+ ORDER BY a
+ }
+} {8 5 8 9 6 9 10 7 10}
+do_test select6-5.2 {
+ execsql {
+ SELECT a,x,b FROM
+ (SELECT x+3 AS 'a', x FROM t1 WHERE y=3),
+ (SELECT x AS 'b' FROM t1 WHERE y=4)
+ WHERE a=b
+ ORDER BY a
+ }
+} {8 5 8 9 6 9 10 7 10}
+
+# Tests of compound sub-selects
+#
+do_test select5-6.1 {
+ execsql {
+ DELETE FROM t1 WHERE x>4;
+ SELECT * FROM t1
+ }
+} {1 1 2 2 3 2 4 3}
+do_test select6-6.2 {
+ execsql {
+ SELECT * FROM (
+ SELECT x AS 'a' FROM t1 UNION ALL SELECT x+10 AS 'a' FROM t1
+ ) ORDER BY a;
+ }
+} {1 2 3 4 11 12 13 14}
+do_test select6-6.3 {
+ execsql {
+ SELECT * FROM (
+ SELECT x AS 'a' FROM t1 UNION ALL SELECT x+1 AS 'a' FROM t1
+ ) ORDER BY a;
+ }
+} {1 2 2 3 3 4 4 5}
+do_test select6-6.4 {
+ execsql {
+ SELECT * FROM (
+ SELECT x AS 'a' FROM t1 UNION SELECT x+1 AS 'a' FROM t1
+ ) ORDER BY a;
+ }
+} {1 2 3 4 5}
+do_test select6-6.5 {
+ execsql {
+ SELECT * FROM (
+ SELECT x AS 'a' FROM t1 INTERSECT SELECT x+1 AS 'a' FROM t1
+ ) ORDER BY a;
+ }
+} {2 3 4}
+do_test select6-6.6 {
+ execsql {
+ SELECT * FROM (
+ SELECT x AS 'a' FROM t1 EXCEPT SELECT x*2 AS 'a' FROM t1
+ ) ORDER BY a;
+ }
+} {1 3}
+
+# Subselects with no FROM clause
+#
+do_test select6-7.1 {
+ execsql {
+ SELECT * FROM (SELECT 1)
+ }
+} {1}
+do_test select6-7.2 {
+ execsql {
+ SELECT c,b,a,* FROM (SELECT 1 AS 'a', 2 AS 'b', 'abc' AS 'c')
+ }
+} {abc 2 1 1 2 abc}
+do_test select6-7.3 {
+ execsql {
+ SELECT c,b,a,* FROM (SELECT 1 AS 'a', 2 AS 'b', 'abc' AS 'c' WHERE 0)
+ }
+} {}
+do_test select6-7.4 {
+ execsql2 {
+ SELECT c,b,a,* FROM (SELECT 1 AS 'a', 2 AS 'b', 'abc' AS 'c' WHERE 1)
+ }
+} {c abc b 2 a 1 a 1 b 2 c abc}
+
+# The following procedure compiles the SQL given as an argument and returns
+# TRUE if that SQL uses any transient tables and returns FALSE if no
+# transient tables are used. This is used to make sure that the
+# sqliteFlattenSubquery() routine in select.c is doing its job.
+#
+proc is_flat {sql} {
+ return [expr 0>[lsearch [execsql "EXPLAIN $sql"] OpenTemp]]
+}
+
+# Check that the flattener works correctly for deeply nested subqueries
+# involving joins.
+#
+do_test select6-8.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t3(p,q);
+ INSERT INTO t3 VALUES(1,11);
+ INSERT INTO t3 VALUES(2,22);
+ CREATE TABLE t4(q,r);
+ INSERT INTO t4 VALUES(11,111);
+ INSERT INTO t4 VALUES(22,222);
+ COMMIT;
+ SELECT * FROM t3 NATURAL JOIN t4;
+ }
+} {1 11 111 2 22 222}
+do_test select6-8.2 {
+ execsql {
+ SELECT y, p, q, r FROM
+ (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m,
+ (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n
+ WHERE y=p
+ }
+} {1 1 11 111 2 2 22 222 2 2 22 222}
+do_test select6-8.3 {
+ is_flat {
+ SELECT y, p, q, r FROM
+ (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m,
+ (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n
+ WHERE y=p
+ }
+} {1}
+do_test select6-8.4 {
+ execsql {
+ SELECT DISTINCT y, p, q, r FROM
+ (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m,
+ (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n
+ WHERE y=p
+ }
+} {1 1 11 111 2 2 22 222}
+do_test select6-8.5 {
+ execsql {
+ SELECT * FROM
+ (SELECT y, p, q, r FROM
+ (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m,
+ (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n
+ WHERE y=p) AS e,
+ (SELECT r AS z FROM t4 WHERE q=11) AS f
+ WHERE e.r=f.z
+ }
+} {1 1 11 111 111}
+do_test select6-8.6 {
+ is_flat {
+ SELECT * FROM
+ (SELECT y, p, q, r FROM
+ (SELECT t1.y AS y, t2.b AS b FROM t1, t2 WHERE t1.x=t2.a) AS m,
+ (SELECT t3.p AS p, t3.q AS q, t4.r AS r FROM t3 NATURAL JOIN t4) as n
+ WHERE y=p) AS e,
+ (SELECT r AS z FROM t4 WHERE q=11) AS f
+ WHERE e.r=f.z
+ }
+} {1}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/sort.test b/usr/src/lib/libsqlite/test/sort.test
new file mode 100644
index 0000000000..337b15d609
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/sort.test
@@ -0,0 +1,364 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 CREATE TABLE statement.
+#
+# $Id: sort.test,v 1.9 2003/04/18 17:45:15 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a bunch of data to sort against
+#
+do_test sort-1.0 {
+ set fd [open data.txt w]
+ puts $fd "1\tone\t0\tI\t3.141592653"
+ puts $fd "2\ttwo\t1\tII\t2.15"
+ puts $fd "3\tthree\t1\tIII\t4221.0"
+ puts $fd "4\tfour\t2\tIV\t-0.0013442"
+ puts $fd "5\tfive\t2\tV\t-11"
+ puts $fd "6\tsix\t2\tVI\t0.123"
+ puts $fd "7\tseven\t2\tVII\t123.0"
+ puts $fd "8\teight\t3\tVIII\t-1.6"
+ close $fd
+ execsql {
+ CREATE TABLE t1(
+ n int,
+ v varchar(10),
+ log int,
+ roman varchar(10),
+ flt real
+ );
+ COPY t1 FROM 'data.txt'
+ }
+ file delete data.txt
+ execsql {SELECT count(*) FROM t1}
+} {8}
+
+do_test sort-1.1 {
+ execsql {SELECT n FROM t1 ORDER BY n}
+} {1 2 3 4 5 6 7 8}
+do_test sort-1.1.1 {
+ execsql {SELECT n FROM t1 ORDER BY n ASC}
+} {1 2 3 4 5 6 7 8}
+do_test sort-1.1.1 {
+ execsql {SELECT ALL n FROM t1 ORDER BY n ASC}
+} {1 2 3 4 5 6 7 8}
+do_test sort-1.2 {
+ execsql {SELECT n FROM t1 ORDER BY n DESC}
+} {8 7 6 5 4 3 2 1}
+do_test sort-1.3a {
+ execsql {SELECT v FROM t1 ORDER BY v}
+} {eight five four one seven six three two}
+do_test sort-1.3b {
+ execsql {SELECT n FROM t1 ORDER BY v}
+} {8 5 4 1 7 6 3 2}
+do_test sort-1.4 {
+ execsql {SELECT n FROM t1 ORDER BY v DESC}
+} {2 3 6 7 1 4 5 8}
+do_test sort-1.5 {
+ execsql {SELECT flt FROM t1 ORDER BY flt}
+} {-11 -1.6 -0.0013442 0.123 2.15 3.141592653 123.0 4221.0}
+do_test sort-1.6 {
+ execsql {SELECT flt FROM t1 ORDER BY flt DESC}
+} {4221.0 123.0 3.141592653 2.15 0.123 -0.0013442 -1.6 -11}
+do_test sort-1.7 {
+ execsql {SELECT roman FROM t1 ORDER BY roman}
+} {I II III IV V VI VII VIII}
+do_test sort-1.8 {
+ execsql {SELECT n FROM t1 ORDER BY log, flt}
+} {1 2 3 5 4 6 7 8}
+do_test sort-1.8.1 {
+ execsql {SELECT n FROM t1 ORDER BY log asc, flt}
+} {1 2 3 5 4 6 7 8}
+do_test sort-1.8.2 {
+ execsql {SELECT n FROM t1 ORDER BY log, flt ASC}
+} {1 2 3 5 4 6 7 8}
+do_test sort-1.8.3 {
+ execsql {SELECT n FROM t1 ORDER BY log ASC, flt asc}
+} {1 2 3 5 4 6 7 8}
+do_test sort-1.9 {
+ execsql {SELECT n FROM t1 ORDER BY log, flt DESC}
+} {1 3 2 7 6 4 5 8}
+do_test sort-1.9.1 {
+ execsql {SELECT n FROM t1 ORDER BY log ASC, flt DESC}
+} {1 3 2 7 6 4 5 8}
+do_test sort-1.10 {
+ execsql {SELECT n FROM t1 ORDER BY log DESC, flt}
+} {8 5 4 6 7 2 3 1}
+do_test sort-1.11 {
+ execsql {SELECT n FROM t1 ORDER BY log DESC, flt DESC}
+} {8 7 6 4 5 3 2 1}
+
+# These tests are designed to reach some hard-to-reach places
+# inside the string comparison routines.
+#
+# (Later) The sorting behavior changed in 2.7.0. But we will
+# keep these tests. You can never have too many test cases!
+#
+do_test sort-2.1.1 {
+ execsql {
+ UPDATE t1 SET v='x' || -flt;
+ UPDATE t1 SET v='x-2b' where v=='x-0.123';
+ SELECT v FROM t1 ORDER BY v;
+ }
+} {x-123 x-2.15 x-2b x-3.141592653 x-4221 x0.0013442 x1.6 x11}
+do_test sort-2.1.2 {
+ execsql {
+ SELECT v FROM t1 ORDER BY substr(v,2,999);
+ }
+} {x-123 x-2.15 x-2b x-3.141592653 x-4221 x0.0013442 x1.6 x11}
+do_test sort-2.1.3 {
+ execsql {
+ SELECT v FROM t1 ORDER BY substr(v,2,999)+0.0;
+ }
+} {x-4221 x-123 x-3.141592653 x-2.15 x-2b x0.0013442 x1.6 x11}
+do_test sort-2.1.4 {
+ execsql {
+ SELECT v FROM t1 ORDER BY substr(v,2,999) DESC;
+ }
+} {x11 x1.6 x0.0013442 x-4221 x-3.141592653 x-2b x-2.15 x-123}
+do_test sort-2.1.5 {
+ execsql {
+ SELECT v FROM t1 ORDER BY substr(v,2,999)+0.0 DESC;
+ }
+} {x11 x1.6 x0.0013442 x-2b x-2.15 x-3.141592653 x-123 x-4221}
+
+# This is a bug fix for 2.2.4.
+# Strings are normally mapped to upper-case for a caseless comparison.
+# But this can cause problems for characters in between 'Z' and 'a'.
+#
+do_test sort-3.1 {
+ execsql {
+ CREATE TABLE t2(a,b);
+ INSERT INTO t2 VALUES('AGLIENTU',1);
+ INSERT INTO t2 VALUES('AGLIE`',2);
+ INSERT INTO t2 VALUES('AGNA',3);
+ SELECT a, b FROM t2 ORDER BY a;
+ }
+} {AGLIENTU 1 AGLIE` 2 AGNA 3}
+do_test sort-3.2 {
+ execsql {
+ SELECT a, b FROM t2 ORDER BY a DESC;
+ }
+} {AGNA 3 AGLIE` 2 AGLIENTU 1}
+do_test sort-3.3 {
+ execsql {
+ DELETE FROM t2;
+ INSERT INTO t2 VALUES('aglientu',1);
+ INSERT INTO t2 VALUES('aglie`',2);
+ INSERT INTO t2 VALUES('agna',3);
+ SELECT a, b FROM t2 ORDER BY a;
+ }
+} {aglie` 2 aglientu 1 agna 3}
+do_test sort-3.4 {
+ execsql {
+ SELECT a, b FROM t2 ORDER BY a DESC;
+ }
+} {agna 3 aglientu 1 aglie` 2}
+
+# Version 2.7.0 testing.
+#
+do_test sort-4.1 {
+ execsql {
+ INSERT INTO t1 VALUES(9,'x2.7',3,'IX',4.0e5);
+ INSERT INTO t1 VALUES(10,'x5.0e10',3,'X',-4.0e5);
+ INSERT INTO t1 VALUES(11,'x-4.0e9',3,'XI',4.1e4);
+ INSERT INTO t1 VALUES(12,'x01234567890123456789',3,'XII',-4.2e3);
+ SELECT n FROM t1 ORDER BY n;
+ }
+} {1 2 3 4 5 6 7 8 9 10 11 12}
+do_test sort-4.2 {
+ execsql {
+ SELECT n||'' FROM t1 ORDER BY 1;
+ }
+} {1 10 11 12 2 3 4 5 6 7 8 9}
+do_test sort-4.3 {
+ execsql {
+ SELECT n+0 FROM t1 ORDER BY 1;
+ }
+} {1 2 3 4 5 6 7 8 9 10 11 12}
+do_test sort-4.4 {
+ execsql {
+ SELECT n||'' FROM t1 ORDER BY 1 DESC;
+ }
+} {9 8 7 6 5 4 3 2 12 11 10 1}
+do_test sort-4.5 {
+ execsql {
+ SELECT n+0 FROM t1 ORDER BY 1 DESC;
+ }
+} {12 11 10 9 8 7 6 5 4 3 2 1}
+do_test sort-4.6 {
+ execsql {
+ SELECT v FROM t1 ORDER BY 1;
+ }
+} {x-123 x-2.15 x-2b x-3.141592653 x-4.0e9 x-4221 x0.0013442 x01234567890123456789 x1.6 x11 x2.7 x5.0e10}
+do_test sort-4.7 {
+ execsql {
+ SELECT v FROM t1 ORDER BY 1 DESC;
+ }
+} {x5.0e10 x2.7 x11 x1.6 x01234567890123456789 x0.0013442 x-4221 x-4.0e9 x-3.141592653 x-2b x-2.15 x-123}
+do_test sort-4.8 {
+ execsql {
+ SELECT substr(v,2,99) FROM t1 ORDER BY 1;
+ }
+} {-123 -2.15 -2b -3.141592653 -4.0e9 -4221 0.0013442 01234567890123456789 1.6 11 2.7 5.0e10}
+#do_test sort-4.9 {
+# execsql {
+# SELECT substr(v,2,99)+0.0 FROM t1 ORDER BY 1;
+# }
+#} {-4000000000 -4221 -123 -3.141592653 -2.15 -2 0.0013442 1.6 2.7 11 50000000000 1.23456789012346e+18}
+
+do_test sort-5.1 {
+ execsql {
+ create table t3(a,b);
+ insert into t3 values(5,NULL);
+ insert into t3 values(6,NULL);
+ insert into t3 values(3,NULL);
+ insert into t3 values(4,'cd');
+ insert into t3 values(1,'ab');
+ insert into t3 values(2,NULL);
+ select a from t3 order by b, a;
+ }
+} {2 3 5 6 1 4}
+do_test sort-5.2 {
+ execsql {
+ select a from t3 order by b, a desc;
+ }
+} {6 5 3 2 1 4}
+do_test sort-5.3 {
+ execsql {
+ select a from t3 order by b desc, a;
+ }
+} {4 1 2 3 5 6}
+do_test sort-5.4 {
+ execsql {
+ select a from t3 order by b desc, a desc;
+ }
+} {4 1 6 5 3 2}
+
+do_test sort-6.1 {
+ execsql {
+ create index i3 on t3(b,a);
+ select a from t3 order by b, a;
+ }
+} {2 3 5 6 1 4}
+do_test sort-6.2 {
+ execsql {
+ select a from t3 order by b, a desc;
+ }
+} {6 5 3 2 1 4}
+do_test sort-6.3 {
+ execsql {
+ select a from t3 order by b desc, a;
+ }
+} {4 1 2 3 5 6}
+do_test sort-6.4 {
+ execsql {
+ select a from t3 order by b desc, a desc;
+ }
+} {4 1 6 5 3 2}
+
+do_test sort-7.1 {
+ execsql {
+ CREATE TABLE t4(
+ a INTEGER,
+ b VARCHAR(30)
+ );
+ INSERT INTO t4 VALUES(1,1);
+ INSERT INTO t4 VALUES(2,2);
+ INSERT INTO t4 VALUES(11,11);
+ INSERT INTO t4 VALUES(12,12);
+ SELECT a FROM t4 ORDER BY 1;
+ }
+} {1 2 11 12}
+do_test sort-7.2 {
+ execsql {
+ SELECT b FROM t4 ORDER BY 1
+ }
+} {1 11 12 2}
+do_test sort-7.3 {
+ execsql {
+ CREATE VIEW v4 AS SELECT * FROM t4;
+ SELECT a FROM v4 ORDER BY 1;
+ }
+} {1 2 11 12}
+do_test sort-7.4 {
+ execsql {
+ SELECT b FROM v4 ORDER BY 1;
+ }
+} {1 11 12 2}
+do_test sort-7.5 {
+ execsql {
+ SELECT a FROM t4 UNION SELECT a FROM v4 ORDER BY 1;
+ }
+} {1 2 11 12}
+do_test sort-7.6 {
+ execsql {
+ SELECT b FROM t4 UNION SELECT a FROM v4 ORDER BY 1;
+ }
+} {1 2 11 12}
+do_test sort-7.7 {
+ execsql {
+ SELECT a FROM t4 UNION SELECT b FROM v4 ORDER BY 1;
+ }
+} {1 2 11 12}
+do_test sort-7.8 {
+ execsql {
+ SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1;
+ }
+} {1 11 12 2}
+do_test sort-7.9 {
+ execsql {
+ SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE numeric;
+ }
+} {1 2 11 12}
+do_test sort-7.10 {
+ execsql {
+ SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE integer;
+ }
+} {1 2 11 12}
+do_test sort-7.11 {
+ execsql {
+ SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE text;
+ }
+} {1 11 12 2}
+do_test sort-7.12 {
+ execsql {
+ SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE blob;
+ }
+} {1 11 12 2}
+do_test sort-7.13 {
+ execsql {
+ SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE clob;
+ }
+} {1 11 12 2}
+do_test sort-7.14 {
+ execsql {
+ SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE varchar;
+ }
+} {1 11 12 2}
+
+# Ticket #297
+#
+do_test sort-8.1 {
+ execsql {
+ CREATE TABLE t5(a real, b text);
+ INSERT INTO t5 VALUES(100,'A1');
+ INSERT INTO t5 VALUES(100.0,'A2');
+ SELECT * FROM t5 ORDER BY a, b;
+ }
+} {100 A1 100.0 A2}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/subselect.test b/usr/src/lib/libsqlite/test/subselect.test
new file mode 100644
index 0000000000..85b3911935
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/subselect.test
@@ -0,0 +1,158 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 SELECT statements that are part of
+# expressions.
+#
+# $Id: subselect.test,v 1.7 2002/07/15 18:55:26 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Basic sanity checking. Try a simple subselect.
+#
+do_test subselect-1.1 {
+ execsql {
+ CREATE TABLE t1(a int, b int);
+ INSERT INTO t1 VALUES(1,2);
+ INSERT INTO t1 VALUES(3,4);
+ INSERT INTO t1 VALUES(5,6);
+ }
+ execsql {SELECT * FROM t1 WHERE a = (SELECT count(*) FROM t1)}
+} {3 4}
+
+# Try a select with more than one result column.
+#
+do_test subselect-1.2 {
+ set v [catch {execsql {SELECT * FROM t1 WHERE a = (SELECT * FROM t1)}} msg]
+ lappend v $msg
+} {1 {only a single result allowed for a SELECT that is part of an expression}}
+
+# A subselect without an aggregate.
+#
+do_test subselect-1.3a {
+ execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=2)}
+} {2}
+do_test subselect-1.3b {
+ execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=4)}
+} {4}
+do_test subselect-1.3c {
+ execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=6)}
+} {6}
+do_test subselect-1.3c {
+ execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=8)}
+} {}
+
+# What if the subselect doesn't return any value. We should get
+# NULL as the result. Check it out.
+#
+do_test subselect-1.4 {
+ execsql {SELECT b from t1 where a = coalesce((SELECT a FROM t1 WHERE b=5),1)}
+} {2}
+
+# Try multiple subselects within a single expression.
+#
+do_test subselect-1.5 {
+ execsql {
+ CREATE TABLE t2(x int, y int);
+ INSERT INTO t2 VALUES(1,2);
+ INSERT INTO t2 VALUES(2,4);
+ INSERT INTO t2 VALUES(3,8);
+ INSERT INTO t2 VALUES(4,16);
+ }
+ execsql {
+ SELECT y from t2
+ WHERE x = (SELECT sum(b) FROM t1 where a notnull) - (SELECT sum(a) FROM t1)
+ }
+} {8}
+
+# Try something useful. Delete every entry from t2 where the
+# x value is less than half of the maximum.
+#
+do_test subselect-1.6 {
+ execsql {DELETE FROM t2 WHERE x < 0.5*(SELECT max(x) FROM t2)}
+ execsql {SELECT x FROM t2 ORDER BY x}
+} {2 3 4}
+
+# Make sure sorting works for SELECTs there used as a scalar expression.
+#
+do_test subselect-2.1 {
+ execsql {
+ SELECT (SELECT a FROM t1 ORDER BY a), (SELECT a FROM t1 ORDER BY a DESC)
+ }
+} {1 5}
+do_test subselect-2.2 {
+ execsql {
+ SELECT 1 IN (SELECT a FROM t1 ORDER BY a);
+ }
+} {1}
+do_test subselect-2.3 {
+ execsql {
+ SELECT 2 IN (SELECT a FROM t1 ORDER BY a DESC);
+ }
+} {0}
+
+# Verify that the ORDER BY clause is honored in a subquery.
+#
+do_test subselect-3.1 {
+ execsql {
+ CREATE TABLE t3(x int);
+ INSERT INTO t3 SELECT a FROM t1 UNION ALL SELECT b FROM t1;
+ SELECT * FROM t3 ORDER BY x;
+ }
+} {1 2 3 4 5 6}
+do_test subselect-3.2 {
+ execsql {
+ SELECT sum(x) FROM (SELECT x FROM t3 ORDER BY x LIMIT 2);
+ }
+} {3}
+do_test subselect-3.3 {
+ execsql {
+ SELECT sum(x) FROM (SELECT x FROM t3 ORDER BY x DESC LIMIT 2);
+ }
+} {11}
+do_test subselect-3.4 {
+ execsql {
+ SELECT (SELECT x FROM t3 ORDER BY x);
+ }
+} {1}
+do_test subselect-3.5 {
+ execsql {
+ SELECT (SELECT x FROM t3 ORDER BY x DESC);
+ }
+} {6}
+do_test subselect-3.6 {
+ execsql {
+ SELECT (SELECT x FROM t3 ORDER BY x LIMIT 1);
+ }
+} {1}
+do_test subselect-3.7 {
+ execsql {
+ SELECT (SELECT x FROM t3 ORDER BY x DESC LIMIT 1);
+ }
+} {6}
+do_test subselect-3.8 {
+ execsql {
+ SELECT (SELECT x FROM t3 ORDER BY x LIMIT 1 OFFSET 2);
+ }
+} {3}
+do_test subselect-3.9 {
+ execsql {
+ SELECT (SELECT x FROM t3 ORDER BY x DESC LIMIT 1 OFFSET 2);
+ }
+} {4}
+
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/table.test b/usr/src/lib/libsqlite/test/table.test
new file mode 100644
index 0000000000..f04b2a5bad
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/table.test
@@ -0,0 +1,506 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 CREATE TABLE statement.
+#
+# $Id: table.test,v 1.22 2003/01/29 18:46:54 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create a basic table and verify it is added to sqlite_master
+#
+do_test table-1.1 {
+ execsql {
+ CREATE TABLE test1 (
+ one varchar(10),
+ two text
+ )
+ }
+ execsql {
+ SELECT sql FROM sqlite_master WHERE type!='meta'
+ }
+} {{CREATE TABLE test1 (
+ one varchar(10),
+ two text
+ )}}
+
+
+# Verify the other fields of the sqlite_master file.
+#
+do_test table-1.3 {
+ execsql {SELECT name, tbl_name, type FROM sqlite_master WHERE type!='meta'}
+} {test1 test1 table}
+
+# Close and reopen the database. Verify that everything is
+# still the same.
+#
+do_test table-1.4 {
+ db close
+ sqlite db test.db
+ execsql {SELECT name, tbl_name, type from sqlite_master WHERE type!='meta'}
+} {test1 test1 table}
+
+# Drop the database and make sure it disappears.
+#
+do_test table-1.5 {
+ execsql {DROP TABLE test1}
+ execsql {SELECT * FROM sqlite_master WHERE type!='meta'}
+} {}
+
+# Close and reopen the database. Verify that the table is
+# still gone.
+#
+do_test table-1.6 {
+ db close
+ sqlite db test.db
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
+} {}
+
+# Repeat the above steps, but this time quote the table name.
+#
+do_test table-1.10 {
+ execsql {CREATE TABLE "create" (f1 int)}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
+} {create}
+do_test table-1.11 {
+ execsql {DROP TABLE "create"}
+ execsql {SELECT name FROM "sqlite_master" WHERE type!='meta'}
+} {}
+do_test table-1.12 {
+ execsql {CREATE TABLE test1("f1 ho" int)}
+ execsql {SELECT name as "X" FROM sqlite_master WHERE type!='meta'}
+} {test1}
+do_test table-1.13 {
+ execsql {DROP TABLE "TEST1"}
+ execsql {SELECT name FROM "sqlite_master" WHERE type!='meta'}
+} {}
+
+
+
+# Verify that we cannot make two tables with the same name
+#
+do_test table-2.1 {
+ execsql {CREATE TABLE TEST2(one text)}
+ set v [catch {execsql {CREATE TABLE test2(two text)}} msg]
+ lappend v $msg
+} {1 {table test2 already exists}}
+do_test table-2.1b {
+ set v [catch {execsql {CREATE TABLE sqlite_master(two text)}} msg]
+ lappend v $msg
+} {1 {table sqlite_master already exists}}
+do_test table-2.1c {
+ db close
+ sqlite db test.db
+ set v [catch {execsql {CREATE TABLE sqlite_master(two text)}} msg]
+ lappend v $msg
+} {1 {table sqlite_master already exists}}
+do_test table-2.1d {
+ execsql {DROP TABLE test2; SELECT name FROM sqlite_master WHERE type!='meta'}
+} {}
+
+# Verify that we cannot make a table with the same name as an index
+#
+do_test table-2.2a {
+ execsql {CREATE TABLE test2(one text); CREATE INDEX test3 ON test2(one)}
+ set v [catch {execsql {CREATE TABLE test3(two text)}} msg]
+ lappend v $msg
+} {1 {there is already an index named test3}}
+do_test table-2.2b {
+ db close
+ sqlite db test.db
+ set v [catch {execsql {CREATE TABLE test3(two text)}} msg]
+ lappend v $msg
+} {1 {there is already an index named test3}}
+do_test table-2.2c {
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {test2 test3}
+do_test table-2.2d {
+ execsql {DROP INDEX test3}
+ set v [catch {execsql {CREATE TABLE test3(two text)}} msg]
+ lappend v $msg
+} {0 {}}
+do_test table-2.2e {
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {test2 test3}
+do_test table-2.2f {
+ execsql {DROP TABLE test2; DROP TABLE test3}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {}
+
+# Create a table with many field names
+#
+set big_table \
+{CREATE TABLE big(
+ f1 varchar(20),
+ f2 char(10),
+ f3 varchar(30) primary key,
+ f4 text,
+ f5 text,
+ f6 text,
+ f7 text,
+ f8 text,
+ f9 text,
+ f10 text,
+ f11 text,
+ f12 text,
+ f13 text,
+ f14 text,
+ f15 text,
+ f16 text,
+ f17 text,
+ f18 text,
+ f19 text,
+ f20 text
+)}
+do_test table-3.1 {
+ execsql $big_table
+ execsql {SELECT sql FROM sqlite_master WHERE type=='table'}
+} \{$big_table\}
+do_test table-3.2 {
+ set v [catch {execsql {CREATE TABLE BIG(xyz foo)}} msg]
+ lappend v $msg
+} {1 {table BIG already exists}}
+do_test table-3.3 {
+ set v [catch {execsql {CREATE TABLE biG(xyz foo)}} msg]
+ lappend v $msg
+} {1 {table biG already exists}}
+do_test table-3.4 {
+ set v [catch {execsql {CREATE TABLE bIg(xyz foo)}} msg]
+ lappend v $msg
+} {1 {table bIg already exists}}
+do_test table-3.5 {
+ db close
+ sqlite db test.db
+ set v [catch {execsql {CREATE TABLE Big(xyz foo)}} msg]
+ lappend v $msg
+} {1 {table Big already exists}}
+do_test table-3.6 {
+ execsql {DROP TABLE big}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
+} {}
+
+# Try creating large numbers of tables
+#
+set r {}
+for {set i 1} {$i<=100} {incr i} {
+ lappend r [format test%03d $i]
+}
+do_test table-4.1 {
+ for {set i 1} {$i<=100} {incr i} {
+ set sql "CREATE TABLE [format test%03d $i] ("
+ for {set k 1} {$k<$i} {incr k} {
+ append sql "field$k text,"
+ }
+ append sql "last_field text)"
+ execsql $sql
+ }
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} $r
+do_test table-4.1b {
+ db close
+ sqlite db test.db
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} $r
+
+# Drop the even numbered tables
+#
+set r {}
+for {set i 1} {$i<=100} {incr i 2} {
+ lappend r [format test%03d $i]
+}
+do_test table-4.2 {
+ for {set i 2} {$i<=100} {incr i 2} {
+ # if {$i==38} {execsql {pragma vdbe_trace=on}}
+ set sql "DROP TABLE [format TEST%03d $i]"
+ execsql $sql
+ }
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} $r
+#exit
+
+# Drop the odd number tables
+#
+do_test table-4.3 {
+ for {set i 1} {$i<=100} {incr i 2} {
+ set sql "DROP TABLE [format test%03d $i]"
+ execsql $sql
+ }
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
+} {}
+
+# Try to drop a table that does not exist
+#
+do_test table-5.1 {
+ set v [catch {execsql {DROP TABLE test009}} msg]
+ lappend v $msg
+} {1 {no such table: test009}}
+
+# Try to drop sqlite_master
+#
+do_test table-5.2 {
+ set v [catch {execsql {DROP TABLE sqlite_master}} msg]
+ lappend v $msg
+} {1 {table sqlite_master may not be dropped}}
+
+# Make sure an EXPLAIN does not really create a new table
+#
+do_test table-5.3 {
+ execsql {EXPLAIN CREATE TABLE test1(f1 int)}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
+} {}
+
+# Make sure an EXPLAIN does not really drop an existing table
+#
+do_test table-5.4 {
+ execsql {CREATE TABLE test1(f1 int)}
+ execsql {EXPLAIN DROP TABLE test1}
+ execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
+} {test1}
+
+# Create a table with a goofy name
+#
+#do_test table-6.1 {
+# execsql {CREATE TABLE 'Spaces In This Name!'(x int)}
+# execsql {INSERT INTO 'spaces in this name!' VALUES(1)}
+# set list [glob -nocomplain testdb/spaces*.tbl]
+#} {testdb/spaces+in+this+name+.tbl}
+
+# Try using keywords as table names or column names.
+#
+do_test table-7.1 {
+ set v [catch {execsql {
+ CREATE TABLE weird(
+ desc text,
+ asc text,
+ explain int,
+ [14_vac] boolean,
+ fuzzy_dog_12 varchar(10),
+ begin blob,
+ end clob
+ )
+ }} msg]
+ lappend v $msg
+} {0 {}}
+do_test table-7.2 {
+ execsql {
+ INSERT INTO weird VALUES('a','b',9,0,'xyz','hi','y''all');
+ SELECT * FROM weird;
+ }
+} {a b 9 0 xyz hi y'all}
+do_test table-7.3 {
+ execsql2 {
+ SELECT * FROM weird;
+ }
+} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
+
+# Try out the CREATE TABLE AS syntax
+#
+do_test table-8.1 {
+ execsql2 {
+ CREATE TABLE t2 AS SELECT * FROM weird;
+ SELECT * FROM t2;
+ }
+} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
+do_test table-8.1.1 {
+ execsql {
+ SELECT sql FROM sqlite_master WHERE name='t2';
+ }
+} {{CREATE TABLE t2(
+ 'desc',
+ 'asc',
+ 'explain',
+ '14_vac',
+ fuzzy_dog_12,
+ 'begin',
+ 'end'
+)}}
+do_test table-8.2 {
+ execsql {
+ CREATE TABLE 't3''xyz'(a,b,c);
+ INSERT INTO [t3'xyz] VALUES(1,2,3);
+ SELECT * FROM [t3'xyz];
+ }
+} {1 2 3}
+do_test table-8.3 {
+ execsql2 {
+ CREATE TABLE [t4'abc] AS SELECT count(*) as cnt, max(b+c) FROM [t3'xyz];
+ SELECT * FROM [t4'abc];
+ }
+} {cnt 1 max(b+c) 5}
+do_test table-8.3.1 {
+ execsql {
+ SELECT sql FROM sqlite_master WHERE name='t4''abc'
+ }
+} {{CREATE TABLE 't4''abc'(cnt,'max(b+c)')}}
+do_test table-8.4 {
+ execsql2 {
+ CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3'xyz];
+ SELECT * FROM t5;
+ }
+} {y'all 1}
+do_test table-8.5 {
+ db close
+ sqlite db test.db
+ execsql2 {
+ SELECT * FROM [t4'abc];
+ }
+} {cnt 1 max(b+c) 5}
+do_test table-8.6 {
+ execsql2 {
+ SELECT * FROM t2;
+ }
+} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
+do_test table-8.7 {
+ catchsql {
+ SELECT * FROM t5;
+ }
+} {1 {no such table: t5}}
+do_test table-8.8 {
+ catchsql {
+ CREATE TABLE t5 AS SELECT * FROM no_such_table;
+ }
+} {1 {no such table: no_such_table}}
+
+# Make sure we cannot have duplicate column names within a table.
+#
+do_test table-9.1 {
+ catchsql {
+ CREATE TABLE t6(a,b,a);
+ }
+} {1 {duplicate column name: a}}
+
+# Check the foreign key syntax.
+#
+do_test table-10.1 {
+ catchsql {
+ CREATE TABLE t6(a REFERENCES t4(a) NOT NULL);
+ INSERT INTO t6 VALUES(NULL);
+ }
+} {1 {t6.a may not be NULL}}
+do_test table-10.2 {
+ catchsql {
+ DROP TABLE t6;
+ CREATE TABLE t6(a REFERENCES t4(a) MATCH PARTIAL);
+ }
+} {0 {}}
+do_test table-10.3 {
+ catchsql {
+ DROP TABLE t6;
+ CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON DELETE SET NULL NOT NULL);
+ }
+} {0 {}}
+do_test table-10.4 {
+ catchsql {
+ DROP TABLE t6;
+ CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON UPDATE SET DEFAULT DEFAULT 1);
+ }
+} {0 {}}
+do_test table-10.5 {
+ catchsql {
+ DROP TABLE t6;
+ CREATE TABLE t6(a NOT NULL NOT DEFERRABLE INITIALLY IMMEDIATE);
+ }
+} {0 {}}
+do_test table-10.6 {
+ catchsql {
+ DROP TABLE t6;
+ CREATE TABLE t6(a NOT NULL DEFERRABLE INITIALLY DEFERRED);
+ }
+} {0 {}}
+do_test table-10.7 {
+ catchsql {
+ DROP TABLE t6;
+ CREATE TABLE t6(a,
+ FOREIGN KEY (a) REFERENCES t4(b) DEFERRABLE INITIALLY DEFERRED
+ );
+ }
+} {0 {}}
+do_test table-10.8 {
+ catchsql {
+ DROP TABLE t6;
+ CREATE TABLE t6(a,b,c,
+ FOREIGN KEY (b,c) REFERENCES t4(x,y) MATCH PARTIAL
+ ON UPDATE SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
+ );
+ }
+} {0 {}}
+do_test table-10.9 {
+ catchsql {
+ DROP TABLE t6;
+ CREATE TABLE t6(a,b,c,
+ FOREIGN KEY (b,c) REFERENCES t4(x)
+ );
+ }
+} {1 {number of columns in foreign key does not match the number of columns in the referenced table}}
+do_test table-10.10 {
+ catchsql {DROP TABLE t6}
+ catchsql {
+ CREATE TABLE t6(a,b,c,
+ FOREIGN KEY (b,c) REFERENCES t4(x,y,z)
+ );
+ }
+} {1 {number of columns in foreign key does not match the number of columns in the referenced table}}
+do_test table-10.11 {
+ catchsql {DROP TABLE t6}
+ catchsql {
+ CREATE TABLE t6(a,b, c REFERENCES t4(x,y));
+ }
+} {1 {foreign key on c should reference only one column of table t4}}
+do_test table-10.12 {
+ catchsql {DROP TABLE t6}
+ catchsql {
+ CREATE TABLE t6(a,b,c,
+ FOREIGN KEY (b,x) REFERENCES t4(x,y)
+ );
+ }
+} {1 {unknown column "x" in foreign key definition}}
+do_test table-10.13 {
+ catchsql {DROP TABLE t6}
+ catchsql {
+ CREATE TABLE t6(a,b,c,
+ FOREIGN KEY (x,b) REFERENCES t4(x,y)
+ );
+ }
+} {1 {unknown column "x" in foreign key definition}}
+
+
+# Test for the "typeof" function.
+#
+do_test table-11.1 {
+ execsql {
+ CREATE TABLE t7(
+ a integer primary key,
+ b number(5,10),
+ c character varying (8),
+ d VARCHAR(9),
+ e clob,
+ f BLOB,
+ g Text,
+ h
+ );
+ INSERT INTO t7(a) VALUES(1);
+ SELECT typeof(a), typeof(b), typeof(c), typeof(d),
+ typeof(e), typeof(f), typeof(g), typeof(h)
+ FROM t7 LIMIT 1;
+ }
+} {numeric numeric text text text text text numeric}
+do_test table-11.2 {
+ execsql {
+ SELECT typeof(a+b), typeof(a||b), typeof(c+d), typeof(c||d)
+ FROM t7 LIMIT 1;
+ }
+} {numeric text numeric text}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/tableapi.test b/usr/src/lib/libsqlite/test/tableapi.test
new file mode 100644
index 0000000000..a41fd55695
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/tableapi.test
@@ -0,0 +1,204 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 sqlite_exec_printf() and
+# sqlite_get_table_printf() APIs.
+#
+# $Id: tableapi.test,v 1.7 2004/02/02 12:29:25 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test tableapi-1.0 {
+ set ::dbx [sqlite_open test.db]
+ catch {sqlite_exec_printf $::dbx {DROP TABLE xyz} {}}
+ sqlite_exec_printf $::dbx {CREATE TABLE %s(a int, b text)} xyz
+} {0 {}}
+do_test tableapi-1.1 {
+ sqlite_exec_printf $::dbx {
+ INSERT INTO xyz VALUES(1,'%q')
+ } {Hi Y'all}
+} {0 {}}
+do_test tableapi-1.2 {
+ sqlite_exec_printf $::dbx {SELECT * FROM xyz} {}
+} {0 {a b 1 {Hi Y'all}}}
+
+do_test tableapi-2.1 {
+ sqlite_get_table_printf $::dbx {
+ BEGIN TRANSACTION;
+ SELECT * FROM xyz WHERE b='%q'
+ } {Hi Y'all}
+} {0 1 2 a b 1 {Hi Y'all}}
+do_test tableapi-2.2 {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz
+ } {}
+} {0 1 2 a b 1 {Hi Y'all}}
+do_test tableapi-2.3 {
+ for {set i 2} {$i<=50} {incr i} {
+ sqlite_get_table_printf $::dbx \
+ "INSERT INTO xyz VALUES($i,'(%s)')" $i
+ }
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz ORDER BY a
+ } {}
+} {0 50 2 a b 1 {Hi Y'all} 2 (2) 3 (3) 4 (4) 5 (5) 6 (6) 7 (7) 8 (8) 9 (9) 10 (10) 11 (11) 12 (12) 13 (13) 14 (14) 15 (15) 16 (16) 17 (17) 18 (18) 19 (19) 20 (20) 21 (21) 22 (22) 23 (23) 24 (24) 25 (25) 26 (26) 27 (27) 28 (28) 29 (29) 30 (30) 31 (31) 32 (32) 33 (33) 34 (34) 35 (35) 36 (36) 37 (37) 38 (38) 39 (39) 40 (40) 41 (41) 42 (42) 43 (43) 44 (44) 45 (45) 46 (46) 47 (47) 48 (48) 49 (49) 50 (50)}
+do_test tableapi-2.3.1 {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz WHERE a>49 ORDER BY a
+ } {}
+} {0 1 2 a b 50 (50)}
+do_test tableapi-2.3.2 {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz WHERE a>47 ORDER BY a
+ } {}
+} {0 3 2 a b 48 (48) 49 (49) 50 (50)}
+do_test tableapi-2.4 {
+ set manyquote ''''''''
+ append manyquote $manyquote
+ append manyquote $manyquote
+ append manyquote $manyquote
+ append manyquote $manyquote
+ append manyquote $manyquote
+ append manyquote $manyquote
+ set ::big_str "$manyquote Hello $manyquote"
+ sqlite_get_table_printf $::dbx {
+ INSERT INTO xyz VALUES(51,'%q')
+ } $::big_str
+} {0 0 0}
+do_test tableapi-2.5 {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz WHERE a>49 ORDER BY a;
+ } {}
+} "0 2 2 a b 50 (50) 51 \173$::big_str\175"
+do_test tableapi-2.6 {
+ sqlite_get_table_printf $::dbx {
+ INSERT INTO xyz VALUES(52,NULL)
+ } {}
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz WHERE a IN (42,50,52) ORDER BY a DESC
+ } {}
+} {0 3 2 a b 52 NULL 50 (50) 42 (42)}
+do_test tableapi-2.7 {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz WHERE a>1000
+ } {}
+} {0 0 0}
+
+# Repeat all tests with the empty_result_callbacks pragma turned on
+#
+do_test tableapi-3.1 {
+ sqlite_get_table_printf $::dbx {
+ ROLLBACK;
+ PRAGMA empty_result_callbacks = ON;
+ SELECT * FROM xyz WHERE b='%q'
+ } {Hi Y'all}
+} {0 1 2 a b 1 {Hi Y'all}}
+do_test tableapi-3.2 {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz
+ } {}
+} {0 1 2 a b 1 {Hi Y'all}}
+do_test tableapi-3.3 {
+ for {set i 2} {$i<=50} {incr i} {
+ sqlite_get_table_printf $::dbx \
+ "INSERT INTO xyz VALUES($i,'(%s)')" $i
+ }
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz ORDER BY a
+ } {}
+} {0 50 2 a b 1 {Hi Y'all} 2 (2) 3 (3) 4 (4) 5 (5) 6 (6) 7 (7) 8 (8) 9 (9) 10 (10) 11 (11) 12 (12) 13 (13) 14 (14) 15 (15) 16 (16) 17 (17) 18 (18) 19 (19) 20 (20) 21 (21) 22 (22) 23 (23) 24 (24) 25 (25) 26 (26) 27 (27) 28 (28) 29 (29) 30 (30) 31 (31) 32 (32) 33 (33) 34 (34) 35 (35) 36 (36) 37 (37) 38 (38) 39 (39) 40 (40) 41 (41) 42 (42) 43 (43) 44 (44) 45 (45) 46 (46) 47 (47) 48 (48) 49 (49) 50 (50)}
+do_test tableapi-3.3.1 {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz WHERE a>49 ORDER BY a
+ } {}
+} {0 1 2 a b 50 (50)}
+do_test tableapi-3.3.2 {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz WHERE a>47 ORDER BY a
+ } {}
+} {0 3 2 a b 48 (48) 49 (49) 50 (50)}
+do_test tableapi-3.4 {
+ sqlite_get_table_printf $::dbx {
+ INSERT INTO xyz VALUES(51,'%q')
+ } $::big_str
+} {0 0 0}
+do_test tableapi-3.5 {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz WHERE a>49 ORDER BY a;
+ } {}
+} "0 2 2 a b 50 (50) 51 \173$::big_str\175"
+do_test tableapi-3.6 {
+ sqlite_get_table_printf $::dbx {
+ INSERT INTO xyz VALUES(52,NULL)
+ } {}
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz WHERE a IN (42,50,52) ORDER BY a DESC
+ } {}
+} {0 3 2 a b 52 NULL 50 (50) 42 (42)}
+do_test tableapi-3.7 {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz WHERE a>1000
+ } {}
+} {0 0 2 a b}
+
+do_test tableapi-4.1 {
+ set rc [catch {
+ sqlite_get_table_printf $::dbx {
+ SELECT * FROM xyz; SELECT * FROM sqlite_master
+ } {}
+ } msg]
+ concat $rc $msg
+} {0 1 {sqlite_get_table() called with two or more incompatible queries}}
+
+# A report on the mailing list says that the sqlite_get_table() api fails
+# on queries involving more than 40 columns. The following code attempts
+# to test that complaint
+#
+do_test tableapi-5.1 {
+ set sql "CREATE TABLE t2("
+ set sep ""
+ for {set i 1} {$i<=100} {incr i} {
+ append sql ${sep}x$i
+ set sep ,
+ }
+ append sql )
+ sqlite_get_table_printf $::dbx $sql {}
+ set sql "INSERT INTO t2 VALUES("
+ set sep ""
+ for {set i 1} {$i<=100} {incr i} {
+ append sql ${sep}$i
+ set sep ,
+ }
+ append sql )
+ sqlite_get_table_printf $::dbx $sql {}
+ sqlite_get_table_printf $::dbx {SELECT * FROM t2} {}
+} {0 1 100 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41 x42 x43 x44 x45 x46 x47 x48 x49 x50 x51 x52 x53 x54 x55 x56 x57 x58 x59 x60 x61 x62 x63 x64 x65 x66 x67 x68 x69 x70 x71 x72 x73 x74 x75 x76 x77 x78 x79 x80 x81 x82 x83 x84 x85 x86 x87 x88 x89 x90 x91 x92 x93 x94 x95 x96 x97 x98 x99 x100 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100}
+do_test tableapi-5.2 {
+ set sql "INSERT INTO t2 VALUES("
+ set sep ""
+ for {set i 1} {$i<=100} {incr i} {
+ append sql ${sep}[expr {$i+1000}]
+ set sep ,
+ }
+ append sql )
+ sqlite_get_table_printf $::dbx $sql {}
+ sqlite_get_table_printf $::dbx {SELECT * FROM t2} {}
+} {0 2 100 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41 x42 x43 x44 x45 x46 x47 x48 x49 x50 x51 x52 x53 x54 x55 x56 x57 x58 x59 x60 x61 x62 x63 x64 x65 x66 x67 x68 x69 x70 x71 x72 x73 x74 x75 x76 x77 x78 x79 x80 x81 x82 x83 x84 x85 x86 x87 x88 x89 x90 x91 x92 x93 x94 x95 x96 x97 x98 x99 x100 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100}
+
+do_test tableapi-99.0 {
+ sqlite_close $::dbx
+} {}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/tclsqlite.test b/usr/src/lib/libsqlite/test/tclsqlite.test
new file mode 100644
index 0000000000..d5a4249c7f
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/tclsqlite.test
@@ -0,0 +1,122 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 TCL interface to the
+# SQLite library.
+#
+# Actually, all tests are based on the TCL interface, so the main
+# interface is pretty well tested. This file contains some addition
+# tests for fringe issues that the main test suite does not cover.
+#
+# $Id: tclsqlite.test,v 1.20.2.1 2004/07/19 19:30:50 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Check the error messages generated by tclsqlite
+#
+if {[sqlite -has-codec]} {
+ set r "sqlite_orig HANDLE FILENAME ?-key CODEC-KEY?"
+} else {
+ set r "sqlite HANDLE FILENAME ?MODE?"
+}
+do_test tcl-1.1 {
+ set v [catch {sqlite bogus} msg]
+ lappend v $msg
+} [list 1 "wrong # args: should be \"$r\""]
+do_test tcl-1.2 {
+ set v [catch {db bogus} msg]
+ lappend v $msg
+} {1 {bad option "bogus": must be authorizer, busy, changes, close, commit_hook, complete, errorcode, eval, function, last_insert_rowid, last_statement_changes, onecolumn, progress, rekey, timeout, or trace}}
+do_test tcl-1.3 {
+ execsql {CREATE TABLE t1(a int, b int)}
+ execsql {INSERT INTO t1 VALUES(10,20)}
+ set v [catch {
+ db eval {SELECT * FROM t1} data {
+ error "The error message"
+ }
+ } msg]
+ lappend v $msg
+} {1 {The error message}}
+do_test tcl-1.4 {
+ set v [catch {
+ db eval {SELECT * FROM t2} data {
+ error "The error message"
+ }
+ } msg]
+ lappend v $msg
+} {1 {no such table: t2}}
+do_test tcl-1.5 {
+ set v [catch {
+ db eval {SELECT * FROM t1} data {
+ break
+ }
+ } msg]
+ lappend v $msg
+} {0 {}}
+do_test tcl-1.6 {
+ set v [catch {
+ db eval {SELECT * FROM t1} data {
+ expr x*
+ }
+ } msg]
+ regsub {:.*$} $msg {} msg
+ lappend v $msg
+} {1 {syntax error in expression "x*"}}
+
+if {[sqlite -encoding]=="UTF-8" && [sqlite -tcl-uses-utf]} {
+ catch {unset ::result}
+ do_test tcl-2.1 {
+ execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)"
+ execsql "PRAGMA table_info(t\u0123x)"
+ } "0 a int 0 {} 0 1 b\u1235 float 0 {} 0"
+ do_test tcl-2.2 {
+ execsql "INSERT INTO t\u0123x VALUES(1,2.3)"
+ db eval "SELECT * FROM t\u0123x" result break
+ set result(*)
+ } "a b\u1235"
+}
+
+if {[sqlite -encoding]=="iso8859" && [sqlite -tcl-uses-utf]} {
+ do_test tcl-2.1 {
+ execsql "CREATE TABLE t\251x(a int, b\306 float)"
+ execsql "PRAGMA table_info(t\251x)"
+ } "0 a int 0 {} 0 1 b\306 float 0 {} 0"
+ do_test tcl-2.2 {
+ execsql "INSERT INTO t\251x VALUES(1,2.3)"
+ db eval "SELECT * FROM t\251x" result break
+ set result(*)
+ } "a b\306"
+}
+
+# Test the onecolumn method
+#
+do_test tcl-3.1 {
+ execsql {
+ INSERT INTO t1 SELECT a*2, b*2 FROM t1;
+ INSERT INTO t1 SELECT a*2+1, b*2+1 FROM t1;
+ INSERT INTO t1 SELECT a*2+3, b*2+3 FROM t1;
+ }
+ set rc [catch {db onecolumn {SELECT * FROM t1 ORDER BY a}} msg]
+ lappend rc $msg
+} {0 10}
+do_test tcl-3.2 {
+ db onecolumn {SELECT * FROM t1 WHERE a<0}
+} {}
+do_test tcl-3.3 {
+ set rc [catch {db onecolumn} errmsg]
+ lappend rc $errmsg
+} {1 {wrong # args: should be "db onecolumn SQL"}}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/temptable.test b/usr/src/lib/libsqlite/test/temptable.test
new file mode 100644
index 0000000000..93ff24bc6c
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/temptable.test
@@ -0,0 +1,402 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 October 7
+#
+# 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.
+#
+# This file implements tests for temporary tables and indices.
+#
+# $Id: temptable.test,v 1.11 2004/02/14 16:31:04 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create an alternative connection to the database
+#
+do_test temptable-1.0 {
+ sqlite db2 ./test.db
+ set dummy {}
+} {}
+
+# Create a permanent table.
+#
+do_test temptable-1.1 {
+ execsql {CREATE TABLE t1(a,b,c);}
+ execsql {INSERT INTO t1 VALUES(1,2,3);}
+ execsql {SELECT * FROM t1}
+} {1 2 3}
+do_test temptable-1.2 {
+ catch {db2 eval {SELECT * FROM sqlite_master}}
+ db2 eval {SELECT * FROM t1}
+} {1 2 3}
+do_test temptable-1.3 {
+ execsql {SELECT name FROM sqlite_master}
+} {t1}
+do_test temptable-1.4 {
+ db2 eval {SELECT name FROM sqlite_master}
+} {t1}
+
+# Create a temporary table. Verify that only one of the two
+# processes can see it.
+#
+do_test temptable-1.5 {
+ db2 eval {
+ CREATE TEMP TABLE t2(x,y,z);
+ INSERT INTO t2 VALUES(4,5,6);
+ }
+ db2 eval {SELECT * FROM t2}
+} {4 5 6}
+do_test temptable-1.6 {
+ catch {execsql {SELECT * FROM sqlite_master}}
+ catchsql {SELECT * FROM t2}
+} {1 {no such table: t2}}
+do_test temptable-1.7 {
+ catchsql {INSERT INTO t2 VALUES(8,9,0);}
+} {1 {no such table: t2}}
+do_test temptable-1.8 {
+ db2 eval {INSERT INTO t2 VALUES(8,9,0);}
+ db2 eval {SELECT * FROM t2 ORDER BY x}
+} {4 5 6 8 9 0}
+do_test temptable-1.9 {
+ db2 eval {DELETE FROM t2 WHERE x==8}
+ db2 eval {SELECT * FROM t2 ORDER BY x}
+} {4 5 6}
+do_test temptable-1.10 {
+ db2 eval {DELETE FROM t2}
+ db2 eval {SELECT * FROM t2}
+} {}
+do_test temptable-1.11 {
+ db2 eval {
+ INSERT INTO t2 VALUES(7,6,5);
+ INSERT INTO t2 VALUES(4,3,2);
+ SELECT * FROM t2 ORDER BY x;
+ }
+} {4 3 2 7 6 5}
+do_test temptable-1.12 {
+ db2 eval {DROP TABLE t2;}
+ set r [catch {db2 eval {SELECT * FROM t2}} msg]
+ lappend r $msg
+} {1 {no such table: t2}}
+
+# Make sure temporary tables work with transactions
+#
+do_test temptable-2.1 {
+ execsql {
+ BEGIN TRANSACTION;
+ CREATE TEMPORARY TABLE t2(x,y);
+ INSERT INTO t2 VALUES(1,2);
+ SELECT * FROM t2;
+ }
+} {1 2}
+do_test temptable-2.2 {
+ execsql {ROLLBACK}
+ catchsql {SELECT * FROM t2}
+} {1 {no such table: t2}}
+do_test temptable-2.3 {
+ execsql {
+ BEGIN TRANSACTION;
+ CREATE TEMPORARY TABLE t2(x,y);
+ INSERT INTO t2 VALUES(1,2);
+ SELECT * FROM t2;
+ }
+} {1 2}
+do_test temptable-2.4 {
+ execsql {COMMIT}
+ catchsql {SELECT * FROM t2}
+} {0 {1 2}}
+do_test temptable-2.5 {
+ set r [catch {db2 eval {SELECT * FROM t2}} msg]
+ lappend r $msg
+} {1 {no such table: t2}}
+
+# Make sure indices on temporary tables are also temporary.
+#
+do_test temptable-3.1 {
+ execsql {
+ CREATE INDEX i2 ON t2(x);
+ SELECT name FROM sqlite_master WHERE type='index';
+ }
+} {}
+do_test temptable-3.2 {
+ execsql {
+ SELECT y FROM t2 WHERE x=1;
+ }
+} {2}
+do_test temptable-3.3 {
+ execsql {
+ DROP INDEX i2;
+ SELECT y FROM t2 WHERE x=1;
+ }
+} {2}
+do_test temptable-3.4 {
+ execsql {
+ CREATE INDEX i2 ON t2(x);
+ DROP TABLE t2;
+ }
+ catchsql {DROP INDEX i2}
+} {1 {no such index: i2}}
+
+# Check for correct name collision processing. A name collision can
+# occur when process A creates a temporary table T then process B
+# creates a permanent table also named T. The temp table in process A
+# hides the existance of the permanent table.
+#
+do_test temptable-4.1 {
+ execsql {
+ CREATE TEMP TABLE t2(x,y);
+ INSERT INTO t2 VALUES(10,20);
+ SELECT * FROM t2;
+ } db2
+} {10 20}
+do_test temptable-4.2 {
+ execsql {
+ CREATE TABLE t2(x,y,z);
+ INSERT INTO t2 VALUES(9,8,7);
+ SELECT * FROM t2;
+ }
+} {9 8 7}
+do_test temptable-4.3 {
+ catchsql {
+ SELECT * FROM t2;
+ } db2
+} {0 {10 20}}
+do_test temptable-4.4.1 {
+ catchsql {
+ SELECT * FROM temp.t2;
+ } db2
+} {0 {10 20}}
+do_test temptable-4.4.2 {
+ catchsql {
+ SELECT * FROM main.t2;
+ } db2
+} {1 {no such table: main.t2}}
+#do_test temptable-4.4.3 {
+# catchsql {
+# SELECT name FROM main.sqlite_master WHERE type='table';
+# } db2
+#} {1 {database schema has changed}}
+do_test temptable-4.4.4 {
+ catchsql {
+ SELECT name FROM main.sqlite_master WHERE type='table';
+ } db2
+} {0 {t1 t2}}
+do_test temptable-4.4.5 {
+ catchsql {
+ SELECT * FROM main.t2;
+ } db2
+} {0 {9 8 7}}
+do_test temptable-4.4.6 {
+ # TEMP takes precedence over MAIN
+ catchsql {
+ SELECT * FROM t2;
+ } db2
+} {0 {10 20}}
+do_test temptable-4.5 {
+ catchsql {
+ DROP TABLE t2; -- should drop TEMP
+ SELECT * FROM t2; -- data should be from MAIN
+ } db2
+} {0 {9 8 7}}
+do_test temptable-4.6 {
+ db2 close
+ sqlite db2 ./test.db
+ catchsql {
+ SELECT * FROM t2;
+ } db2
+} {0 {9 8 7}}
+do_test temptable-4.7 {
+ catchsql {
+ DROP TABLE t2;
+ SELECT * FROM t2;
+ }
+} {1 {no such table: t2}}
+do_test temptable-4.8 {
+ db2 close
+ sqlite db2 ./test.db
+ execsql {
+ CREATE TEMP TABLE t2(x unique,y);
+ INSERT INTO t2 VALUES(1,2);
+ SELECT * FROM t2;
+ } db2
+} {1 2}
+do_test temptable-4.9 {
+ execsql {
+ CREATE TABLE t2(x unique, y);
+ INSERT INTO t2 VALUES(3,4);
+ SELECT * FROM t2;
+ }
+} {3 4}
+do_test temptable-4.10.1 {
+ catchsql {
+ SELECT * FROM t2;
+ } db2
+} {0 {1 2}}
+#do_test temptable-4.10.2 {
+# catchsql {
+# SELECT name FROM sqlite_master WHERE type='table'
+# } db2
+#} {1 {database schema has changed}}
+do_test temptable-4.10.3 {
+ catchsql {
+ SELECT name FROM sqlite_master WHERE type='table'
+ } db2
+} {0 {t1 t2}}
+do_test temptable-4.11 {
+ execsql {
+ SELECT * FROM t2;
+ } db2
+} {1 2}
+do_test temptable-4.12 {
+ execsql {
+ SELECT * FROM t2;
+ }
+} {3 4}
+do_test temptable-4.13 {
+ catchsql {
+ DROP TABLE t2; -- drops TEMP.T2
+ SELECT * FROM t2; -- uses MAIN.T2
+ } db2
+} {0 {3 4}}
+do_test temptable-4.14 {
+ execsql {
+ SELECT * FROM t2;
+ }
+} {3 4}
+do_test temptable-4.15 {
+ db2 close
+ sqlite db2 ./test.db
+ execsql {
+ SELECT * FROM t2;
+ } db2
+} {3 4}
+
+# Now create a temporary table in db2 and a permanent index in db. The
+# temporary table in db2 should mask the name of the permanent index,
+# but the permanent index should still be accessible and should still
+# be updated when its corresponding table changes.
+#
+do_test temptable-5.1 {
+ execsql {
+ CREATE TEMP TABLE mask(a,b,c)
+ } db2
+ execsql {
+ CREATE INDEX mask ON t2(x);
+ SELECT * FROM t2;
+ }
+} {3 4}
+#do_test temptable-5.2 {
+# catchsql {
+# SELECT * FROM t2;
+# } db2
+#} {1 {database schema has changed}}
+do_test temptable-5.3 {
+ catchsql {
+ SELECT * FROM t2;
+ } db2
+} {0 {3 4}}
+do_test temptable-5.4 {
+ execsql {
+ SELECT y FROM t2 WHERE x=3
+ }
+} {4}
+do_test temptable-5.5 {
+ execsql {
+ SELECT y FROM t2 WHERE x=3
+ } db2
+} {4}
+do_test temptable-5.6 {
+ execsql {
+ INSERT INTO t2 VALUES(1,2);
+ SELECT y FROM t2 WHERE x=1;
+ } db2
+} {2}
+do_test temptable-5.7 {
+ execsql {
+ SELECT y FROM t2 WHERE x=3
+ } db2
+} {4}
+do_test temptable-5.8 {
+ execsql {
+ SELECT y FROM t2 WHERE x=1;
+ }
+} {2}
+do_test temptable-5.9 {
+ execsql {
+ SELECT y FROM t2 WHERE x=3
+ }
+} {4}
+
+db2 close
+
+# Test for correct operation of read-only databases
+#
+do_test temptable-6.1 {
+ execsql {
+ CREATE TABLE t8(x);
+ INSERT INTO t8 VALUES('xyzzy');
+ SELECT * FROM t8;
+ }
+} {xyzzy}
+do_test temptable-6.2 {
+ db close
+ catch {file attributes test.db -permissions 0444}
+ catch {file attributes test.db -readonly 1}
+ sqlite db test.db
+ if {[file writable test.db]} {
+ error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user"
+ }
+ execsql {
+ SELECT * FROM t8;
+ }
+} {xyzzy}
+do_test temptable-6.3 {
+ if {[file writable test.db]} {
+ error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user"
+ }
+ catchsql {
+ CREATE TABLE t9(x,y);
+ }
+} {1 {attempt to write a readonly database}}
+do_test temptable-6.4 {
+ catchsql {
+ CREATE TEMP TABLE t9(x,y);
+ }
+} {0 {}}
+do_test temptable-6.5 {
+ catchsql {
+ INSERT INTO t9 VALUES(1,2);
+ SELECT * FROM t9;
+ }
+} {0 {1 2}}
+do_test temptable-6.6 {
+ if {[file writable test.db]} {
+ error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user"
+ }
+ catchsql {
+ INSERT INTO t8 VALUES('hello');
+ SELECT * FROM t8;
+ }
+} {1 {attempt to write a readonly database}}
+do_test temptable-6.7 {
+ catchsql {
+ SELECT * FROM t8,t9;
+ }
+} {0 {xyzzy 1 2}}
+do_test temptable-6.8 {
+ db close
+ sqlite db test.db
+ catchsql {
+ SELECT * FROM t8,t9;
+ }
+} {1 {no such table: t9}}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/tester.tcl b/usr/src/lib/libsqlite/test/tester.tcl
new file mode 100644
index 0000000000..8cc6951eee
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/tester.tcl
@@ -0,0 +1,267 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 some common TCL routines used for regression
+# testing the SQLite library
+#
+# $Id: tester.tcl,v 1.28 2004/02/14 01:39:50 drh Exp $
+
+# Make sure tclsqlite was compiled correctly. Abort now with an
+# error message if not.
+#
+if {[sqlite -tcl-uses-utf]} {
+ if {"\u1234"=="u1234"} {
+ puts stderr "***** BUILD PROBLEM *****"
+ puts stderr "$argv0 was linked against an older version"
+ puts stderr "of TCL that does not support Unicode, but uses a header"
+ puts stderr "file (\"tcl.h\") from a new TCL version that does support"
+ puts stderr "Unicode. This combination causes internal errors."
+ puts stderr "Recompile using a TCL library and header file that match"
+ puts stderr "and try again.\n**************************"
+ exit 1
+ }
+} else {
+ if {"\u1234"!="u1234"} {
+ puts stderr "***** BUILD PROBLEM *****"
+ puts stderr "$argv0 was linked against an newer version"
+ puts stderr "of TCL that supports Unicode, but uses a header file"
+ puts stderr "(\"tcl.h\") from a old TCL version that does not support"
+ puts stderr "Unicode. This combination causes internal errors."
+ puts stderr "Recompile using a TCL library and header file that match"
+ puts stderr "and try again.\n**************************"
+ exit 1
+ }
+}
+
+# Use the pager codec if it is available
+#
+if {[sqlite -has-codec] && [info command sqlite_orig]==""} {
+ rename sqlite sqlite_orig
+ proc sqlite {args} {
+ if {[llength $args]==2 && [string index [lindex $args 0] 0]!="-"} {
+ lappend args -key {xyzzy}
+ }
+ uplevel 1 sqlite_orig $args
+ }
+}
+
+
+# Create a test database
+#
+catch {db close}
+file delete -force test.db
+file delete -force test.db-journal
+sqlite db ./test.db
+if {[info exists ::SETUP_SQL]} {
+ db eval $::SETUP_SQL
+}
+
+# Abort early if this script has been run before.
+#
+if {[info exists nTest]} return
+
+# Set the test counters to zero
+#
+set nErr 0
+set nTest 0
+set nProb 0
+set skip_test 0
+set failList {}
+
+# Invoke the do_test procedure to run a single test
+#
+proc do_test {name cmd expected} {
+ global argv nErr nTest skip_test
+ if {$skip_test} {
+ set skip_test 0
+ return
+ }
+ if {[llength $argv]==0} {
+ set go 1
+ } else {
+ set go 0
+ foreach pattern $argv {
+ if {[string match $pattern $name]} {
+ set go 1
+ break
+ }
+ }
+ }
+ if {!$go} return
+ incr nTest
+ puts -nonewline $name...
+ flush stdout
+ if {[catch {uplevel #0 "$cmd;\n"} result]} {
+ puts "\nError: $result"
+ incr nErr
+ lappend ::failList $name
+ if {$nErr>100} {puts "*** Giving up..."; finalize_testing}
+ } elseif {[string compare $result $expected]} {
+ puts "\nExpected: \[$expected\]\n Got: \[$result\]"
+ incr nErr
+ lappend ::failList $name
+ if {$nErr>100} {puts "*** Giving up..."; finalize_testing}
+ } else {
+ puts " Ok"
+ }
+}
+
+# Invoke this procedure on a test that is probabilistic
+# and might fail sometimes.
+#
+proc do_probtest {name cmd expected} {
+ global argv nProb nTest skip_test
+ if {$skip_test} {
+ set skip_test 0
+ return
+ }
+ if {[llength $argv]==0} {
+ set go 1
+ } else {
+ set go 0
+ foreach pattern $argv {
+ if {[string match $pattern $name]} {
+ set go 1
+ break
+ }
+ }
+ }
+ if {!$go} return
+ incr nTest
+ puts -nonewline $name...
+ flush stdout
+ if {[catch {uplevel #0 "$cmd;\n"} result]} {
+ puts "\nError: $result"
+ incr nErr
+ } elseif {[string compare $result $expected]} {
+ puts "\nExpected: \[$expected\]\n Got: \[$result\]"
+ puts "NOTE: The results of the previous test depend on system load"
+ puts "and processor speed. The test may sometimes fail even if the"
+ puts "library is working correctly."
+ incr nProb
+ } else {
+ puts " Ok"
+ }
+}
+
+# The procedure uses the special "sqlite_malloc_stat" command
+# (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1)
+# to see how many malloc()s have not been free()ed. The number
+# of surplus malloc()s is stored in the global variable $::Leak.
+# If the value in $::Leak grows, it may mean there is a memory leak
+# in the library.
+#
+proc memleak_check {} {
+ if {[info command sqlite_malloc_stat]!=""} {
+ set r [sqlite_malloc_stat]
+ set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]
+ }
+}
+
+# Run this routine last
+#
+proc finish_test {} {
+ finalize_testing
+}
+proc finalize_testing {} {
+ global nTest nErr nProb sqlite_open_file_count
+ if {$nErr==0} memleak_check
+ catch {db close}
+ puts "$nErr errors out of $nTest tests"
+ puts "Failures on these tests: $::failList"
+ if {$nProb>0} {
+ puts "$nProb probabilistic tests also failed, but this does"
+ puts "not necessarily indicate a malfunction."
+ }
+ if {$sqlite_open_file_count} {
+ puts "$sqlite_open_file_count files were left open"
+ incr nErr
+ }
+ exit [expr {$nErr>0}]
+}
+
+# A procedure to execute SQL
+#
+proc execsql {sql {db db}} {
+ # puts "SQL = $sql"
+ return [$db eval $sql]
+}
+
+# Execute SQL and catch exceptions.
+#
+proc catchsql {sql {db db}} {
+ # puts "SQL = $sql"
+ set r [catch {$db eval $sql} msg]
+ lappend r $msg
+ return $r
+}
+
+# Do an VDBE code dump on the SQL given
+#
+proc explain {sql {db db}} {
+ puts ""
+ puts "addr opcode p1 p2 p3 "
+ puts "---- ------------ ------ ------ ---------------"
+ $db eval "explain $sql" {} {
+ puts [format {%-4d %-12.12s %-6d %-6d %s} $addr $opcode $p1 $p2 $p3]
+ }
+}
+
+# Another procedure to execute SQL. This one includes the field
+# names in the returned list.
+#
+proc execsql2 {sql} {
+ set result {}
+ db eval $sql data {
+ foreach f $data(*) {
+ lappend result $f $data($f)
+ }
+ }
+ return $result
+}
+
+# Use the non-callback API to execute multiple SQL statements
+#
+proc stepsql {dbptr sql} {
+ set sql [string trim $sql]
+ set r 0
+ while {[string length $sql]>0} {
+ if {[catch {sqlite_compile $dbptr $sql sqltail} vm]} {
+ return [list 1 $vm]
+ }
+ set sql [string trim $sqltail]
+ while {[sqlite_step $vm N VAL COL]=="SQLITE_ROW"} {
+ foreach v $VAL {lappend r $v}
+ }
+ if {[catch {sqlite_finalize $vm} errmsg]} {
+ return [list 1 $errmsg]
+ }
+ }
+ return $r
+}
+
+# Delete a file or directory
+#
+proc forcedelete {filename} {
+ if {[catch {file delete -force $filename}]} {
+ exec rm -rf $filename
+ }
+}
+
+# Do an integrity check of the entire database
+#
+proc integrity_check {name} {
+ do_test $name {
+ execsql {PRAGMA integrity_check}
+ } {ok}
+}
diff --git a/usr/src/lib/libsqlite/test/thread1.test b/usr/src/lib/libsqlite/test/thread1.test
new file mode 100644
index 0000000000..cbca2e364a
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/thread1.test
@@ -0,0 +1,161 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2003 December 18
+#
+# 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 multithreading behavior
+#
+# $Id: thread1.test,v 1.3 2004/02/11 02:18:07 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Skip this whole file if the thread testing code is not enabled
+#
+if {[llength [info command thread_step]]==0 || [sqlite -has-codec]} {
+ finish_test
+ return
+}
+
+# Create some data to work with
+#
+do_test thread1-1.1 {
+ execsql {
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1 VALUES(1,'abcdefgh');
+ INSERT INTO t1 SELECT a+1, b||b FROM t1;
+ INSERT INTO t1 SELECT a+2, b||b FROM t1;
+ INSERT INTO t1 SELECT a+4, b||b FROM t1;
+ SELECT count(*), max(length(b)) FROM t1;
+ }
+} {8 64}
+
+# Interleave two threads on read access. Then make sure a third
+# thread can write the database. In other words:
+#
+# read-lock A
+# read-lock B
+# unlock A
+# unlock B
+# write-lock C
+#
+# At one point, the write-lock of C would fail on Linux.
+#
+do_test thread1-1.2 {
+ thread_create A test.db
+ thread_create B test.db
+ thread_create C test.db
+ thread_compile A {SELECT a FROM t1}
+ thread_step A
+ thread_result A
+} SQLITE_ROW
+do_test thread1-1.3 {
+ thread_argc A
+} 1
+do_test thread1-1.4 {
+ thread_argv A 0
+} 1
+do_test thread1-1.5 {
+ thread_compile B {SELECT b FROM t1}
+ thread_step B
+ thread_result B
+} SQLITE_ROW
+do_test thread1-1.6 {
+ thread_argc B
+} 1
+do_test thread1-1.7 {
+ thread_argv B 0
+} abcdefgh
+do_test thread1-1.8 {
+ thread_finalize A
+ thread_result A
+} SQLITE_OK
+do_test thread1-1.9 {
+ thread_finalize B
+ thread_result B
+} SQLITE_OK
+do_test thread1-1.10 {
+ thread_compile C {CREATE TABLE t2(x,y)}
+ thread_step C
+ thread_result C
+} SQLITE_DONE
+do_test thread1-1.11 {
+ thread_finalize C
+ thread_result C
+} SQLITE_OK
+do_test thread1-1.12 {
+ catchsql {SELECT name FROM sqlite_master}
+ execsql {SELECT name FROM sqlite_master}
+} {t1 t2}
+
+
+# Under this scenario:
+#
+# read-lock A
+# read-lock B
+# unlock A
+# write-lock C
+#
+# Make sure the write-lock fails with SQLITE_BUSY
+#
+do_test thread1-2.1 {
+ thread_halt *
+ thread_create A test.db
+ thread_compile A {SELECT a FROM t1}
+ thread_step A
+ thread_result A
+} SQLITE_ROW
+do_test thread1-2.2 {
+ thread_create B test.db
+ thread_compile B {SELECT b FROM t1}
+ thread_step B
+ thread_result B
+} SQLITE_ROW
+do_test thread1-2.3 {
+ thread_create C test.db
+ thread_compile C {INSERT INTO t2 VALUES(98,99)}
+ thread_step C
+ thread_result C
+} SQLITE_BUSY
+do_test thread1-2.4 {
+ execsql {SELECT * FROM t2}
+} {}
+do_test thread1-2.5 {
+ thread_finalize A
+ thread_result A
+} SQLITE_OK
+do_test thread1-2.6 {
+ thread_step C
+ thread_result C
+} SQLITE_BUSY
+do_test thread1-2.7 {
+ execsql {SELECT * FROM t2}
+} {}
+do_test thread1-2.8 {
+ thread_finalize B
+ thread_result B
+} SQLITE_OK
+do_test thread1-2.9 {
+ thread_step C
+ thread_result C
+} SQLITE_DONE
+do_test thread1-2.10 {
+ execsql {SELECT * FROM t2}
+} {98 99}
+do_test thread1-2.11 {
+ thread_finalize C
+ thread_result C
+} SQLITE_OK
+
+thread_halt *
+finish_test
diff --git a/usr/src/lib/libsqlite/test/threadtest1.c b/usr/src/lib/libsqlite/test/threadtest1.c
new file mode 100644
index 0000000000..48f4bf7679
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/threadtest1.c
@@ -0,0 +1,285 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+** 2002 January 15
+**
+** 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 a simple standalone program used to test whether
+** or not the SQLite library is threadsafe.
+**
+** Testing the thread safety of SQLite is difficult because there are very
+** few places in the code that are even potentially unsafe, and those
+** places execute for very short periods of time. So even if the library
+** is compiled with its mutexes disabled, it is likely to work correctly
+** in a multi-threaded program most of the time.
+**
+** This file is NOT part of the standard SQLite library. It is used for
+** testing only.
+*/
+#include "sqlite.h"
+#include <pthread.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+** Enable for tracing
+*/
+static int verbose = 0;
+
+/*
+** Come here to die.
+*/
+static void Exit(int rc){
+ exit(rc);
+}
+
+extern char *sqlite_mprintf(const char *zFormat, ...);
+extern char *sqlite_vmprintf(const char *zFormat, va_list);
+
+/*
+** When a lock occurs, yield.
+*/
+static int db_is_locked(void *NotUsed, const char *zNotUsed, int iNotUsed){
+ /* sched_yield(); */
+ if( verbose ) printf("BUSY %s\n", (char*)NotUsed);
+ usleep(100);
+ return 1;
+}
+
+/*
+** Used to accumulate query results by db_query()
+*/
+struct QueryResult {
+ const char *zFile; /* Filename - used for error reporting */
+ int nElem; /* Number of used entries in azElem[] */
+ int nAlloc; /* Number of slots allocated for azElem[] */
+ char **azElem; /* The result of the query */
+};
+
+/*
+** The callback function for db_query
+*/
+static int db_query_callback(
+ void *pUser, /* Pointer to the QueryResult structure */
+ int nArg, /* Number of columns in this result row */
+ char **azArg, /* Text of data in all columns */
+ char **NotUsed /* Names of the columns */
+){
+ struct QueryResult *pResult = (struct QueryResult*)pUser;
+ int i;
+ if( pResult->nElem + nArg >= pResult->nAlloc ){
+ if( pResult->nAlloc==0 ){
+ pResult->nAlloc = nArg+1;
+ }else{
+ pResult->nAlloc = pResult->nAlloc*2 + nArg + 1;
+ }
+ pResult->azElem = realloc( pResult->azElem, pResult->nAlloc*sizeof(char*));
+ if( pResult->azElem==0 ){
+ fprintf(stdout,"%s: malloc failed\n", pResult->zFile);
+ return 1;
+ }
+ }
+ if( azArg==0 ) return 0;
+ for(i=0; i<nArg; i++){
+ pResult->azElem[pResult->nElem++] =
+ sqlite_mprintf("%s",azArg[i] ? azArg[i] : "");
+ }
+ return 0;
+}
+
+/*
+** Execute a query against the database. NULL values are returned
+** as an empty string. The list is terminated by a single NULL pointer.
+*/
+char **db_query(sqlite *db, const char *zFile, const char *zFormat, ...){
+ char *zSql;
+ int rc;
+ char *zErrMsg = 0;
+ va_list ap;
+ struct QueryResult sResult;
+ va_start(ap, zFormat);
+ zSql = sqlite_vmprintf(zFormat, ap);
+ va_end(ap);
+ memset(&sResult, 0, sizeof(sResult));
+ sResult.zFile = zFile;
+ if( verbose ) printf("QUERY %s: %s\n", zFile, zSql);
+ rc = sqlite_exec(db, zSql, db_query_callback, &sResult, &zErrMsg);
+ if( rc==SQLITE_SCHEMA ){
+ if( zErrMsg ) free(zErrMsg);
+ rc = sqlite_exec(db, zSql, db_query_callback, &sResult, &zErrMsg);
+ }
+ if( verbose ) printf("DONE %s %s\n", zFile, zSql);
+ if( zErrMsg ){
+ fprintf(stdout,"%s: query failed: %s - %s\n", zFile, zSql, zErrMsg);
+ free(zErrMsg);
+ free(zSql);
+ Exit(1);
+ }
+ sqlite_freemem(zSql);
+ if( sResult.azElem==0 ){
+ db_query_callback(&sResult, 0, 0, 0);
+ }
+ sResult.azElem[sResult.nElem] = 0;
+ return sResult.azElem;
+}
+
+/*
+** Execute an SQL statement.
+*/
+void db_execute(sqlite *db, const char *zFile, const char *zFormat, ...){
+ char *zSql;
+ int rc;
+ char *zErrMsg = 0;
+ va_list ap;
+ va_start(ap, zFormat);
+ zSql = sqlite_vmprintf(zFormat, ap);
+ va_end(ap);
+ if( verbose ) printf("EXEC %s: %s\n", zFile, zSql);
+ rc = sqlite_exec(db, zSql, 0, 0, &zErrMsg);
+ while( rc==SQLITE_SCHEMA ){
+ if( zErrMsg ) free(zErrMsg);
+ rc = sqlite_exec(db, zSql, 0, 0, &zErrMsg);
+ }
+ if( verbose ) printf("DONE %s: %s\n", zFile, zSql);
+ if( zErrMsg ){
+ fprintf(stdout,"%s: command failed: %s - %s\n", zFile, zSql, zErrMsg);
+ free(zErrMsg);
+ sqlite_freemem(zSql);
+ Exit(1);
+ }
+ sqlite_freemem(zSql);
+}
+
+/*
+** Free the results of a db_query() call.
+*/
+void db_query_free(char **az){
+ int i;
+ for(i=0; az[i]; i++){
+ sqlite_freemem(az[i]);
+ }
+ free(az);
+}
+
+/*
+** Check results
+*/
+void db_check(const char *zFile, const char *zMsg, char **az, ...){
+ va_list ap;
+ int i;
+ char *z;
+ va_start(ap, az);
+ for(i=0; (z = va_arg(ap, char*))!=0; i++){
+ if( az[i]==0 || strcmp(az[i],z)!=0 ){
+ fprintf(stdout,"%s: %s: bad result in column %d: %s\n",
+ zFile, zMsg, i+1, az[i]);
+ db_query_free(az);
+ Exit(1);
+ }
+ }
+ va_end(ap);
+ db_query_free(az);
+}
+
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t sig = PTHREAD_COND_INITIALIZER;
+int thread_cnt = 0;
+
+static void *worker_bee(void *pArg){
+ const char *zFilename = (char*)pArg;
+ char *azErr;
+ int i, cnt;
+ int t = atoi(zFilename);
+ char **az;
+ sqlite *db;
+
+ pthread_mutex_lock(&lock);
+ thread_cnt++;
+ pthread_mutex_unlock(&lock);
+ printf("%s: START\n", zFilename);
+ fflush(stdout);
+ for(cnt=0; cnt<10; cnt++){
+ db = sqlite_open(&zFilename[2], 0, &azErr);
+ if( db==0 ){
+ fprintf(stdout,"%s: can't open\n", zFilename);
+ Exit(1);
+ }
+ sqlite_busy_handler(db, db_is_locked, zFilename);
+ db_execute(db, zFilename, "CREATE TABLE t%d(a,b,c);", t);
+ for(i=1; i<=100; i++){
+ db_execute(db, zFilename, "INSERT INTO t%d VALUES(%d,%d,%d);",
+ t, i, i*2, i*i);
+ }
+ az = db_query(db, zFilename, "SELECT count(*) FROM t%d", t);
+ db_check(zFilename, "tX size", az, "100", 0);
+ az = db_query(db, zFilename, "SELECT avg(b) FROM t%d", t);
+ db_check(zFilename, "tX avg", az, "101", 0);
+ db_execute(db, zFilename, "DELETE FROM t%d WHERE a>50", t);
+ az = db_query(db, zFilename, "SELECT avg(b) FROM t%d", t);
+ db_check(zFilename, "tX avg2", az, "51", 0);
+ for(i=1; i<=50; i++){
+ char z1[30], z2[30];
+ az = db_query(db, zFilename, "SELECT b, c FROM t%d WHERE a=%d", t, i);
+ sprintf(z1, "%d", i*2);
+ sprintf(z2, "%d", i*i);
+ db_check(zFilename, "readback", az, z1, z2, 0);
+ }
+ db_execute(db, zFilename, "DROP TABLE t%d;", t);
+ sqlite_close(db);
+ }
+ printf("%s: END\n", zFilename);
+ /* unlink(zFilename); */
+ fflush(stdout);
+ pthread_mutex_lock(&lock);
+ thread_cnt--;
+ if( thread_cnt<=0 ){
+ pthread_cond_signal(&sig);
+ }
+ pthread_mutex_unlock(&lock);
+ return 0;
+}
+
+int main(int argc, char **argv){
+ char *zFile;
+ int i, n;
+ pthread_t id;
+ if( argc>2 && strcmp(argv[1], "-v")==0 ){
+ verbose = 1;
+ argc--;
+ argv++;
+ }
+ if( argc<2 || (n=atoi(argv[1]))<1 ) n = 10;
+ for(i=0; i<n; i++){
+ char zBuf[200];
+ sprintf(zBuf, "testdb-%d", (i+1)/2);
+ unlink(zBuf);
+ }
+ for(i=0; i<n; i++){
+ zFile = sqlite_mprintf("%d.testdb-%d", i%2+1, (i+2)/2);
+ unlink(zFile);
+ pthread_create(&id, 0, worker_bee, (void*)zFile);
+ pthread_detach(id);
+ }
+ pthread_mutex_lock(&lock);
+ while( thread_cnt>0 ){
+ pthread_cond_wait(&sig, &lock);
+ }
+ pthread_mutex_unlock(&lock);
+ for(i=0; i<n; i++){
+ char zBuf[200];
+ sprintf(zBuf, "testdb-%d", (i+1)/2);
+ unlink(zBuf);
+ }
+ return 0;
+}
diff --git a/usr/src/lib/libsqlite/test/threadtest2.c b/usr/src/lib/libsqlite/test/threadtest2.c
new file mode 100644
index 0000000000..9e49e50af1
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/threadtest2.c
@@ -0,0 +1,127 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+** 2004 January 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.
+**
+*************************************************************************
+** This file implements a simple standalone program used to test whether
+** or not the SQLite library is threadsafe.
+**
+** This file is NOT part of the standard SQLite library. It is used for
+** testing only.
+*/
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+#include <stdlib.h>
+#include "sqlite.h"
+
+/*
+** Name of the database
+*/
+#define DB_FILE "test.db"
+
+/*
+** When this variable becomes non-zero, all threads stop
+** what they are doing.
+*/
+volatile int all_stop = 0;
+
+/*
+** Callback from the integrity check. If the result is anything other
+** than "ok" it means the integrity check has failed. Set the "all_stop"
+** global variable to stop all other activity. Print the error message
+** or print OK if the string "ok" is seen.
+*/
+int check_callback(void *notUsed, int argc, char **argv, char **notUsed2){
+ if( strcmp(argv[0],"ok") ){
+ all_stop = 1;
+ fprintf(stderr,"pid=%d. %s\n", getpid(), argv[0]);
+ }else{
+ /* fprintf(stderr,"pid=%d. OK\n", getpid()); */
+ }
+ return 0;
+}
+
+/*
+** Do an integrity check on the database. If the first integrity check
+** fails, try it a second time.
+*/
+int integrity_check(sqlite *db){
+ int rc;
+ if( all_stop ) return 0;
+ /* fprintf(stderr,"pid=%d: CHECK\n", getpid()); */
+ rc = sqlite_exec(db, "pragma integrity_check", check_callback, 0, 0);
+ if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
+ fprintf(stderr,"pid=%d, Integrity check returns %d\n", getpid(), rc);
+ }
+ if( all_stop ){
+ sqlite_exec(db, "pragma integrity_check", check_callback, 0, 0);
+ }
+ return 0;
+}
+
+/*
+** This is the worker thread
+*/
+void *worker(void *notUsed){
+ sqlite *db;
+ int rc;
+ int cnt = 0;
+ while( !all_stop && cnt++<10000 ){
+ if( cnt%1000==0 ) printf("pid=%d: %d\n", getpid(), cnt);
+ while( (db = sqlite_open(DB_FILE, 0, 0))==0 ) sched_yield();
+ sqlite_exec(db, "PRAGMA synchronous=OFF", 0, 0, 0);
+ integrity_check(db);
+ if( all_stop ){ sqlite_close(db); break; }
+ /* fprintf(stderr, "pid=%d: BEGIN\n", getpid()); */
+ rc = sqlite_exec(db, "INSERT INTO t1 VALUES('bogus data')", 0, 0, 0);
+ /* fprintf(stderr, "pid=%d: END rc=%d\n", getpid(), rc); */
+ sqlite_close(db);
+ }
+ return 0;
+}
+
+/*
+** Initialize the database and start the threads
+*/
+int main(int argc, char **argv){
+ sqlite *db;
+ int i, rc;
+ pthread_t aThread[5];
+
+ if( strcmp(DB_FILE,":memory:") ) unlink(DB_FILE);
+ db = sqlite_open(DB_FILE, 0, 0);
+ if( db==0 ){
+ fprintf(stderr,"unable to initialize database\n");
+ exit(1);
+ }
+ rc = sqlite_exec(db, "CREATE TABLE t1(x);", 0,0,0);
+ if( rc ){
+ fprintf(stderr,"cannot create table t1: %d\n", rc);
+ exit(1);
+ }
+ sqlite_close(db);
+ for(i=0; i<sizeof(aThread)/sizeof(aThread[0]); i++){
+ pthread_create(&aThread[i], 0, worker, 0);
+ }
+ for(i=0; i<sizeof(aThread)/sizeof(aThread[i]); i++){
+ pthread_join(aThread[i], 0);
+ }
+ if( !all_stop ){
+ printf("Everything seems ok.\n");
+ return 0;
+ }else{
+ printf("We hit an error.\n");
+ return 1;
+ }
+}
diff --git a/usr/src/lib/libsqlite/test/trans.test b/usr/src/lib/libsqlite/test/trans.test
new file mode 100644
index 0000000000..a6b27e4953
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/trans.test
@@ -0,0 +1,905 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 database locks.
+#
+# $Id: trans.test,v 1.19 2004/03/08 13:26:18 drh Exp $
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+
+# Create several tables to work with.
+#
+do_test trans-1.0 {
+ execsql {
+ CREATE TABLE one(a int PRIMARY KEY, b text);
+ INSERT INTO one VALUES(1,'one');
+ INSERT INTO one VALUES(2,'two');
+ INSERT INTO one VALUES(3,'three');
+ SELECT b FROM one ORDER BY a;
+ }
+} {one two three}
+do_test trans-1.1 {
+ execsql {
+ CREATE TABLE two(a int PRIMARY KEY, b text);
+ INSERT INTO two VALUES(1,'I');
+ INSERT INTO two VALUES(5,'V');
+ INSERT INTO two VALUES(10,'X');
+ SELECT b FROM two ORDER BY a;
+ }
+} {I V X}
+do_test trans-1.9 {
+ sqlite altdb test.db
+ execsql {SELECT b FROM one ORDER BY a} altdb
+} {one two three}
+do_test trans-1.10 {
+ execsql {SELECT b FROM two ORDER BY a} altdb
+} {I V X}
+integrity_check trans-1.11
+
+# Basic transactions
+#
+do_test trans-2.1 {
+ set v [catch {execsql {BEGIN}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.2 {
+ set v [catch {execsql {END}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.3 {
+ set v [catch {execsql {BEGIN TRANSACTION}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.4 {
+ set v [catch {execsql {COMMIT TRANSACTION}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.5 {
+ set v [catch {execsql {BEGIN TRANSACTION 'foo'}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.6 {
+ set v [catch {execsql {ROLLBACK TRANSACTION 'foo'}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.10 {
+ execsql {
+ BEGIN;
+ SELECT a FROM one ORDER BY a;
+ SELECT a FROM two ORDER BY a;
+ END;
+ }
+} {1 2 3 1 5 10}
+integrity_check trans-2.11
+
+# Check the locking behavior
+#
+do_test trans-3.1 {
+ execsql {
+ BEGIN;
+ SELECT a FROM one ORDER BY a;
+ }
+} {1 2 3}
+do_test trans-3.2 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {1 {database is locked}}
+do_test trans-3.3 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {1 {database is locked}}
+do_test trans-3.4 {
+ set v [catch {execsql {
+ INSERT INTO one VALUES(4,'four');
+ }} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-3.5 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {1 {database is locked}}
+do_test trans-3.6 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {1 {database is locked}}
+do_test trans-3.7 {
+ set v [catch {execsql {
+ INSERT INTO two VALUES(4,'IV');
+ }} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-3.8 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {1 {database is locked}}
+do_test trans-3.9 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {1 {database is locked}}
+do_test trans-3.10 {
+ execsql {END TRANSACTION}
+} {}
+do_test trans-3.11 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {0 {1 4 5 10}}
+do_test trans-3.12 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {0 {1 2 3 4}}
+do_test trans-3.13 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } db} msg]
+ lappend v $msg
+} {0 {1 4 5 10}}
+do_test trans-3.14 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } db} msg]
+ lappend v $msg
+} {0 {1 2 3 4}}
+integrity_check trans-3.15
+
+do_test trans-4.1 {
+ set v [catch {execsql {
+ COMMIT;
+ } db} msg]
+ lappend v $msg
+} {1 {cannot commit - no transaction is active}}
+do_test trans-4.2 {
+ set v [catch {execsql {
+ ROLLBACK;
+ } db} msg]
+ lappend v $msg
+} {1 {cannot rollback - no transaction is active}}
+do_test trans-4.3 {
+ set v [catch {execsql {
+ BEGIN TRANSACTION;
+ SELECT a FROM two ORDER BY a;
+ } db} msg]
+ lappend v $msg
+} {0 {1 4 5 10}}
+do_test trans-4.4 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {1 {database is locked}}
+do_test trans-4.5 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {1 {database is locked}}
+do_test trans-4.6 {
+ set v [catch {execsql {
+ BEGIN TRANSACTION;
+ SELECT a FROM one ORDER BY a;
+ } db} msg]
+ lappend v $msg
+} {1 {cannot start a transaction within a transaction}}
+do_test trans-4.7 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {1 {database is locked}}
+do_test trans-4.8 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {1 {database is locked}}
+do_test trans-4.9 {
+ set v [catch {execsql {
+ END TRANSACTION;
+ SELECT a FROM two ORDER BY a;
+ } db} msg]
+ lappend v $msg
+} {0 {1 4 5 10}}
+do_test trans-4.10 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {0 {1 4 5 10}}
+do_test trans-4.11 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {0 {1 2 3 4}}
+integrity_check trans-4.12
+do_test trans-4.98 {
+ altdb close
+ execsql {
+ DROP TABLE one;
+ DROP TABLE two;
+ }
+} {}
+integrity_check trans-4.99
+
+# Check out the commit/rollback behavior of the database
+#
+do_test trans-5.1 {
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
+} {}
+do_test trans-5.2 {
+ execsql {BEGIN TRANSACTION}
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
+} {}
+do_test trans-5.3 {
+ execsql {CREATE TABLE one(a text, b int)}
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
+} {one}
+do_test trans-5.4 {
+ execsql {SELECT a,b FROM one ORDER BY b}
+} {}
+do_test trans-5.5 {
+ execsql {INSERT INTO one(a,b) VALUES('hello', 1)}
+ execsql {SELECT a,b FROM one ORDER BY b}
+} {hello 1}
+do_test trans-5.6 {
+ execsql {ROLLBACK}
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
+} {}
+do_test trans-5.7 {
+ set v [catch {
+ execsql {SELECT a,b FROM one ORDER BY b}
+ } msg]
+ lappend v $msg
+} {1 {no such table: one}}
+
+# Test commits and rollbacks of table CREATE TABLEs, CREATE INDEXs
+# DROP TABLEs and DROP INDEXs
+#
+do_test trans-5.8 {
+ execsql {
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name
+ }
+} {}
+do_test trans-5.9 {
+ execsql {
+ BEGIN TRANSACTION;
+ CREATE TABLE t1(a int, b int, c int);
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {t1}
+do_test trans-5.10 {
+ execsql {
+ CREATE INDEX i1 ON t1(a);
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i1 t1}
+do_test trans-5.11 {
+ execsql {
+ COMMIT;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i1 t1}
+do_test trans-5.12 {
+ execsql {
+ BEGIN TRANSACTION;
+ CREATE TABLE t2(a int, b int, c int);
+ CREATE INDEX i2a ON t2(a);
+ CREATE INDEX i2b ON t2(b);
+ DROP TABLE t1;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i2a i2b t2}
+do_test trans-5.13 {
+ execsql {
+ ROLLBACK;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i1 t1}
+do_test trans-5.14 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {t1}
+do_test trans-5.15 {
+ execsql {
+ ROLLBACK;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i1 t1}
+do_test trans-5.16 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ CREATE TABLE t2(x int, y int, z int);
+ CREATE INDEX i2x ON t2(x);
+ CREATE INDEX i2y ON t2(y);
+ INSERT INTO t2 VALUES(1,2,3);
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i2x i2y t1 t2}
+do_test trans-5.17 {
+ execsql {
+ COMMIT;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i2x i2y t1 t2}
+do_test trans-5.18 {
+ execsql {
+ SELECT * FROM t2;
+ }
+} {1 2 3}
+do_test trans-5.19 {
+ execsql {
+ SELECT x FROM t2 WHERE y=2;
+ }
+} {1}
+do_test trans-5.20 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ DROP TABLE t2;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {}
+do_test trans-5.21 {
+ set r [catch {execsql {
+ SELECT * FROM t2
+ }} msg]
+ lappend r $msg
+} {1 {no such table: t2}}
+do_test trans-5.22 {
+ execsql {
+ ROLLBACK;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i2x i2y t1 t2}
+do_test trans-5.23 {
+ execsql {
+ SELECT * FROM t2;
+ }
+} {1 2 3}
+integrity_check trans-5.23
+
+
+# Try to DROP and CREATE tables and indices with the same name
+# within a transaction. Make sure ROLLBACK works.
+#
+do_test trans-6.1 {
+ execsql2 {
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(p,q,r);
+ ROLLBACK;
+ SELECT * FROM t1;
+ }
+} {a 1 b 2 c 3}
+do_test trans-6.2 {
+ execsql2 {
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(p,q,r);
+ COMMIT;
+ SELECT * FROM t1;
+ }
+} {}
+do_test trans-6.3 {
+ execsql2 {
+ INSERT INTO t1 VALUES(1,2,3);
+ SELECT * FROM t1;
+ }
+} {p 1 q 2 r 3}
+do_test trans-6.4 {
+ execsql2 {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(a,b,c);
+ INSERT INTO t1 VALUES(4,5,6);
+ SELECT * FROM t1;
+ DROP TABLE t1;
+ }
+} {a 4 b 5 c 6}
+do_test trans-6.5 {
+ execsql2 {
+ ROLLBACK;
+ SELECT * FROM t1;
+ }
+} {p 1 q 2 r 3}
+do_test trans-6.6 {
+ execsql2 {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(a,b,c);
+ INSERT INTO t1 VALUES(4,5,6);
+ SELECT * FROM t1;
+ DROP TABLE t1;
+ }
+} {a 4 b 5 c 6}
+do_test trans-6.7 {
+ catchsql {
+ COMMIT;
+ SELECT * FROM t1;
+ }
+} {1 {no such table: t1}}
+
+# Repeat on a table with an automatically generated index.
+#
+do_test trans-6.10 {
+ execsql2 {
+ CREATE TABLE t1(a unique,b,c);
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(p unique,q,r);
+ ROLLBACK;
+ SELECT * FROM t1;
+ }
+} {a 1 b 2 c 3}
+do_test trans-6.11 {
+ execsql2 {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(p unique,q,r);
+ COMMIT;
+ SELECT * FROM t1;
+ }
+} {}
+do_test trans-6.12 {
+ execsql2 {
+ INSERT INTO t1 VALUES(1,2,3);
+ SELECT * FROM t1;
+ }
+} {p 1 q 2 r 3}
+do_test trans-6.13 {
+ execsql2 {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(a unique,b,c);
+ INSERT INTO t1 VALUES(4,5,6);
+ SELECT * FROM t1;
+ DROP TABLE t1;
+ }
+} {a 4 b 5 c 6}
+do_test trans-6.14 {
+ execsql2 {
+ ROLLBACK;
+ SELECT * FROM t1;
+ }
+} {p 1 q 2 r 3}
+do_test trans-6.15 {
+ execsql2 {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(a unique,b,c);
+ INSERT INTO t1 VALUES(4,5,6);
+ SELECT * FROM t1;
+ DROP TABLE t1;
+ }
+} {a 4 b 5 c 6}
+do_test trans-6.16 {
+ catchsql {
+ COMMIT;
+ SELECT * FROM t1;
+ }
+} {1 {no such table: t1}}
+
+do_test trans-6.20 {
+ execsql {
+ CREATE TABLE t1(a integer primary key,b,c);
+ INSERT INTO t1 VALUES(1,-2,-3);
+ INSERT INTO t1 VALUES(4,-5,-6);
+ SELECT * FROM t1;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.21 {
+ execsql {
+ CREATE INDEX i1 ON t1(b);
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.22 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ SELECT * FROM t1 WHERE b<1;
+ ROLLBACK;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.23 {
+ execsql {
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.24 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ ROLLBACK;
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+
+do_test trans-6.25 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ CREATE INDEX i1 ON t1(c);
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.26 {
+ execsql {
+ SELECT * FROM t1 WHERE c<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.27 {
+ execsql {
+ ROLLBACK;
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.28 {
+ execsql {
+ SELECT * FROM t1 WHERE c<1;
+ }
+} {1 -2 -3 4 -5 -6}
+
+# The following repeats steps 6.20 through 6.28, but puts a "unique"
+# constraint the first field of the table in order to generate an
+# automatic index.
+#
+do_test trans-6.30 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(a int unique,b,c);
+ COMMIT;
+ INSERT INTO t1 VALUES(1,-2,-3);
+ INSERT INTO t1 VALUES(4,-5,-6);
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.31 {
+ execsql {
+ CREATE INDEX i1 ON t1(b);
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.32 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ SELECT * FROM t1 WHERE b<1;
+ ROLLBACK;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.33 {
+ execsql {
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.34 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ ROLLBACK;
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+
+do_test trans-6.35 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ CREATE INDEX i1 ON t1(c);
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.36 {
+ execsql {
+ SELECT * FROM t1 WHERE c<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.37 {
+ execsql {
+ DROP INDEX i1;
+ SELECT * FROM t1 WHERE c<1;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.38 {
+ execsql {
+ ROLLBACK;
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.39 {
+ execsql {
+ SELECT * FROM t1 WHERE c<1;
+ }
+} {1 -2 -3 4 -5 -6}
+integrity_check trans-6.40
+
+# Test to make sure rollback restores the database back to its original
+# state.
+#
+do_test trans-7.1 {
+ execsql {BEGIN}
+ for {set i 0} {$i<1000} {incr i} {
+ set r1 [expr {rand()}]
+ set r2 [expr {rand()}]
+ set r3 [expr {rand()}]
+ execsql "INSERT INTO t2 VALUES($r1,$r2,$r3)"
+ }
+ execsql {COMMIT}
+ set ::checksum [execsql {SELECT md5sum(x,y,z) FROM t2}]
+ set ::checksum2 [
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+ ]
+ execsql {SELECT count(*) FROM t2}
+} {1001}
+do_test trans-7.2 {
+ execsql {SELECT md5sum(x,y,z) FROM t2}
+} $checksum
+do_test trans-7.2.1 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+do_test trans-7.3 {
+ execsql {
+ BEGIN;
+ DELETE FROM t2;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.4 {
+ execsql {
+ BEGIN;
+ INSERT INTO t2 SELECT * FROM t2;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.5 {
+ execsql {
+ BEGIN;
+ DELETE FROM t2;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.6 {
+ execsql {
+ BEGIN;
+ INSERT INTO t2 SELECT * FROM t2;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.7 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t3 AS SELECT * FROM t2;
+ INSERT INTO t2 SELECT * FROM t3;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.8 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+do_test trans-7.9 {
+ execsql {
+ BEGIN;
+ CREATE TEMP TABLE t3 AS SELECT * FROM t2;
+ INSERT INTO t2 SELECT * FROM t3;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.10 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+do_test trans-7.11 {
+ execsql {
+ BEGIN;
+ CREATE TEMP TABLE t3 AS SELECT * FROM t2;
+ INSERT INTO t2 SELECT * FROM t3;
+ DROP INDEX i2x;
+ DROP INDEX i2y;
+ CREATE INDEX i3a ON t3(x);
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.12 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+do_test trans-7.13 {
+ execsql {
+ BEGIN;
+ DROP TABLE t2;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.14 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+integrity_check trans-7.15
+
+# Arrange for another process to begin modifying the database but abort
+# and die in the middle of the modification. Then have this process read
+# the database. This process should detect the journal file and roll it
+# back. Verify that this happens correctly.
+#
+set fd [open test.tcl w]
+puts $fd {
+ sqlite db test.db
+ db eval {
+ PRAGMA default_cache_size=20;
+ BEGIN;
+ CREATE TABLE t3 AS SELECT * FROM t2;
+ DELETE FROM t2;
+ }
+ sqlite_abort
+}
+close $fd
+do_test trans-8.1 {
+ catch {exec [info nameofexec] test.tcl}
+ execsql {SELECT md5sum(x,y,z) FROM t2}
+} $checksum
+do_test trans-8.2 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+integrity_check trans-8.3
+
+# In the following sequence of tests, compute the MD5 sum of the content
+# of a table, make lots of modifications to that table, then do a rollback.
+# Verify that after the rollback, the MD5 checksum is unchanged.
+#
+do_test trans-9.1 {
+ execsql {
+ PRAGMA default_cache_size=10;
+ }
+ db close
+ sqlite db test.db
+ execsql {
+ BEGIN;
+ CREATE TABLE t3(x TEXT);
+ INSERT INTO t3 VALUES(randstr(10,400));
+ INSERT INTO t3 VALUES(randstr(10,400));
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ COMMIT;
+ SELECT count(*) FROM t3;
+ }
+} {1024}
+
+# The following procedure computes a "signature" for table "t3". If
+# T3 changes in any way, the signature should change.
+#
+# This is used to test ROLLBACK. We gather a signature for t3, then
+# make lots of changes to t3, then rollback and take another signature.
+# The two signatures should be the same.
+#
+proc signature {} {
+ return [db eval {SELECT count(*), md5sum(x) FROM t3}]
+}
+
+# Repeat the following group of tests 20 times for quick testing and
+# 40 times for full testing. Each iteration of the test makes table
+# t3 a little larger, and thus takes a little longer, so doing 40 tests
+# is more than 2.0 times slower than doing 20 tests. Considerably more.
+#
+if {[info exists ISQUICK]} {
+ set limit 20
+} else {
+ set limit 40
+}
+
+# Do rollbacks. Make sure the signature does not change.
+#
+for {set i 2} {$i<=$limit} {incr i} {
+ set ::sig [signature]
+ set cnt [lindex $::sig 0]
+ set ::journal_format [expr {($i%3)+1}]
+ if {$i%2==0} {
+ execsql {PRAGMA synchronous=FULL}
+ } else {
+ execsql {PRAGMA synchronous=NORMAL}
+ }
+ do_test trans-9.$i.1-$cnt {
+ execsql {
+ BEGIN;
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ ROLLBACK;
+ }
+ signature
+ } $sig
+ do_test trans-9.$i.2-$cnt {
+ execsql {
+ BEGIN;
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ ROLLBACK;
+ }
+ signature
+ } $sig
+ if {$i<$limit} {
+ do_test trans-9.$i.9-$cnt {
+ execsql {
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0;
+ }
+ } {}
+ }
+ set ::pager_old_format 0
+}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/trigger1.test b/usr/src/lib/libsqlite/test/trigger1.test
new file mode 100644
index 0000000000..44e1091597
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/trigger1.test
@@ -0,0 +1,522 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 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 tests creating and dropping triggers, and interaction thereof
+# with the database COMMIT/ROLLBACK logic.
+#
+# 1. CREATE and DROP TRIGGER tests
+# trig-1.1: Error if table does not exist
+# trig-1.2: Error if trigger already exists
+# trig-1.3: Created triggers are deleted if the transaction is rolled back
+# trig-1.4: DROP TRIGGER removes trigger
+# trig-1.5: Dropped triggers are restored if the transaction is rolled back
+# trig-1.6: Error if dropped trigger doesn't exist
+# trig-1.7: Dropping the table automatically drops all triggers
+# trig-1.8: A trigger created on a TEMP table is not inserted into sqlite_master
+# trig-1.9: Ensure that we cannot create a trigger on sqlite_master
+# trig-1.10:
+# trig-1.11:
+# trig-1.12: Ensure that INSTEAD OF triggers cannot be created on tables
+# trig-1.13: Ensure that AFTER triggers cannot be created on views
+# trig-1.14: Ensure that BEFORE triggers cannot be created on views
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test trigger1-1.1.2 {
+ catchsql {
+ CREATE TRIGGER trig UPDATE ON no_such_table BEGIN
+ SELECT * from sqlite_master;
+ END;
+ }
+} {1 {no such table: no_such_table}}
+do_test trigger1-1.1.2 {
+ catchsql {
+ CREATE TEMP TRIGGER trig UPDATE ON no_such_table BEGIN
+ SELECT * from sqlite_master;
+ END;
+ }
+} {1 {no such table: no_such_table}}
+
+execsql {
+ CREATE TABLE t1(a);
+}
+execsql {
+ CREATE TRIGGER tr1 INSERT ON t1 BEGIN
+ INSERT INTO t1 values(1);
+ END;
+}
+do_test trigger1-1.2 {
+ catchsql {
+ CREATE TRIGGER tr1 DELETE ON t1 BEGIN
+ SELECT * FROM sqlite_master;
+ END
+ }
+} {1 {trigger tr1 already exists}}
+
+do_test trigger1-1.3 {
+ catchsql {
+ BEGIN;
+ CREATE TRIGGER tr2 INSERT ON t1 BEGIN
+ SELECT * from sqlite_master; END;
+ ROLLBACK;
+ CREATE TRIGGER tr2 INSERT ON t1 BEGIN
+ SELECT * from sqlite_master; END;
+ }
+} {0 {}}
+
+do_test trigger1-1.4 {
+ catchsql {
+ DROP TRIGGER tr1;
+ CREATE TRIGGER tr1 DELETE ON t1 BEGIN
+ SELECT * FROM sqlite_master;
+ END
+ }
+} {0 {}}
+
+do_test trigger1-1.5 {
+ execsql {
+ BEGIN;
+ DROP TRIGGER tr2;
+ ROLLBACK;
+ DROP TRIGGER tr2;
+ }
+} {}
+
+do_test trigger1-1.6 {
+ catchsql {
+ DROP TRIGGER biggles;
+ }
+} {1 {no such trigger: biggles}}
+
+do_test trigger1-1.7 {
+ catchsql {
+ DROP TABLE t1;
+ DROP TRIGGER tr1;
+ }
+} {1 {no such trigger: tr1}}
+
+execsql {
+ CREATE TEMP TABLE temp_table(a);
+}
+do_test trigger1-1.8 {
+ execsql {
+ CREATE TRIGGER temp_trig UPDATE ON temp_table BEGIN
+ SELECT * from sqlite_master;
+ END;
+ SELECT count(*) FROM sqlite_master WHERE name = 'temp_trig';
+ }
+} {0}
+
+do_test trigger1-1.9 {
+ catchsql {
+ CREATE TRIGGER tr1 AFTER UPDATE ON sqlite_master BEGIN
+ SELECT * FROM sqlite_master;
+ END;
+ }
+} {1 {cannot create trigger on system table}}
+
+# Check to make sure that a DELETE statement within the body of
+# a trigger does not mess up the DELETE that caused the trigger to
+# run in the first place.
+#
+do_test trigger1-1.10 {
+ execsql {
+ create table t1(a,b);
+ insert into t1 values(1,'a');
+ insert into t1 values(2,'b');
+ insert into t1 values(3,'c');
+ insert into t1 values(4,'d');
+ create trigger r1 after delete on t1 for each row begin
+ delete from t1 WHERE a=old.a+2;
+ end;
+ delete from t1 where a in (1,3);
+ select * from t1;
+ drop table t1;
+ }
+} {2 b 4 d}
+do_test trigger1-1.11 {
+ execsql {
+ create table t1(a,b);
+ insert into t1 values(1,'a');
+ insert into t1 values(2,'b');
+ insert into t1 values(3,'c');
+ insert into t1 values(4,'d');
+ create trigger r1 after update on t1 for each row begin
+ delete from t1 WHERE a=old.a+2;
+ end;
+ update t1 set b='x-' || b where a in (1,3);
+ select * from t1;
+ drop table t1;
+ }
+} {1 x-a 2 b 4 d}
+
+# Ensure that we cannot create INSTEAD OF triggers on tables
+do_test trigger1-1.12 {
+ catchsql {
+ create table t1(a,b);
+ create trigger t1t instead of update on t1 for each row begin
+ delete from t1 WHERE a=old.a+2;
+ end;
+ }
+} {1 {cannot create INSTEAD OF trigger on table: t1}}
+# Ensure that we cannot create BEFORE triggers on views
+do_test trigger1-1.13 {
+ catchsql {
+ create view v1 as select * from t1;
+ create trigger v1t before update on v1 for each row begin
+ delete from t1 WHERE a=old.a+2;
+ end;
+ }
+} {1 {cannot create BEFORE trigger on view: v1}}
+# Ensure that we cannot create AFTER triggers on views
+do_test trigger1-1.14 {
+ catchsql {
+ drop view v1;
+ create view v1 as select * from t1;
+ create trigger v1t AFTER update on v1 for each row begin
+ delete from t1 WHERE a=old.a+2;
+ end;
+ }
+} {1 {cannot create AFTER trigger on view: v1}}
+
+# Check for memory leaks in the trigger parser
+#
+do_test trigger1-2.1 {
+ catchsql {
+ CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
+ SELECT * FROM; -- Syntax error
+ END;
+ }
+} {1 {near ";": syntax error}}
+do_test trigger1-2.2 {
+ catchsql {
+ CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
+ SELECT * FROM t1;
+ SELECT * FROM; -- Syntax error
+ END;
+ }
+} {1 {near ";": syntax error}}
+
+# Create a trigger that refers to a table that might not exist.
+#
+do_test trigger1-3.1 {
+ execsql {
+ CREATE TEMP TABLE t2(x,y);
+ }
+ catchsql {
+ CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO t2 VALUES(NEW.a,NEW.b);
+ END;
+ }
+} {0 {}}
+do_test trigger-3.2 {
+ catchsql {
+ INSERT INTO t1 VALUES(1,2);
+ SELECT * FROM t2;
+ }
+} {1 {no such table: main.t2}}
+do_test trigger-3.3 {
+ db close
+ set rc [catch {sqlite db test.db} err]
+ if {$rc} {lappend rc $err}
+ set rc
+} {0}
+do_test trigger-3.4 {
+ catchsql {
+ INSERT INTO t1 VALUES(1,2);
+ SELECT * FROM t2;
+ }
+} {1 {no such table: main.t2}}
+do_test trigger-3.5 {
+ catchsql {
+ CREATE TEMP TABLE t2(x,y);
+ INSERT INTO t1 VALUES(1,2);
+ SELECT * FROM t2;
+ }
+} {1 {no such table: main.t2}}
+do_test trigger-3.6 {
+ catchsql {
+ DROP TRIGGER r1;
+ CREATE TEMP TRIGGER r1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO t2 VALUES(NEW.a,NEW.b);
+ END;
+ INSERT INTO t1 VALUES(1,2);
+ SELECT * FROM t2;
+ }
+} {0 {1 2}}
+do_test trigger-3.7 {
+ execsql {
+ DROP TABLE t2;
+ CREATE TABLE t2(x,y);
+ SELECT * FROM t2;
+ }
+} {}
+do_test trigger-3.8 {
+ execsql {
+ INSERT INTO t1 VALUES(3,4);
+ SELECT * FROM t1 UNION ALL SELECT * FROM t2;
+ }
+} {1 2 3 4 3 4}
+do_test trigger-3.9 {
+ db close
+ sqlite db test.db
+ execsql {
+ INSERT INTO t1 VALUES(5,6);
+ SELECT * FROM t1 UNION ALL SELECT * FROM t2;
+ }
+} {1 2 3 4 5 6 3 4}
+
+do_test trigger-4.1 {
+ execsql {
+ CREATE TEMP TRIGGER r1 BEFORE INSERT ON t1 BEGIN
+ INSERT INTO t2 VALUES(NEW.a,NEW.b);
+ END;
+ INSERT INTO t1 VALUES(7,8);
+ SELECT * FROM t2;
+ }
+} {3 4 7 8}
+do_test trigger-4.2 {
+ sqlite db2 test.db
+ execsql {
+ INSERT INTO t1 VALUES(9,10);
+ } db2;
+ db2 close
+ execsql {
+ SELECT * FROM t2;
+ }
+} {3 4 7 8}
+do_test trigger-4.3 {
+ execsql {
+ DROP TABLE t1;
+ SELECT * FROM t2;
+ };
+} {3 4 7 8}
+do_test trigger-4.4 {
+ db close
+ sqlite db test.db
+ execsql {
+ SELECT * FROM t2;
+ };
+} {3 4 7 8}
+
+integrity_check trigger-5.1
+
+# Create a trigger with the same name as a table. Make sure the
+# trigger works. Then drop the trigger. Make sure the table is
+# still there.
+#
+do_test trigger-6.1 {
+ execsql {SELECT type, name FROM sqlite_master}
+} {view v1 table t2}
+do_test trigger-6.2 {
+ execsql {
+ CREATE TRIGGER t2 BEFORE DELETE ON t2 BEGIN
+ SELECT RAISE(ABORT,'deletes are not allows');
+ END;
+ SELECT type, name FROM sqlite_master;
+ }
+} {view v1 table t2 trigger t2}
+do_test trigger-6.3 {
+ catchsql {DELETE FROM t2}
+} {1 {deletes are not allows}}
+do_test trigger-6.4 {
+ execsql {SELECT * FROM t2}
+} {3 4 7 8}
+do_test trigger-6.5 {
+ db close
+ sqlite db test.db
+ execsql {SELECT type, name FROM sqlite_master}
+} {view v1 table t2 trigger t2}
+do_test trigger-6.6 {
+ execsql {
+ DROP TRIGGER t2;
+ SELECT type, name FROM sqlite_master;
+ }
+} {view v1 table t2}
+do_test trigger-6.7 {
+ execsql {SELECT * FROM t2}
+} {3 4 7 8}
+do_test trigger-6.8 {
+ db close
+ sqlite db test.db
+ execsql {SELECT * FROM t2}
+} {3 4 7 8}
+
+integrity_check trigger-7.1
+
+# Check to make sure the name of a trigger can be quoted so that keywords
+# can be used as trigger names. Ticket #468
+#
+do_test trigger-8.1 {
+ execsql {
+ CREATE TRIGGER 'trigger' AFTER INSERT ON t2 BEGIN SELECT 1; END;
+ SELECT name FROM sqlite_master WHERE type='trigger';
+ }
+} {trigger}
+do_test trigger-8.2 {
+ execsql {
+ DROP TRIGGER 'trigger';
+ SELECT name FROM sqlite_master WHERE type='trigger';
+ }
+} {}
+do_test trigger-8.3 {
+ execsql {
+ CREATE TRIGGER "trigger" AFTER INSERT ON t2 BEGIN SELECT 1; END;
+ SELECT name FROM sqlite_master WHERE type='trigger';
+ }
+} {trigger}
+do_test trigger-8.4 {
+ execsql {
+ DROP TRIGGER "trigger";
+ SELECT name FROM sqlite_master WHERE type='trigger';
+ }
+} {}
+do_test trigger-8.5 {
+ execsql {
+ CREATE TRIGGER [trigger] AFTER INSERT ON t2 BEGIN SELECT 1; END;
+ SELECT name FROM sqlite_master WHERE type='trigger';
+ }
+} {trigger}
+do_test trigger-8.6 {
+ execsql {
+ DROP TRIGGER [trigger];
+ SELECT name FROM sqlite_master WHERE type='trigger';
+ }
+} {}
+
+# Make sure REPLACE works inside of triggers.
+#
+do_test trigger-9.1 {
+ execsql {
+ CREATE TABLE t3(a,b);
+ CREATE TABLE t4(x UNIQUE, b);
+ CREATE TRIGGER r34 AFTER INSERT ON t3 BEGIN
+ REPLACE INTO t4 VALUES(new.a,new.b);
+ END;
+ INSERT INTO t3 VALUES(1,2);
+ SELECT * FROM t3 UNION ALL SELECT 99, 99 UNION ALL SELECT * FROM t4;
+ }
+} {1 2 99 99 1 2}
+do_test trigger-9.2 {
+ execsql {
+ INSERT INTO t3 VALUES(1,3);
+ SELECT * FROM t3 UNION ALL SELECT 99, 99 UNION ALL SELECT * FROM t4;
+ }
+} {1 2 1 3 99 99 1 3}
+
+execsql {
+ DROP TABLE t2;
+ DROP TABLE t3;
+ DROP TABLE t4;
+}
+
+# Ticket #764. At one stage TEMP triggers would fail to re-install when the
+# schema was reloaded. The following tests ensure that TEMP triggers are
+# correctly re-installed.
+#
+# Also verify that references within trigger programs are resolved at
+# statement compile time, not trigger installation time. This means, for
+# example, that you can drop and re-create tables referenced by triggers.
+do_test trigger-10.0 {
+ file delete -force test2.db
+ file delete -force test2.db-journal
+ sqlite db2 test2.db
+ execsql {CREATE TABLE t3(a, b, c);} db2
+ db2 close
+ execsql {
+ ATTACH 'test2.db' AS aux;
+ }
+} {}
+do_test trigger-10.1 {
+ execsql {
+ CREATE TABLE t1(a, b, c);
+ CREATE temp TABLE t2(a, b, c);
+ CREATE TABLE insert_log(db, a, b, c);
+ }
+} {}
+do_test trigger-10.2 {
+ execsql {
+ CREATE TEMP TRIGGER trig1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO insert_log VALUES('main', new.a, new.b, new.c);
+ END;
+ CREATE TEMP TRIGGER trig2 AFTER INSERT ON t2 BEGIN
+ INSERT INTO insert_log VALUES('temp', new.a, new.b, new.c);
+ END;
+ CREATE TEMP TRIGGER trig3 AFTER INSERT ON t3 BEGIN
+ INSERT INTO insert_log VALUES('aux', new.a, new.b, new.c);
+ END;
+ }
+} {}
+do_test trigger-10.3 {
+ execsql {
+ INSERT INTO t1 VALUES(1, 2, 3);
+ INSERT INTO t2 VALUES(4, 5, 6);
+ INSERT INTO t3 VALUES(7, 8, 9);
+ }
+} {}
+do_test trigger-10.4 {
+ execsql {
+ SELECT * FROM insert_log;
+ }
+} {main 1 2 3 temp 4 5 6 aux 7 8 9}
+do_test trigger-10.5 {
+ execsql {
+ BEGIN;
+ INSERT INTO t1 VALUES(1, 2, 3);
+ INSERT INTO t2 VALUES(4, 5, 6);
+ INSERT INTO t3 VALUES(7, 8, 9);
+ ROLLBACK;
+ }
+} {}
+do_test trigger-10.6 {
+ execsql {
+ SELECT * FROM insert_log;
+ }
+} {main 1 2 3 temp 4 5 6 aux 7 8 9}
+do_test trigger-10.7 {
+ execsql {
+ DELETE FROM insert_log;
+ INSERT INTO t1 VALUES(11, 12, 13);
+ INSERT INTO t2 VALUES(14, 15, 16);
+ INSERT INTO t3 VALUES(17, 18, 19);
+ }
+} {}
+do_test trigger-10.8 {
+ execsql {
+ SELECT * FROM insert_log;
+ }
+} {main 11 12 13 temp 14 15 16 aux 17 18 19}
+do_test trigger-10.8 {
+# Drop and re-create the insert_log table in a different database. Note
+# that we can change the column names because the trigger programs don't
+# use them explicitly.
+ execsql {
+ DROP TABLE insert_log;
+ CREATE temp TABLE insert_log(db, d, e, f);
+ }
+} {}
+do_test trigger-10.10 {
+ execsql {
+ INSERT INTO t1 VALUES(21, 22, 23);
+ INSERT INTO t2 VALUES(24, 25, 26);
+ INSERT INTO t3 VALUES(27, 28, 29);
+ }
+} {}
+do_test trigger-10.11 {
+ execsql {
+ SELECT * FROM insert_log;
+ }
+} {main 21 22 23 temp 24 25 26 aux 27 28 29}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/trigger2.test b/usr/src/lib/libsqlite/test/trigger2.test
new file mode 100644
index 0000000000..7567f01fcd
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/trigger2.test
@@ -0,0 +1,721 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 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.
+#
+#***********************************************************************
+#
+# Regression testing of FOR EACH ROW table triggers
+#
+# 1. Trigger execution order tests.
+# These tests ensure that BEFORE and AFTER triggers are fired at the correct
+# times relative to each other and the triggering statement.
+#
+# trigger2-1.1.*: ON UPDATE trigger execution model.
+# trigger2-1.2.*: DELETE trigger execution model.
+# trigger2-1.3.*: INSERT trigger execution model.
+#
+# 2. Trigger program execution tests.
+# These tests ensure that trigger programs execute correctly (ie. that a
+# trigger program can correctly execute INSERT, UPDATE, DELETE * SELECT
+# statements, and combinations thereof).
+#
+# 3. Selective trigger execution
+# This tests that conditional triggers (ie. UPDATE OF triggers and triggers
+# with WHEN clauses) are fired only fired when they are supposed to be.
+#
+# trigger2-3.1: UPDATE OF triggers
+# trigger2-3.2: WHEN clause
+#
+# 4. Cascaded trigger execution
+# Tests that trigger-programs may cause other triggers to fire. Also that a
+# trigger-program is never executed recursively.
+#
+# trigger2-4.1: Trivial cascading trigger
+# trigger2-4.2: Trivial recursive trigger handling
+#
+# 5. Count changes behaviour.
+# Verify that rows altered by triggers are not included in the return value
+# of the "count changes" interface.
+#
+# 6. ON CONFLICT clause handling
+# trigger2-6.1[a-f]: INSERT statements
+# trigger2-6.2[a-f]: UPDATE statements
+#
+# 7. Triggers on views fire correctly.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# 1.
+set ii 0
+foreach tbl_defn {
+ {CREATE TEMP TABLE tbl (a, b);}
+ {CREATE TABLE tbl (a, b);}
+ {CREATE TABLE tbl (a INTEGER PRIMARY KEY, b);}
+ {CREATE TEMPORARY TABLE tbl (a INTEGER PRIMARY KEY, b);}
+ {CREATE TABLE tbl (a, b PRIMARY KEY);}
+ {CREATE TABLE tbl (a, b); CREATE INDEX tbl_idx ON tbl(b);}
+ {CREATE TEMP TABLE tbl (a, b); CREATE INDEX tbl_idx ON tbl(b);}
+} {
+ incr ii
+ catchsql { DROP INDEX tbl_idx; }
+ catchsql {
+ DROP TABLE rlog;
+ DROP TABLE clog;
+ DROP TABLE tbl;
+ DROP TABLE other_tbl;
+ }
+
+ execsql $tbl_defn
+
+ execsql {
+ INSERT INTO tbl VALUES(1, 2);
+ INSERT INTO tbl VALUES(3, 4);
+
+ CREATE TABLE rlog (idx, old_a, old_b, db_sum_a, db_sum_b, new_a, new_b);
+ CREATE TABLE clog (idx, old_a, old_b, db_sum_a, db_sum_b, new_a, new_b);
+
+ CREATE TRIGGER before_update_row BEFORE UPDATE ON tbl FOR EACH ROW
+ BEGIN
+ INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog),
+ old.a, old.b,
+ (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl),
+ new.a, new.b);
+ END;
+
+ CREATE TRIGGER after_update_row AFTER UPDATE ON tbl FOR EACH ROW
+ BEGIN
+ INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog),
+ old.a, old.b,
+ (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl),
+ new.a, new.b);
+ END;
+
+ CREATE TRIGGER conditional_update_row AFTER UPDATE ON tbl FOR EACH ROW
+ WHEN old.a = 1
+ BEGIN
+ INSERT INTO clog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM clog),
+ old.a, old.b,
+ (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl),
+ new.a, new.b);
+ END;
+ }
+
+ do_test trigger2-1.$ii.1 {
+ execsql {
+ UPDATE tbl SET a = a * 10, b = b * 10;
+ SELECT * FROM rlog ORDER BY idx;
+ SELECT * FROM clog ORDER BY idx;
+ }
+ } [list 1 1 2 4 6 10 20 \
+ 2 1 2 13 24 10 20 \
+ 3 3 4 13 24 30 40 \
+ 4 3 4 40 60 30 40 \
+ 1 1 2 13 24 10 20 ]
+
+ execsql {
+ DELETE FROM rlog;
+ DELETE FROM tbl;
+ INSERT INTO tbl VALUES (100, 100);
+ INSERT INTO tbl VALUES (300, 200);
+ CREATE TRIGGER delete_before_row BEFORE DELETE ON tbl FOR EACH ROW
+ BEGIN
+ INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog),
+ old.a, old.b,
+ (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl),
+ 0, 0);
+ END;
+
+ CREATE TRIGGER delete_after_row AFTER DELETE ON tbl FOR EACH ROW
+ BEGIN
+ INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog),
+ old.a, old.b,
+ (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl),
+ 0, 0);
+ END;
+ }
+ do_test trigger2-1.$ii.2 {
+ execsql {
+ DELETE FROM tbl;
+ SELECT * FROM rlog;
+ }
+ } [list 1 100 100 400 300 0 0 \
+ 2 100 100 300 200 0 0 \
+ 3 300 200 300 200 0 0 \
+ 4 300 200 0 0 0 0 ]
+
+ execsql {
+ DELETE FROM rlog;
+ CREATE TRIGGER insert_before_row BEFORE INSERT ON tbl FOR EACH ROW
+ BEGIN
+ INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog),
+ 0, 0,
+ (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl),
+ new.a, new.b);
+ END;
+
+ CREATE TRIGGER insert_after_row AFTER INSERT ON tbl FOR EACH ROW
+ BEGIN
+ INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog),
+ 0, 0,
+ (SELECT sum(a) FROM tbl), (SELECT sum(b) FROM tbl),
+ new.a, new.b);
+ END;
+ }
+ do_test trigger2-1.$ii.3 {
+ execsql {
+
+ CREATE TABLE other_tbl(a, b);
+ INSERT INTO other_tbl VALUES(1, 2);
+ INSERT INTO other_tbl VALUES(3, 4);
+ -- INSERT INTO tbl SELECT * FROM other_tbl;
+ INSERT INTO tbl VALUES(5, 6);
+ DROP TABLE other_tbl;
+
+ SELECT * FROM rlog;
+ }
+ } [list 1 0 0 0 0 5 6 \
+ 2 0 0 5 6 5 6 ]
+
+ do_test trigger2-1.$ii.4 {
+ execsql {
+ PRAGMA integrity_check;
+ }
+ } {ok}
+}
+catchsql {
+ DROP TABLE rlog;
+ DROP TABLE clog;
+ DROP TABLE tbl;
+ DROP TABLE other_tbl;
+}
+
+# 2.
+set ii 0
+foreach tr_program {
+ {UPDATE tbl SET b = old.b;}
+ {INSERT INTO log VALUES(new.c, 2, 3);}
+ {DELETE FROM log WHERE a = 1;}
+ {INSERT INTO tbl VALUES(500, new.b * 10, 700);
+ UPDATE tbl SET c = old.c;
+ DELETE FROM log;}
+ {INSERT INTO log select * from tbl;}
+} {
+ foreach test_varset [ list \
+ {
+ set statement {UPDATE tbl SET c = 10 WHERE a = 1;}
+ set prep {INSERT INTO tbl VALUES(1, 2, 3);}
+ set newC 10
+ set newB 2
+ set newA 1
+ set oldA 1
+ set oldB 2
+ set oldC 3
+ } \
+ {
+ set statement {DELETE FROM tbl WHERE a = 1;}
+ set prep {INSERT INTO tbl VALUES(1, 2, 3);}
+ set oldA 1
+ set oldB 2
+ set oldC 3
+ } \
+ {
+ set statement {INSERT INTO tbl VALUES(1, 2, 3);}
+ set newA 1
+ set newB 2
+ set newC 3
+ }
+ ] \
+ {
+ set statement {}
+ set prep {}
+ set newA {''}
+ set newB {''}
+ set newC {''}
+ set oldA {''}
+ set oldB {''}
+ set oldC {''}
+
+ incr ii
+
+ eval $test_varset
+
+ set statement_type [string range $statement 0 5]
+ set tr_program_fixed $tr_program
+ if {$statement_type == "DELETE"} {
+ regsub -all new\.a $tr_program_fixed {''} tr_program_fixed
+ regsub -all new\.b $tr_program_fixed {''} tr_program_fixed
+ regsub -all new\.c $tr_program_fixed {''} tr_program_fixed
+ }
+ if {$statement_type == "INSERT"} {
+ regsub -all old\.a $tr_program_fixed {''} tr_program_fixed
+ regsub -all old\.b $tr_program_fixed {''} tr_program_fixed
+ regsub -all old\.c $tr_program_fixed {''} tr_program_fixed
+ }
+
+
+ set tr_program_cooked $tr_program
+ regsub -all new\.a $tr_program_cooked $newA tr_program_cooked
+ regsub -all new\.b $tr_program_cooked $newB tr_program_cooked
+ regsub -all new\.c $tr_program_cooked $newC tr_program_cooked
+ regsub -all old\.a $tr_program_cooked $oldA tr_program_cooked
+ regsub -all old\.b $tr_program_cooked $oldB tr_program_cooked
+ regsub -all old\.c $tr_program_cooked $oldC tr_program_cooked
+
+ catchsql {
+ DROP TABLE tbl;
+ DROP TABLE log;
+ }
+
+ execsql {
+ CREATE TABLE tbl(a PRIMARY KEY, b, c);
+ CREATE TABLE log(a, b, c);
+ }
+
+ set query {SELECT * FROM tbl; SELECT * FROM log;}
+ set prep "$prep; INSERT INTO log VALUES(1, 2, 3);\
+ INSERT INTO log VALUES(10, 20, 30);"
+
+# Check execution of BEFORE programs:
+
+ set before_data [ execsql "$prep $tr_program_cooked $statement $query" ]
+
+ execsql "DELETE FROM tbl; DELETE FROM log; $prep";
+ execsql "CREATE TRIGGER the_trigger BEFORE [string range $statement 0 6]\
+ ON tbl BEGIN $tr_program_fixed END;"
+
+ do_test trigger2-2.$ii-before "execsql {$statement $query}" $before_data
+
+ execsql "DROP TRIGGER the_trigger;"
+ execsql "DELETE FROM tbl; DELETE FROM log;"
+
+# Check execution of AFTER programs
+ set after_data [ execsql "$prep $statement $tr_program_cooked $query" ]
+
+ execsql "DELETE FROM tbl; DELETE FROM log; $prep";
+ execsql "CREATE TRIGGER the_trigger AFTER [string range $statement 0 6]\
+ ON tbl BEGIN $tr_program_fixed END;"
+
+ do_test trigger2-2.$ii-after "execsql {$statement $query}" $after_data
+ execsql "DROP TRIGGER the_trigger;"
+
+ do_test trigger2-2.$ii-integrity {
+ execsql {
+ PRAGMA integrity_check;
+ }
+ } {ok}
+
+ }
+}
+catchsql {
+ DROP TABLE tbl;
+ DROP TABLE log;
+}
+
+# 3.
+
+# trigger2-3.1: UPDATE OF triggers
+execsql {
+ CREATE TABLE tbl (a, b, c, d);
+ CREATE TABLE log (a);
+ INSERT INTO log VALUES (0);
+ INSERT INTO tbl VALUES (0, 0, 0, 0);
+ INSERT INTO tbl VALUES (1, 0, 0, 0);
+ CREATE TRIGGER tbl_after_update_cd BEFORE UPDATE OF c, d ON tbl
+ BEGIN
+ UPDATE log SET a = a + 1;
+ END;
+}
+do_test trigger2-3.1 {
+ execsql {
+ UPDATE tbl SET b = 1, c = 10; -- 2
+ UPDATE tbl SET b = 10; -- 0
+ UPDATE tbl SET d = 4 WHERE a = 0; --1
+ UPDATE tbl SET a = 4, b = 10; --0
+ SELECT * FROM log;
+ }
+} {3}
+execsql {
+ DROP TABLE tbl;
+ DROP TABLE log;
+}
+
+# trigger2-3.2: WHEN clause
+set when_triggers [ list \
+ {t1 BEFORE INSERT ON tbl WHEN new.a > 20} \
+ {t2 BEFORE INSERT ON tbl WHEN (SELECT count(*) FROM tbl) = 0} ]
+
+execsql {
+ CREATE TABLE tbl (a, b, c, d);
+ CREATE TABLE log (a);
+ INSERT INTO log VALUES (0);
+}
+
+foreach trig $when_triggers {
+ execsql "CREATE TRIGGER $trig BEGIN UPDATE log set a = a + 1; END;"
+}
+
+do_test trigger2-3.2 {
+ execsql {
+
+ INSERT INTO tbl VALUES(0, 0, 0, 0); -- 1
+ SELECT * FROM log;
+ UPDATE log SET a = 0;
+
+ INSERT INTO tbl VALUES(0, 0, 0, 0); -- 0
+ SELECT * FROM log;
+ UPDATE log SET a = 0;
+
+ INSERT INTO tbl VALUES(200, 0, 0, 0); -- 1
+ SELECT * FROM log;
+ UPDATE log SET a = 0;
+ }
+} {1 0 1}
+execsql {
+ DROP TABLE tbl;
+ DROP TABLE log;
+}
+do_test trigger2-3.3 {
+ execsql {
+ PRAGMA integrity_check;
+ }
+} {ok}
+
+# Simple cascaded trigger
+execsql {
+ CREATE TABLE tblA(a, b);
+ CREATE TABLE tblB(a, b);
+ CREATE TABLE tblC(a, b);
+
+ CREATE TRIGGER tr1 BEFORE INSERT ON tblA BEGIN
+ INSERT INTO tblB values(new.a, new.b);
+ END;
+
+ CREATE TRIGGER tr2 BEFORE INSERT ON tblB BEGIN
+ INSERT INTO tblC values(new.a, new.b);
+ END;
+}
+do_test trigger2-4.1 {
+ execsql {
+ INSERT INTO tblA values(1, 2);
+ SELECT * FROM tblA;
+ SELECT * FROM tblB;
+ SELECT * FROM tblC;
+ }
+} {1 2 1 2 1 2}
+execsql {
+ DROP TABLE tblA;
+ DROP TABLE tblB;
+ DROP TABLE tblC;
+}
+
+# Simple recursive trigger
+execsql {
+ CREATE TABLE tbl(a, b, c);
+ CREATE TRIGGER tbl_trig BEFORE INSERT ON tbl
+ BEGIN
+ INSERT INTO tbl VALUES (new.a, new.b, new.c);
+ END;
+}
+do_test trigger2-4.2 {
+ execsql {
+ INSERT INTO tbl VALUES (1, 2, 3);
+ select * from tbl;
+ }
+} {1 2 3 1 2 3}
+execsql {
+ DROP TABLE tbl;
+}
+
+# 5.
+execsql {
+ CREATE TABLE tbl(a, b, c);
+ CREATE TRIGGER tbl_trig BEFORE INSERT ON tbl
+ BEGIN
+ INSERT INTO tbl VALUES (1, 2, 3);
+ INSERT INTO tbl VALUES (2, 2, 3);
+ UPDATE tbl set b = 10 WHERE a = 1;
+ DELETE FROM tbl WHERE a = 1;
+ DELETE FROM tbl;
+ END;
+}
+do_test trigger2-5 {
+ execsql {
+ INSERT INTO tbl VALUES(100, 200, 300);
+ }
+ db changes
+} {1}
+execsql {
+ DROP TABLE tbl;
+}
+
+# Handling of ON CONFLICT by INSERT statements inside triggers
+execsql {
+ CREATE TABLE tbl (a primary key, b, c);
+ CREATE TRIGGER ai_tbl AFTER INSERT ON tbl BEGIN
+ INSERT OR IGNORE INTO tbl values (new.a, 0, 0);
+ END;
+}
+do_test trigger2-6.1a {
+ execsql {
+ BEGIN;
+ INSERT INTO tbl values (1, 2, 3);
+ SELECT * from tbl;
+ }
+} {1 2 3}
+do_test trigger2-6.1b {
+ catchsql {
+ INSERT OR ABORT INTO tbl values (2, 2, 3);
+ }
+} {1 {column a is not unique}}
+do_test trigger2-6.1c {
+ execsql {
+ SELECT * from tbl;
+ }
+} {1 2 3}
+do_test trigger2-6.1d {
+ catchsql {
+ INSERT OR FAIL INTO tbl values (2, 2, 3);
+ }
+} {1 {column a is not unique}}
+do_test trigger2-6.1e {
+ execsql {
+ SELECT * from tbl;
+ }
+} {1 2 3 2 2 3}
+do_test trigger2-6.1f {
+ execsql {
+ INSERT OR REPLACE INTO tbl values (2, 2, 3);
+ SELECT * from tbl;
+ }
+} {1 2 3 2 0 0}
+do_test trigger2-6.1g {
+ catchsql {
+ INSERT OR ROLLBACK INTO tbl values (3, 2, 3);
+ }
+} {1 {column a is not unique}}
+do_test trigger2-6.1h {
+ execsql {
+ SELECT * from tbl;
+ }
+} {}
+execsql {DELETE FROM tbl}
+
+
+# Handling of ON CONFLICT by UPDATE statements inside triggers
+execsql {
+ INSERT INTO tbl values (4, 2, 3);
+ INSERT INTO tbl values (6, 3, 4);
+ CREATE TRIGGER au_tbl AFTER UPDATE ON tbl BEGIN
+ UPDATE OR IGNORE tbl SET a = new.a, c = 10;
+ END;
+}
+do_test trigger2-6.2a {
+ execsql {
+ BEGIN;
+ UPDATE tbl SET a = 1 WHERE a = 4;
+ SELECT * from tbl;
+ }
+} {1 2 10 6 3 4}
+do_test trigger2-6.2b {
+ catchsql {
+ UPDATE OR ABORT tbl SET a = 4 WHERE a = 1;
+ }
+} {1 {column a is not unique}}
+do_test trigger2-6.2c {
+ execsql {
+ SELECT * from tbl;
+ }
+} {1 2 10 6 3 4}
+do_test trigger2-6.2d {
+ catchsql {
+ UPDATE OR FAIL tbl SET a = 4 WHERE a = 1;
+ }
+} {1 {column a is not unique}}
+do_test trigger2-6.2e {
+ execsql {
+ SELECT * from tbl;
+ }
+} {4 2 10 6 3 4}
+do_test trigger2-6.2f.1 {
+ execsql {
+ UPDATE OR REPLACE tbl SET a = 1 WHERE a = 4;
+ SELECT * from tbl;
+ }
+} {1 3 10}
+do_test trigger2-6.2f.2 {
+ execsql {
+ INSERT INTO tbl VALUES (2, 3, 4);
+ SELECT * FROM tbl;
+ }
+} {1 3 10 2 3 4}
+do_test trigger2-6.2g {
+ catchsql {
+ UPDATE OR ROLLBACK tbl SET a = 4 WHERE a = 1;
+ }
+} {1 {column a is not unique}}
+do_test trigger2-6.2h {
+ execsql {
+ SELECT * from tbl;
+ }
+} {4 2 3 6 3 4}
+execsql {
+ DROP TABLE tbl;
+}
+
+# 7. Triggers on views
+do_test trigger2-7.1 {
+ execsql {
+ CREATE TABLE ab(a, b);
+ CREATE TABLE cd(c, d);
+ INSERT INTO ab VALUES (1, 2);
+ INSERT INTO ab VALUES (0, 0);
+ INSERT INTO cd VALUES (3, 4);
+
+ CREATE TABLE tlog(ii INTEGER PRIMARY KEY,
+ olda, oldb, oldc, oldd, newa, newb, newc, newd);
+
+ CREATE VIEW abcd AS SELECT a, b, c, d FROM ab, cd;
+
+ CREATE TRIGGER before_update INSTEAD OF UPDATE ON abcd BEGIN
+ INSERT INTO tlog VALUES(NULL,
+ old.a, old.b, old.c, old.d, new.a, new.b, new.c, new.d);
+ END;
+ CREATE TRIGGER after_update INSTEAD OF UPDATE ON abcd BEGIN
+ INSERT INTO tlog VALUES(NULL,
+ old.a, old.b, old.c, old.d, new.a, new.b, new.c, new.d);
+ END;
+
+ CREATE TRIGGER before_delete INSTEAD OF DELETE ON abcd BEGIN
+ INSERT INTO tlog VALUES(NULL,
+ old.a, old.b, old.c, old.d, 0, 0, 0, 0);
+ END;
+ CREATE TRIGGER after_delete INSTEAD OF DELETE ON abcd BEGIN
+ INSERT INTO tlog VALUES(NULL,
+ old.a, old.b, old.c, old.d, 0, 0, 0, 0);
+ END;
+
+ CREATE TRIGGER before_insert INSTEAD OF INSERT ON abcd BEGIN
+ INSERT INTO tlog VALUES(NULL,
+ 0, 0, 0, 0, new.a, new.b, new.c, new.d);
+ END;
+ CREATE TRIGGER after_insert INSTEAD OF INSERT ON abcd BEGIN
+ INSERT INTO tlog VALUES(NULL,
+ 0, 0, 0, 0, new.a, new.b, new.c, new.d);
+ END;
+ }
+} {};
+
+do_test trigger2-7.2 {
+ execsql {
+ UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1;
+ DELETE FROM abcd WHERE a = 1;
+ INSERT INTO abcd VALUES(10, 20, 30, 40);
+ SELECT * FROM tlog;
+ }
+} [ list 1 1 2 3 4 100 25 3 4 \
+ 2 1 2 3 4 100 25 3 4 \
+ 3 1 2 3 4 0 0 0 0 \
+ 4 1 2 3 4 0 0 0 0 \
+ 5 0 0 0 0 10 20 30 40 \
+ 6 0 0 0 0 10 20 30 40 ]
+
+do_test trigger2-7.3 {
+ execsql {
+ DELETE FROM tlog;
+ INSERT INTO abcd VALUES(10, 20, 30, 40);
+ UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1;
+ DELETE FROM abcd WHERE a = 1;
+ SELECT * FROM tlog;
+ }
+} [ list \
+ 1 0 0 0 0 10 20 30 40 \
+ 2 0 0 0 0 10 20 30 40 \
+ 3 1 2 3 4 100 25 3 4 \
+ 4 1 2 3 4 100 25 3 4 \
+ 5 1 2 3 4 0 0 0 0 \
+ 6 1 2 3 4 0 0 0 0 \
+]
+do_test trigger2-7.4 {
+ execsql {
+ DELETE FROM tlog;
+ DELETE FROM abcd WHERE a = 1;
+ INSERT INTO abcd VALUES(10, 20, 30, 40);
+ UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1;
+ SELECT * FROM tlog;
+ }
+} [ list \
+ 1 1 2 3 4 0 0 0 0 \
+ 2 1 2 3 4 0 0 0 0 \
+ 3 0 0 0 0 10 20 30 40 \
+ 4 0 0 0 0 10 20 30 40 \
+ 5 1 2 3 4 100 25 3 4 \
+ 6 1 2 3 4 100 25 3 4 \
+]
+
+do_test trigger2-8.1 {
+ execsql {
+ CREATE TABLE t1(a,b,c);
+ INSERT INTO t1 VALUES(1,2,3);
+ CREATE VIEW v1 AS
+ SELECT a+b AS x, b+c AS y, a+c AS z FROM t1;
+ SELECT * FROM v1;
+ }
+} {3 5 4}
+do_test trigger2-8.2 {
+ execsql {
+ CREATE TABLE v1log(a,b,c,d,e,f);
+ CREATE TRIGGER r1 INSTEAD OF DELETE ON v1 BEGIN
+ INSERT INTO v1log VALUES(OLD.x,NULL,OLD.y,NULL,OLD.z,NULL);
+ END;
+ DELETE FROM v1 WHERE x=1;
+ SELECT * FROM v1log;
+ }
+} {}
+do_test trigger2-8.3 {
+ execsql {
+ DELETE FROM v1 WHERE x=3;
+ SELECT * FROM v1log;
+ }
+} {3 {} 5 {} 4 {}}
+do_test trigger2-8.4 {
+ execsql {
+ INSERT INTO t1 VALUES(4,5,6);
+ DELETE FROM v1log;
+ DELETE FROM v1 WHERE y=11;
+ SELECT * FROM v1log;
+ }
+} {9 {} 11 {} 10 {}}
+do_test trigger2-8.5 {
+ execsql {
+ CREATE TRIGGER r2 INSTEAD OF INSERT ON v1 BEGIN
+ INSERT INTO v1log VALUES(NULL,NEW.x,NULL,NEW.y,NULL,NEW.z);
+ END;
+ DELETE FROM v1log;
+ INSERT INTO v1 VALUES(1,2,3);
+ SELECT * FROM v1log;
+ }
+} {{} 1 {} 2 {} 3}
+do_test trigger2-8.6 {
+ execsql {
+ CREATE TRIGGER r3 INSTEAD OF UPDATE ON v1 BEGIN
+ INSERT INTO v1log VALUES(OLD.x,NEW.x,OLD.y,NEW.y,OLD.z,NEW.z);
+ END;
+ DELETE FROM v1log;
+ UPDATE v1 SET x=x+100, y=y+200, z=z+300;
+ SELECT * FROM v1log;
+ }
+} {3 103 5 205 4 304 9 109 11 211 10 310}
+
+do_test trigger2-9.9 {
+ execsql {PRAGMA integrity_check}
+} {ok}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/trigger3.test b/usr/src/lib/libsqlite/test/trigger3.test
new file mode 100644
index 0000000000..bf4101600b
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/trigger3.test
@@ -0,0 +1,169 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 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 tests the RAISE() function.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Test that we can cause ROLLBACK, FAIL and ABORT correctly
+# catchsql { DROP TABLE tbl; }
+catchsql { CREATE TABLE tbl (a, b, c) }
+
+execsql {
+ CREATE TRIGGER before_tbl_insert BEFORE INSERT ON tbl BEGIN SELECT CASE
+ WHEN (new.a = 4) THEN RAISE(IGNORE) END;
+ END;
+
+ CREATE TRIGGER after_tbl_insert AFTER INSERT ON tbl BEGIN SELECT CASE
+ WHEN (new.a = 1) THEN RAISE(ABORT, 'Trigger abort')
+ WHEN (new.a = 2) THEN RAISE(FAIL, 'Trigger fail')
+ WHEN (new.a = 3) THEN RAISE(ROLLBACK, 'Trigger rollback') END;
+ END;
+}
+# ABORT
+do_test trigger3-1.1 {
+ catchsql {
+ BEGIN;
+ INSERT INTO tbl VALUES (5, 5, 6);
+ INSERT INTO tbl VALUES (1, 5, 6);
+ }
+} {1 {Trigger abort}}
+do_test trigger3-1.2 {
+ execsql {
+ SELECT * FROM tbl;
+ ROLLBACK;
+ }
+} {5 5 6}
+do_test trigger3-1.3 {
+ execsql {SELECT * FROM tbl}
+} {}
+
+# FAIL
+do_test trigger3-2.1 {
+ catchsql {
+ BEGIN;
+ INSERT INTO tbl VALUES (5, 5, 6);
+ INSERT INTO tbl VALUES (2, 5, 6);
+ }
+} {1 {Trigger fail}}
+do_test trigger3-2.2 {
+ execsql {
+ SELECT * FROM tbl;
+ ROLLBACK;
+ }
+} {5 5 6 2 5 6}
+# ROLLBACK
+do_test trigger3-3.1 {
+ catchsql {
+ BEGIN;
+ INSERT INTO tbl VALUES (5, 5, 6);
+ INSERT INTO tbl VALUES (3, 5, 6);
+ }
+} {1 {Trigger rollback}}
+do_test trigger3-3.2 {
+ execsql {
+ SELECT * FROM tbl;
+ }
+} {}
+# IGNORE
+do_test trigger3-4.1 {
+ catchsql {
+ BEGIN;
+ INSERT INTO tbl VALUES (5, 5, 6);
+ INSERT INTO tbl VALUES (4, 5, 6);
+ }
+} {0 {}}
+do_test trigger3-4.2 {
+ execsql {
+ SELECT * FROM tbl;
+ ROLLBACK;
+ }
+} {5 5 6}
+
+# Check that we can also do RAISE(IGNORE) for UPDATE and DELETE
+execsql {DROP TABLE tbl;}
+execsql {CREATE TABLE tbl (a, b, c);}
+execsql {INSERT INTO tbl VALUES(1, 2, 3);}
+execsql {INSERT INTO tbl VALUES(4, 5, 6);}
+execsql {
+ CREATE TRIGGER before_tbl_update BEFORE UPDATE ON tbl BEGIN
+ SELECT CASE WHEN (old.a = 1) THEN RAISE(IGNORE) END;
+ END;
+
+ CREATE TRIGGER before_tbl_delete BEFORE DELETE ON tbl BEGIN
+ SELECT CASE WHEN (old.a = 1) THEN RAISE(IGNORE) END;
+ END;
+}
+do_test trigger3-5.1 {
+ execsql {
+ UPDATE tbl SET c = 10;
+ SELECT * FROM tbl;
+ }
+} {1 2 3 4 5 10}
+do_test trigger3-5.2 {
+ execsql {
+ DELETE FROM tbl;
+ SELECT * FROM tbl;
+ }
+} {1 2 3}
+
+# Check that RAISE(IGNORE) works correctly for nested triggers:
+execsql {CREATE TABLE tbl2(a, b, c)}
+execsql {
+ CREATE TRIGGER after_tbl2_insert AFTER INSERT ON tbl2 BEGIN
+ UPDATE tbl SET c = 10;
+ INSERT INTO tbl2 VALUES (new.a, new.b, new.c);
+ END;
+}
+do_test trigger3-6 {
+ execsql {
+ INSERT INTO tbl2 VALUES (1, 2, 3);
+ SELECT * FROM tbl2;
+ SELECT * FROM tbl;
+ }
+} {1 2 3 1 2 3 1 2 3}
+
+# Check that things also work for view-triggers
+execsql {CREATE VIEW tbl_view AS SELECT * FROM tbl}
+execsql {
+ CREATE TRIGGER tbl_view_insert INSTEAD OF INSERT ON tbl_view BEGIN
+ SELECT CASE WHEN (new.a = 1) THEN RAISE(ROLLBACK, 'View rollback')
+ WHEN (new.a = 2) THEN RAISE(IGNORE)
+ WHEN (new.a = 3) THEN RAISE(ABORT, 'View abort') END;
+ END;
+}
+
+do_test trigger3-7.1 {
+ catchsql {
+ INSERT INTO tbl_view VALUES(1, 2, 3);
+ }
+} {1 {View rollback}}
+do_test trigger3-7.2 {
+ catchsql {
+ INSERT INTO tbl_view VALUES(2, 2, 3);
+ }
+} {0 {}}
+do_test trigger3-7.3 {
+ catchsql {
+ INSERT INTO tbl_view VALUES(3, 2, 3);
+ }
+} {1 {View abort}}
+
+integrity_check trigger3-8.1
+
+catchsql { DROP TABLE tbl; }
+catchsql { DROP TABLE tbl2; }
+catchsql { DROP VIEW tbl_view; }
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/trigger4.test b/usr/src/lib/libsqlite/test/trigger4.test
new file mode 100644
index 0000000000..9f6301bee1
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/trigger4.test
@@ -0,0 +1,130 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 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 tests the triggers of views.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test trigger4-1.1 {
+ execsql {
+ create table test1(id integer primary key,a);
+ create table test2(id integer,b);
+ create view test as
+ select test1.id as id,a as a,b as b
+ from test1 join test2 on test2.id = test1.id;
+ create trigger I_test instead of insert on test
+ begin
+ insert into test1 (id,a) values (NEW.id,NEW.a);
+ insert into test2 (id,b) values (NEW.id,NEW.b);
+ end;
+ insert into test values(1,2,3);
+ select * from test1;
+ }
+} {1 2}
+do_test trigger4-1.2 {
+ execsql {
+ select * from test2;
+ }
+} {1 3}
+do_test trigger4-1.3 {
+ db close
+ sqlite db test.db
+ execsql {
+ insert into test values(4,5,6);
+ select * from test1;
+ }
+} {1 2 4 5}
+do_test trigger4-1.4 {
+ execsql {
+ select * from test2;
+ }
+} {1 3 4 6}
+
+do_test trigger4-2.1 {
+ execsql {
+ create trigger U_test instead of update on test
+ begin
+ update test1 set a=NEW.a where id=NEW.id;
+ update test2 set b=NEW.b where id=NEW.id;
+ end;
+ update test set a=22 where id=1;
+ select * from test1;
+ }
+} {1 22 4 5}
+do_test trigger4-2.2 {
+ execsql {
+ select * from test2;
+ }
+} {1 3 4 6}
+do_test trigger4-2.3 {
+ db close
+ sqlite db test.db
+ execsql {
+ update test set b=66 where id=4;
+ select * from test1;
+ }
+} {1 22 4 5}
+do_test trigger4-2.4 {
+ execsql {
+ select * from test2;
+ }
+} {1 3 4 66}
+
+do_test trigger4-3.1 {
+ catchsql {
+ drop table test2;
+ insert into test values(7,8,9);
+ }
+} {1 {no such table: main.test2}}
+do_test trigger4-3.2 {
+ db close
+ sqlite db test.db
+ catchsql {
+ insert into test values(7,8,9);
+ }
+} {1 {no such table: main.test2}}
+do_test trigger4-3.3 {
+ catchsql {
+ update test set a=222 where id=1;
+ }
+} {1 {no such table: main.test2}}
+do_test trigger4-3.4 {
+ execsql {
+ select * from test1;
+ }
+} {1 22 4 5}
+do_test trigger4-3.5 {
+ execsql {
+ create table test2(id,b);
+ insert into test values(7,8,9);
+ select * from test1;
+ }
+} {1 22 4 5 7 8}
+do_test trigger4-3.6 {
+ execsql {
+ select * from test2;
+ }
+} {7 9}
+do_test trigger4-3.7 {
+ db close
+ sqlite db test.db
+ execsql {
+ update test set b=99 where id=7;
+ select * from test2;
+ }
+} {7 99}
+
+integrity_check trigger4-4.1
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/unique.test b/usr/src/lib/libsqlite/test/unique.test
new file mode 100644
index 0000000000..9b6977bf71
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/unique.test
@@ -0,0 +1,235 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 27
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing the CREATE UNIQUE INDEX statement,
+# and primary keys, and the UNIQUE constraint on table columns
+#
+# $Id: unique.test,v 1.7 2003/08/05 13:13:39 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Try to create a table with two primary keys.
+# (This is allowed in SQLite even that it is not valid SQL)
+#
+do_test unique-1.1 {
+ catchsql {
+ CREATE TABLE t1(
+ a int PRIMARY KEY,
+ b int PRIMARY KEY,
+ c text
+ );
+ }
+} {1 {table "t1" has more than one primary key}}
+do_test unique-1.1b {
+ catchsql {
+ CREATE TABLE t1(
+ a int PRIMARY KEY,
+ b int UNIQUE,
+ c text
+ );
+ }
+} {0 {}}
+do_test unique-1.2 {
+ catchsql {
+ INSERT INTO t1(a,b,c) VALUES(1,2,3)
+ }
+} {0 {}}
+do_test unique-1.3 {
+ catchsql {
+ INSERT INTO t1(a,b,c) VALUES(1,3,4)
+ }
+} {1 {column a is not unique}}
+do_test unique-1.4 {
+ execsql {
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 2 3}
+do_test unique-1.5 {
+ catchsql {
+ INSERT INTO t1(a,b,c) VALUES(3,2,4)
+ }
+} {1 {column b is not unique}}
+do_test unique-1.6 {
+ execsql {
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 2 3}
+do_test unique-1.7 {
+ catchsql {
+ INSERT INTO t1(a,b,c) VALUES(3,4,5)
+ }
+} {0 {}}
+do_test unique-1.8 {
+ execsql {
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 2 3 3 4 5}
+integrity_check unique-1.9
+
+do_test unique-2.0 {
+ execsql {
+ DROP TABLE t1;
+ CREATE TABLE t2(a int, b int);
+ INSERT INTO t2(a,b) VALUES(1,2);
+ INSERT INTO t2(a,b) VALUES(3,4);
+ SELECT * FROM t2 ORDER BY a;
+ }
+} {1 2 3 4}
+do_test unique-2.1 {
+ catchsql {
+ CREATE UNIQUE INDEX i2 ON t2(a)
+ }
+} {0 {}}
+do_test unique-2.2 {
+ catchsql {
+ SELECT * FROM t2 ORDER BY a
+ }
+} {0 {1 2 3 4}}
+do_test unique-2.3 {
+ catchsql {
+ INSERT INTO t2 VALUES(1,5);
+ }
+} {1 {column a is not unique}}
+do_test unique-2.4 {
+ catchsql {
+ SELECT * FROM t2 ORDER BY a
+ }
+} {0 {1 2 3 4}}
+do_test unique-2.5 {
+ catchsql {
+ DROP INDEX i2;
+ SELECT * FROM t2 ORDER BY a;
+ }
+} {0 {1 2 3 4}}
+do_test unique-2.6 {
+ catchsql {
+ INSERT INTO t2 VALUES(1,5)
+ }
+} {0 {}}
+do_test unique-2.7 {
+ catchsql {
+ SELECT * FROM t2 ORDER BY a, b;
+ }
+} {0 {1 2 1 5 3 4}}
+do_test unique-2.8 {
+ catchsql {
+ CREATE UNIQUE INDEX i2 ON t2(a);
+ }
+} {1 {indexed columns are not unique}}
+do_test unique-2.9 {
+ catchsql {
+ CREATE INDEX i2 ON t2(a);
+ }
+} {0 {}}
+integrity_check unique-2.10
+
+# Test the UNIQUE keyword as used on two or more fields.
+#
+do_test unique-3.1 {
+ catchsql {
+ CREATE TABLE t3(
+ a int,
+ b int,
+ c int,
+ d int,
+ unique(a,c,d)
+ );
+ }
+} {0 {}}
+do_test unique-3.2 {
+ catchsql {
+ INSERT INTO t3(a,b,c,d) VALUES(1,2,3,4);
+ SELECT * FROM t3 ORDER BY a,b,c,d;
+ }
+} {0 {1 2 3 4}}
+do_test unique-3.3 {
+ catchsql {
+ INSERT INTO t3(a,b,c,d) VALUES(1,2,3,5);
+ SELECT * FROM t3 ORDER BY a,b,c,d;
+ }
+} {0 {1 2 3 4 1 2 3 5}}
+do_test unique-3.4 {
+ catchsql {
+ INSERT INTO t3(a,b,c,d) VALUES(1,4,3,5);
+ SELECT * FROM t3 ORDER BY a,b,c,d;
+ }
+} {1 {columns a, c, d are not unique}}
+integrity_check unique-3.5
+
+# Make sure NULLs are distinct as far as the UNIQUE tests are
+# concerned.
+#
+do_test unique-4.1 {
+ execsql {
+ CREATE TABLE t4(a UNIQUE, b, c, UNIQUE(b,c));
+ INSERT INTO t4 VALUES(1,2,3);
+ INSERT INTO t4 VALUES(NULL, 2, NULL);
+ SELECT * FROM t4;
+ }
+} {1 2 3 {} 2 {}}
+do_test unique-4.2 {
+ catchsql {
+ INSERT INTO t4 VALUES(NULL, 3, 4);
+ }
+} {0 {}}
+do_test unique-4.3 {
+ execsql {
+ SELECT * FROM t4
+ }
+} {1 2 3 {} 2 {} {} 3 4}
+do_test unique-4.4 {
+ catchsql {
+ INSERT INTO t4 VALUES(2, 2, NULL);
+ }
+} {0 {}}
+do_test unique-4.5 {
+ execsql {
+ SELECT * FROM t4
+ }
+} {1 2 3 {} 2 {} {} 3 4 2 2 {}}
+integrity_check unique-4.6
+
+# Test the error message generation logic. In particular, make sure we
+# do not overflow the static buffer used to generate the error message.
+#
+do_test unique-5.1 {
+ execsql {
+ CREATE TABLE t5(
+ first_column_with_long_name,
+ second_column_with_long_name,
+ third_column_with_long_name,
+ fourth_column_with_long_name,
+ fifth_column_with_long_name,
+ sixth_column_with_long_name,
+ UNIQUE(
+ first_column_with_long_name,
+ second_column_with_long_name,
+ third_column_with_long_name,
+ fourth_column_with_long_name,
+ fifth_column_with_long_name,
+ sixth_column_with_long_name
+ )
+ );
+ INSERT INTO t5 VALUES(1,2,3,4,5,6);
+ SELECT * FROM t5;
+ }
+} {1 2 3 4 5 6}
+do_test unique-5.2 {
+ catchsql {
+ INSERT INTO t5 VALUES(1,2,3,4,5,6);
+ }
+} {1 {columns first_column_with_long_name, second_column_with_long_name, third_column_with_long_name, fourth_column_with_long_name, fifth_column_with_long_name, ... are not unique}}
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/update.test b/usr/src/lib/libsqlite/test/update.test
new file mode 100644
index 0000000000..48e270f704
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/update.test
@@ -0,0 +1,565 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 UPDATE statement.
+#
+# $Id: update.test,v 1.15 2004/02/10 13:41:53 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Try to update an non-existent table
+#
+do_test update-1.1 {
+ set v [catch {execsql {UPDATE test1 SET f2=5 WHERE f1<1}} msg]
+ lappend v $msg
+} {1 {no such table: test1}}
+
+# Try to update a read-only table
+#
+do_test update-2.1 {
+ set v [catch \
+ {execsql {UPDATE sqlite_master SET name='xyz' WHERE name='123'}} msg]
+ lappend v $msg
+} {1 {table sqlite_master may not be modified}}
+
+# Create a table to work with
+#
+do_test update-3.1 {
+ execsql {CREATE TABLE test1(f1 int,f2 int)}
+ for {set i 1} {$i<=10} {incr i} {
+ set sql "INSERT INTO test1 VALUES($i,[expr {int(pow(2,$i))}])"
+ execsql $sql
+ }
+ execsql {SELECT * FROM test1 ORDER BY f1}
+} {1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024}
+
+# Unknown column name in an expression
+#
+do_test update-3.2 {
+ set v [catch {execsql {UPDATE test1 SET f1=f3*2 WHERE f2==32}} msg]
+ lappend v $msg
+} {1 {no such column: f3}}
+do_test update-3.3 {
+ set v [catch {execsql {UPDATE test1 SET f1=test2.f1*2 WHERE f2==32}} msg]
+ lappend v $msg
+} {1 {no such column: test2.f1}}
+do_test update-3.4 {
+ set v [catch {execsql {UPDATE test1 SET f3=f1*2 WHERE f2==32}} msg]
+ lappend v $msg
+} {1 {no such column: f3}}
+
+# Actually do some updates
+#
+do_test update-3.5 {
+ execsql {UPDATE test1 SET f2=f2*3}
+} {}
+do_test update-3.6 {
+ execsql {SELECT * FROM test1 ORDER BY f1}
+} {1 6 2 12 3 24 4 48 5 96 6 192 7 384 8 768 9 1536 10 3072}
+do_test update-3.7 {
+ execsql {PRAGMA count_changes=on}
+ execsql {UPDATE test1 SET f2=f2/3 WHERE f1<=5}
+} {5}
+do_test update-3.8 {
+ execsql {SELECT * FROM test1 ORDER BY f1}
+} {1 2 2 4 3 8 4 16 5 32 6 192 7 384 8 768 9 1536 10 3072}
+do_test update-3.9 {
+ execsql {UPDATE test1 SET f2=f2/3 WHERE f1>5}
+} {5}
+do_test update-3.10 {
+ execsql {SELECT * FROM test1 ORDER BY f1}
+} {1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024}
+
+# Swap the values of f1 and f2 for all elements
+#
+do_test update-3.11 {
+ execsql {UPDATE test1 SET F2=f1, F1=f2}
+} {10}
+do_test update-3.12 {
+ execsql {SELECT * FROM test1 ORDER BY F1}
+} {2 1 4 2 8 3 16 4 32 5 64 6 128 7 256 8 512 9 1024 10}
+do_test update-3.13 {
+ execsql {PRAGMA count_changes=off}
+ execsql {UPDATE test1 SET F2=f1, F1=f2}
+} {}
+do_test update-3.14 {
+ execsql {SELECT * FROM test1 ORDER BY F1}
+} {1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024}
+
+# Create duplicate entries and make sure updating still
+# works.
+#
+do_test update-4.0 {
+ execsql {
+ DELETE FROM test1 WHERE f1<=5;
+ INSERT INTO test1(f1,f2) VALUES(8,88);
+ INSERT INTO test1(f1,f2) VALUES(8,888);
+ INSERT INTO test1(f1,f2) VALUES(77,128);
+ INSERT INTO test1(f1,f2) VALUES(777,128);
+ }
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-4.1 {
+ execsql {UPDATE test1 SET f2=f2+1 WHERE f1==8}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
+do_test update-4.2 {
+ execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
+do_test update-4.3 {
+ execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-4.4 {
+ execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 778 128}
+do_test update-4.5 {
+ execsql {UPDATE test1 SET f1=f1-1 WHERE f1>100 and f2==128}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 777 128}
+do_test update-4.6 {
+ execsql {
+ PRAGMA count_changes=on;
+ UPDATE test1 SET f1=f1-1 WHERE f1<=100 and f2==128;
+ }
+} {2}
+do_test update-4.7 {
+ execsql {
+ PRAGMA count_changes=off;
+ SELECT * FROM test1 ORDER BY f1,f2
+ }
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+
+# Repeat the previous sequence of tests with an index.
+#
+do_test update-5.0 {
+ execsql {CREATE INDEX idx1 ON test1(f1)}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-5.1 {
+ execsql {UPDATE test1 SET f2=f2+1 WHERE f1==8}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
+do_test update-5.2 {
+ execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
+do_test update-5.3 {
+ execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-5.4 {
+ execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 778 128}
+do_test update-5.4.1 {
+ execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
+} {78 128}
+do_test update-5.4.2 {
+ execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
+} {778 128}
+do_test update-5.4.3 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 128 8 256 8 888}
+do_test update-5.5 {
+ execsql {UPDATE test1 SET f1=f1-1 WHERE f1>100 and f2==128}
+} {}
+do_test update-5.5.1 {
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 777 128}
+do_test update-5.5.2 {
+ execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
+} {78 128}
+do_test update-5.5.3 {
+ execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
+} {}
+do_test update-5.5.4 {
+ execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
+} {777 128}
+do_test update-5.5.5 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 128 8 256 8 888}
+do_test update-5.6 {
+ execsql {
+ PRAGMA count_changes=on;
+ UPDATE test1 SET f1=f1-1 WHERE f1<=100 and f2==128;
+ }
+} {2}
+do_test update-5.6.1 {
+ execsql {
+ PRAGMA count_changes=off;
+ SELECT * FROM test1 ORDER BY f1,f2
+ }
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-5.6.2 {
+ execsql {SELECT * FROM test1 WHERE f1==77 ORDER BY f1,f2}
+} {77 128}
+do_test update-5.6.3 {
+ execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
+} {}
+do_test update-5.6.4 {
+ execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
+} {777 128}
+do_test update-5.6.5 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 256 8 888}
+
+# Repeat the previous sequence of tests with a different index.
+#
+execsql {PRAGMA synchronous=FULL}
+do_test update-6.0 {
+ execsql {DROP INDEX idx1}
+ execsql {CREATE INDEX idx1 ON test1(f2)}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-6.1 {
+ execsql {UPDATE test1 SET f2=f2+1 WHERE f1==8}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
+do_test update-6.1.1 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 89 8 257 8 889}
+do_test update-6.1.2 {
+ execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
+} {8 89}
+do_test update-6.1.3 {
+ execsql {SELECT * FROM test1 WHERE f1==88 ORDER BY f1,f2}
+} {}
+do_test update-6.2 {
+ execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
+do_test update-6.3 {
+ execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-6.3.1 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 256 8 888}
+do_test update-6.3.2 {
+ execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
+} {}
+do_test update-6.3.3 {
+ execsql {SELECT * FROM test1 WHERE f2==88 ORDER BY f1,f2}
+} {8 88}
+do_test update-6.4 {
+ execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 778 128}
+do_test update-6.4.1 {
+ execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
+} {78 128}
+do_test update-6.4.2 {
+ execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
+} {778 128}
+do_test update-6.4.3 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 128 8 256 8 888}
+do_test update-6.5 {
+ execsql {UPDATE test1 SET f1=f1-1 WHERE f1>100 and f2==128}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 777 128}
+do_test update-6.5.1 {
+ execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
+} {78 128}
+do_test update-6.5.2 {
+ execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
+} {}
+do_test update-6.5.3 {
+ execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
+} {777 128}
+do_test update-6.5.4 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 128 8 256 8 888}
+do_test update-6.6 {
+ execsql {UPDATE test1 SET f1=f1-1 WHERE f1<=100 and f2==128}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-6.6.1 {
+ execsql {SELECT * FROM test1 WHERE f1==77 ORDER BY f1,f2}
+} {77 128}
+do_test update-6.6.2 {
+ execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
+} {}
+do_test update-6.6.3 {
+ execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
+} {777 128}
+do_test update-6.6.4 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 256 8 888}
+
+# Repeat the previous sequence of tests with multiple
+# indices
+#
+do_test update-7.0 {
+ execsql {CREATE INDEX idx2 ON test1(f2)}
+ execsql {CREATE INDEX idx3 ON test1(f1,f2)}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-7.1 {
+ execsql {UPDATE test1 SET f2=f2+1 WHERE f1==8}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
+do_test update-7.1.1 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 89 8 257 8 889}
+do_test update-7.1.2 {
+ execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
+} {8 89}
+do_test update-7.1.3 {
+ execsql {SELECT * FROM test1 WHERE f1==88 ORDER BY f1,f2}
+} {}
+do_test update-7.2 {
+ execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
+do_test update-7.3 {
+ # explain {UPDATE test1 SET f2=f2-1 WHERE f1==8 and F2<300}
+ execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-7.3.1 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 256 8 888}
+do_test update-7.3.2 {
+ execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
+} {}
+do_test update-7.3.3 {
+ execsql {SELECT * FROM test1 WHERE f2==88 ORDER BY f1,f2}
+} {8 88}
+do_test update-7.4 {
+ execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 778 128}
+do_test update-7.4.1 {
+ execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
+} {78 128}
+do_test update-7.4.2 {
+ execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
+} {778 128}
+do_test update-7.4.3 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 128 8 256 8 888}
+do_test update-7.5 {
+ execsql {UPDATE test1 SET f1=f1-1 WHERE f1>100 and f2==128}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 777 128}
+do_test update-7.5.1 {
+ execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
+} {78 128}
+do_test update-7.5.2 {
+ execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
+} {}
+do_test update-7.5.3 {
+ execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
+} {777 128}
+do_test update-7.5.4 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 128 8 256 8 888}
+do_test update-7.6 {
+ execsql {UPDATE test1 SET f1=f1-1 WHERE f1<=100 and f2==128}
+ execsql {SELECT * FROM test1 ORDER BY f1,f2}
+} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
+do_test update-7.6.1 {
+ execsql {SELECT * FROM test1 WHERE f1==77 ORDER BY f1,f2}
+} {77 128}
+do_test update-7.6.2 {
+ execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
+} {}
+do_test update-7.6.3 {
+ execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
+} {777 128}
+do_test update-7.6.4 {
+ execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
+} {8 88 8 256 8 888}
+
+# Error messages
+#
+do_test update-9.1 {
+ set v [catch {execsql {
+ UPDATE test1 SET x=11 WHERE f1=1025
+ }} msg]
+ lappend v $msg
+} {1 {no such column: x}}
+do_test update-9.2 {
+ set v [catch {execsql {
+ UPDATE test1 SET f1=x(11) WHERE f1=1025
+ }} msg]
+ lappend v $msg
+} {1 {no such function: x}}
+do_test update-9.3 {
+ set v [catch {execsql {
+ UPDATE test1 SET f1=11 WHERE x=1025
+ }} msg]
+ lappend v $msg
+} {1 {no such column: x}}
+do_test update-9.4 {
+ set v [catch {execsql {
+ UPDATE test1 SET f1=11 WHERE x(f1)=1025
+ }} msg]
+ lappend v $msg
+} {1 {no such function: x}}
+
+# Try doing updates on a unique column where the value does not
+# really change.
+#
+do_test update-10.1 {
+ execsql {
+ DROP TABLE test1;
+ CREATE TABLE t1(
+ a integer primary key,
+ b UNIQUE,
+ c, d,
+ e, f,
+ UNIQUE(c,d)
+ );
+ INSERT INTO t1 VALUES(1,2,3,4,5,6);
+ INSERT INTO t1 VALUES(2,3,4,4,6,7);
+ SELECT * FROM t1
+ }
+} {1 2 3 4 5 6 2 3 4 4 6 7}
+do_test update-10.2 {
+ catchsql {
+ UPDATE t1 SET a=1, e=9 WHERE f=6;
+ SELECT * FROM t1;
+ }
+} {0 {1 2 3 4 9 6 2 3 4 4 6 7}}
+do_test update-10.3 {
+ catchsql {
+ UPDATE t1 SET a=1, e=10 WHERE f=7;
+ SELECT * FROM t1;
+ }
+} {1 {PRIMARY KEY must be unique}}
+do_test update-10.4 {
+ catchsql {
+ SELECT * FROM t1;
+ }
+} {0 {1 2 3 4 9 6 2 3 4 4 6 7}}
+do_test update-10.5 {
+ catchsql {
+ UPDATE t1 SET b=2, e=11 WHERE f=6;
+ SELECT * FROM t1;
+ }
+} {0 {1 2 3 4 11 6 2 3 4 4 6 7}}
+do_test update-10.6 {
+ catchsql {
+ UPDATE t1 SET b=2, e=12 WHERE f=7;
+ SELECT * FROM t1;
+ }
+} {1 {column b is not unique}}
+do_test update-10.7 {
+ catchsql {
+ SELECT * FROM t1;
+ }
+} {0 {1 2 3 4 11 6 2 3 4 4 6 7}}
+do_test update-10.8 {
+ catchsql {
+ UPDATE t1 SET c=3, d=4, e=13 WHERE f=6;
+ SELECT * FROM t1;
+ }
+} {0 {1 2 3 4 13 6 2 3 4 4 6 7}}
+do_test update-10.9 {
+ catchsql {
+ UPDATE t1 SET c=3, d=4, e=14 WHERE f=7;
+ SELECT * FROM t1;
+ }
+} {1 {columns c, d are not unique}}
+do_test update-10.10 {
+ catchsql {
+ SELECT * FROM t1;
+ }
+} {0 {1 2 3 4 13 6 2 3 4 4 6 7}}
+
+# Make sure we can handle a subquery in the where clause.
+#
+do_test update-11.1 {
+ execsql {
+ UPDATE t1 SET e=e+1 WHERE b IN (SELECT b FROM t1);
+ SELECT b,e FROM t1;
+ }
+} {2 14 3 7}
+do_test update-11.2 {
+ execsql {
+ UPDATE t1 SET e=e+1 WHERE a IN (SELECT a FROM t1);
+ SELECT a,e FROM t1;
+ }
+} {1 15 2 8}
+
+integrity_check update-12.1
+
+# Ticket 602. Updates should occur in the same order as the records
+# were discovered in the WHERE clause.
+#
+do_test update-13.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t2(a);
+ INSERT INTO t2 VALUES(1);
+ INSERT INTO t2 VALUES(2);
+ INSERT INTO t2 SELECT a+2 FROM t2;
+ INSERT INTO t2 SELECT a+4 FROM t2;
+ INSERT INTO t2 SELECT a+8 FROM t2;
+ INSERT INTO t2 SELECT a+16 FROM t2;
+ INSERT INTO t2 SELECT a+32 FROM t2;
+ INSERT INTO t2 SELECT a+64 FROM t2;
+ INSERT INTO t2 SELECT a+128 FROM t2;
+ INSERT INTO t2 SELECT a+256 FROM t2;
+ INSERT INTO t2 SELECT a+512 FROM t2;
+ INSERT INTO t2 SELECT a+1024 FROM t2;
+ COMMIT;
+ SELECT count(*) FROM t2;
+ }
+} {2048}
+do_test update-13.2 {
+ execsql {
+ SELECT count(*) FROM t2 WHERE a=rowid;
+ }
+} {2048}
+do_test update-13.3 {
+ execsql {
+ UPDATE t2 SET rowid=rowid-1;
+ SELECT count(*) FROM t2 WHERE a=rowid+1;
+ }
+} {2048}
+do_test update-13.3 {
+ execsql {
+ UPDATE t2 SET rowid=rowid+10000;
+ UPDATE t2 SET rowid=rowid-9999;
+ SELECT count(*) FROM t2 WHERE a=rowid;
+ }
+} {2048}
+do_test update-13.4 {
+ execsql {
+ BEGIN;
+ INSERT INTO t2 SELECT a+2048 FROM t2;
+ INSERT INTO t2 SELECT a+4096 FROM t2;
+ INSERT INTO t2 SELECT a+8192 FROM t2;
+ SELECT count(*) FROM t2 WHERE a=rowid;
+ COMMIT;
+ }
+} 16384
+do_test update-13.5 {
+ execsql {
+ UPDATE t2 SET rowid=rowid-1;
+ SELECT count(*) FROM t2 WHERE a=rowid+1;
+ }
+} 16384
+
+integrity_check update-13.6
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/vacuum.test b/usr/src/lib/libsqlite/test/vacuum.test
new file mode 100644
index 0000000000..4154107c97
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/vacuum.test
@@ -0,0 +1,176 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 VACUUM statement.
+#
+# $Id: vacuum.test,v 1.15 2004/02/14 16:31:04 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+proc cksum {{db db}} {
+ set txt [$db eval {SELECT name, type, sql FROM sqlite_master}]\n
+ foreach tbl [$db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
+ append txt [$db eval "SELECT * FROM $tbl"]\n
+ }
+ foreach prag {default_synchronous default_cache_size} {
+ append txt $prag-[$db eval "PRAGMA $prag"]\n
+ }
+ set cksum [string length $txt]-[md5 $txt]
+ # puts $cksum-[file size test.db]
+ return $cksum
+}
+do_test vacuum-1.1 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
+ INSERT INTO t1 VALUES(NULL,randstr(10,100),randstr(5,50));
+ INSERT INTO t1 VALUES(123456,randstr(10,100),randstr(5,50));
+ INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
+ INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
+ CREATE INDEX i1 ON t1(b,c);
+ CREATE TABLE t2 AS SELECT * FROM t1;
+ COMMIT;
+ DROP TABLE t2;
+ }
+ set ::size1 [file size test.db]
+ set ::cksum [cksum]
+ expr {$::cksum!=""}
+} {1}
+do_test vacuum-1.2 {
+ execsql {
+ VACUUM;
+ }
+ cksum
+} $cksum
+do_test vacuum-1.3 {
+ expr {[file size test.db]<$::size1}
+} {1}
+do_test vacuum-1.4 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t2 AS SELECT * FROM t1;
+ CREATE TABLE t3 AS SELECT * FROM t1;
+ CREATE VIEW v1 AS SELECT b, c FROM t3;
+ CREATE TRIGGER r1 AFTER DELETE ON t2 BEGIN
+ SELECT 1;
+ END;
+ COMMIT;
+ DROP TABLE t2;
+ }
+ set ::size1 [file size test.db]
+ set ::cksum [cksum]
+ expr {$::cksum!=""}
+} {1}
+do_test vacuum-1.5 {
+ execsql {
+ VACUUM;
+ }
+ cksum
+} $cksum
+do_test vacuum-1.6 {
+ expr {[file size test.db]<$::size1}
+} {1}
+
+do_test vacuum-2.1 {
+ catchsql {
+ BEGIN;
+ VACUUM;
+ COMMIT;
+ }
+} {1 {cannot VACUUM from within a transaction}}
+catch {db eval COMMIT}
+do_test vacuum-2.2 {
+ sqlite db2 test.db
+ execsql {
+ BEGIN;
+ CREATE TABLE t4 AS SELECT * FROM t1;
+ CREATE TABLE t5 AS SELECT * FROM t1;
+ COMMIT;
+ DROP TABLE t4;
+ DROP TABLE t5;
+ } db2
+ set ::cksum [cksum db2]
+ catchsql {
+ VACUUM
+ }
+} {0 {}}
+do_test vacuum-2.3 {
+ cksum
+} $cksum
+do_test vacuum-2.4 {
+ catch {db2 eval {SELECT count(*) FROM sqlite_master}}
+ cksum db2
+} $cksum
+
+# Ticket #427. Make sure VACUUM works when the EMPTY_RESULT_CALLBACKS
+# pragma is turned on.
+#
+do_test vacuum-3.1 {
+ db close
+ db2 close
+ file delete test.db
+ sqlite db test.db
+ execsql {
+ PRAGMA empty_result_callbacks=on;
+ VACUUM;
+ }
+} {}
+
+# Ticket #464. Make sure VACUUM works with the sqlite_compile() API.
+#
+do_test vacuum-4.1 {
+ db close
+ set DB [sqlite db test.db]
+ set VM [sqlite_compile $DB {VACUUM} TAIL]
+ sqlite_step $VM N VALUES COLNAMES
+} {SQLITE_DONE}
+do_test vacuum-4.2 {
+ sqlite_finalize $VM
+} {}
+
+# Ticket #515. VACUUM after deleting and recreating the table that
+# a view refers to.
+#
+do_test vacuum-5.1 {
+ db close
+ file delete -force test.db
+ sqlite db test.db
+ catchsql {
+ CREATE TABLE Test (TestID int primary key);
+ INSERT INTO Test VALUES (NULL);
+ CREATE VIEW viewTest AS SELECT * FROM Test;
+
+ BEGIN;
+ CREATE TEMP TABLE tempTest (TestID int primary key, Test2 int NULL);
+ INSERT INTO tempTest SELECT TestID, 1 FROM Test;
+ DROP TABLE Test;
+ CREATE TABLE Test(TestID int primary key, Test2 int NULL);
+ INSERT INTO Test SELECT * FROM tempTest;
+ COMMIT;
+ VACUUM;
+ }
+} {0 {}}
+do_test vacuum-5.2 {
+ catchsql {
+ VACUUM;
+ }
+} {0 {}}
+
+# finish_test
diff --git a/usr/src/lib/libsqlite/test/version.test b/usr/src/lib/libsqlite/test/version.test
new file mode 100644
index 0000000000..2e44e0b6ab
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/version.test
@@ -0,0 +1,201 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 July 17
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing the ability of the library to detect
+# past or future file format version numbers and respond appropriately.
+#
+# $Id: version.test,v 1.9 2004/02/12 19:01:05 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Current file format version
+set VX 4
+
+# Create a new database
+#
+do_test version-1.1 {
+ execsql {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(1);
+ INSERT INTO t1 SELECT x+1 FROM t1;
+ INSERT INTO t1 SELECT x+2 FROM t1;
+ INSERT INTO t1 SELECT x+4 FROM t1;
+ SELECT * FROM t1;
+ }
+} {1 2 3 4 5 6 7 8}
+
+# Make sure the version number is set correctly
+#
+do_test version-1.2 {
+ db close
+ set ::bt [btree_open test.db]
+ btree_begin_transaction $::bt
+ set ::meta [btree_get_meta $::bt]
+ btree_rollback $::bt
+ lindex $::meta 2
+} $VX
+
+# Increase the file_format number by one. Verify that the
+# file will refuse to open.
+#
+do_test version-1.3 {
+ set m2 [lreplace $::meta 2 2 [expr {$::VX+1}]]
+ btree_begin_transaction $::bt
+ eval btree_update_meta $::bt $m2
+ btree_commit $::bt
+ set rc [catch {sqlite db test.db} msg]
+ lappend rc $msg
+} {1 {unsupported file format}}
+
+# Decrease the file_format number by one. Verify that the
+# file will open correctly.
+#
+do_test version-1.4 {
+ set m2 [lreplace $::meta 2 2 [expr {$::VX-1}]]
+ btree_begin_transaction $::bt
+ eval btree_update_meta $::bt $m2
+ btree_commit $::bt
+ sqlite db test.db
+ execsql {
+ SELECT * FROM t1;
+ }
+} {1 2 3 4 5 6 7 8}
+
+# Set the file_format number to 2. This should cause the automatic
+# upgrade processing to run.
+#
+do_test version-1.5 {
+ set m2 [lreplace $::meta 2 2 2]
+ btree_begin_transaction $::bt
+ eval btree_update_meta $::bt $m2
+ btree_commit $::bt
+ sqlite db test.db
+ execsql {
+ SELECT * FROM t1;
+ }
+} {1 2 3 4 5 6 7 8}
+do_test version-1.6 {
+ set ::meta [btree_get_meta $::bt]
+ lindex $::meta 2
+} $VX
+
+# Add some triggers, views, and indices to the schema and make sure the
+# automatic upgrade still works.
+#
+do_test version-1.7 {
+ execsql {
+ CREATE INDEX i1 ON t1(x);
+ DELETE FROM t1;
+ CREATE TABLE t2(a INTEGER PRIMARY KEY, b UNIQUE, c);
+ CREATE TABLE cnt(name,ins, del);
+ INSERT INTO cnt VALUES('t1',0,0);
+ INSERT INTO cnt VALUES('t2',0,0);
+ CREATE TRIGGER r1 AFTER INSERT ON t1 FOR EACH ROW BEGIN
+ UPDATE cnt SET ins=ins+1 WHERE name='t1';
+ END;
+ CREATE TRIGGER r2 AFTER DELETE ON t1 FOR EACH ROW BEGIN
+ UPDATE cnt SET del=del+1 WHERE name='t1';
+ END;
+ CREATE TRIGGER r3 AFTER INSERT ON t2 FOR EACH ROW BEGIN
+ UPDATE cnt SET ins=ins+1 WHERE name='t2';
+ END;
+ CREATE TRIGGER r4 AFTER DELETE ON t2 FOR EACH ROW BEGIN
+ UPDATE cnt SET del=del+1 WHERE name='t2';
+ END;
+ CREATE VIEW v1 AS SELECT x+100 FROM t1;
+ CREATE VIEW v2 AS SELECT sum(ins), sum(del) FROM cnt;
+ INSERT INTO t1 VALUES(1);
+ INSERT INTO t1 SELECT x+1 FROM t1;
+ INSERT INTO t1 SELECT x+2 FROM t1;
+ INSERT INTO t1 SELECT x+4 FROM t1;
+ SELECT * FROM t1;
+ }
+} {1 2 3 4 5 6 7 8}
+do_test version-1.8 {
+ execsql {
+ SELECT * FROM v2;
+ }
+} {8 0}
+do_test version-1.9 {
+ execsql {
+ SELECT * FROM cnt;
+ }
+} {t1 8 0 t2 0 0}
+do_test version-1.10 {
+ execsql {
+ INSERT INTO t2 SELECT x*3, x*2, x FROM t1;
+ SELECT * FROM t2;
+ }
+} {3 2 1 6 4 2 9 6 3 12 8 4 15 10 5 18 12 6 21 14 7 24 16 8}
+do_test version-1.11 {
+ execsql {
+ SELECT * FROM cnt;
+ }
+} {t1 8 0 t2 8 0}
+
+# Here we do the upgrade test.
+#
+do_test version-1.12 {
+ db close
+ set m2 [lreplace $::meta 2 2 2]
+ btree_begin_transaction $::bt
+ eval btree_update_meta $::bt $m2
+ btree_commit $::bt
+ sqlite db test.db
+ execsql {
+ SELECT * FROM cnt;
+ }
+} {t1 8 0 t2 8 0}
+do_test version-1.13 {
+ execsql {
+ SELECT * FROM v1;
+ }
+} {101 102 103 104 105 106 107 108}
+do_test version-1.14 {
+ execsql {
+ SELECT * FROM v2;
+ }
+} {16 0}
+
+# Try to do an upgrade where the database file is read-only
+#
+do_test version-2.1 {
+ db close
+ set m2 [lreplace $::meta 2 2 2]
+ btree_begin_transaction $::bt
+ eval btree_update_meta $::bt $m2
+ btree_commit $::bt
+ btree_close $::bt
+ catch {file attributes test.db -permissions 0444}
+ catch {file attributes test.db -readonly 1}
+ if {[file writable test.db]} {
+ error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user"
+ }
+ set rc [catch {sqlite db test.db} msg]
+ lappend rc $msg
+} {1 {unable to upgrade database to the version 2.6 format: attempt to write a readonly database}}
+do_test version-2.2 {
+ file delete -force test.db
+ set fd [open test.db w]
+ set txt "This is not a valid database file\n"
+ while {[string length $txt]<4092} {append txt $txt}
+ puts $fd $txt
+ close $fd
+ set rc [catch {sqlite db test.db} msg]
+ lappend rc $msg
+} {1 {file is encrypted or is not a database}}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/view.test b/usr/src/lib/libsqlite/test/view.test
new file mode 100644
index 0000000000..2da7e8deb6
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/view.test
@@ -0,0 +1,410 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2002 February 26
+#
+# 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 VIEW statements.
+#
+# $Id: view.test,v 1.16.2.1 2004/07/20 00:20:47 drh Exp $
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test view-1.0 {
+ execsql {
+ CREATE TABLE t1(a,b,c);
+ INSERT INTO t1 VALUES(1,2,3);
+ INSERT INTO t1 VALUES(4,5,6);
+ INSERT INTO t1 VALUES(7,8,9);
+ SELECT * FROM t1;
+ }
+} {1 2 3 4 5 6 7 8 9}
+
+do_test view-1.1 {
+ execsql {
+ BEGIN;
+ CREATE VIEW v1 AS SELECT a,b FROM t1;
+ SELECT * FROM v1 ORDER BY a;
+ }
+} {1 2 4 5 7 8}
+do_test view-1.2 {
+ catchsql {
+ ROLLBACK;
+ SELECT * FROM v1 ORDER BY a;
+ }
+} {1 {no such table: v1}}
+do_test view-1.3 {
+ execsql {
+ CREATE VIEW v1 AS SELECT a,b FROM t1;
+ SELECT * FROM v1 ORDER BY a;
+ }
+} {1 2 4 5 7 8}
+do_test view-1.3.1 {
+ db close
+ sqlite db test.db
+ execsql {
+ SELECT * FROM v1 ORDER BY a;
+ }
+} {1 2 4 5 7 8}
+do_test view-1.4 {
+ catchsql {
+ DROP VIEW v1;
+ SELECT * FROM v1 ORDER BY a;
+ }
+} {1 {no such table: v1}}
+do_test view-1.5 {
+ execsql {
+ CREATE VIEW v1 AS SELECT a,b FROM t1;
+ SELECT * FROM v1 ORDER BY a;
+ }
+} {1 2 4 5 7 8}
+do_test view-1.6 {
+ catchsql {
+ DROP TABLE t1;
+ SELECT * FROM v1 ORDER BY a;
+ }
+} {1 {no such table: main.t1}}
+do_test view-1.7 {
+ execsql {
+ CREATE TABLE t1(x,a,b,c);
+ INSERT INTO t1 VALUES(1,2,3,4);
+ INSERT INTO t1 VALUES(4,5,6,7);
+ INSERT INTO t1 VALUES(7,8,9,10);
+ SELECT * FROM v1 ORDER BY a;
+ }
+} {2 3 5 6 8 9}
+do_test view-1.8 {
+ db close
+ sqlite db test.db
+ execsql {
+ SELECT * FROM v1 ORDER BY a;
+ }
+} {2 3 5 6 8 9}
+
+do_test view-2.1 {
+ execsql {
+ CREATE VIEW v2 AS SELECT * FROM t1 WHERE a>5
+ }; # No semicolon
+ execsql2 {
+ SELECT * FROM v2;
+ }
+} {x 7 a 8 b 9 c 10}
+do_test view-2.2 {
+ catchsql {
+ INSERT INTO v2 VALUES(1,2,3,4);
+ }
+} {1 {cannot modify v2 because it is a view}}
+do_test view-2.3 {
+ catchsql {
+ UPDATE v2 SET a=10 WHERE a=5;
+ }
+} {1 {cannot modify v2 because it is a view}}
+do_test view-2.4 {
+ catchsql {
+ DELETE FROM v2;
+ }
+} {1 {cannot modify v2 because it is a view}}
+do_test view-2.5 {
+ execsql {
+ INSERT INTO t1 VALUES(11,12,13,14);
+ SELECT * FROM v2 ORDER BY x;
+ }
+} {7 8 9 10 11 12 13 14}
+do_test view-2.6 {
+ execsql {
+ SELECT x FROM v2 WHERE a>10
+ }
+} {11}
+
+# Test that column name of views are generated correctly.
+#
+do_test view-3.1 {
+ execsql2 {
+ SELECT * FROM v1 LIMIT 1
+ }
+} {a 2 b 3}
+do_test view-3.2 {
+ execsql2 {
+ SELECT * FROM v2 LIMIT 1
+ }
+} {x 7 a 8 b 9 c 10}
+do_test view-3.3 {
+ execsql2 {
+ DROP VIEW v1;
+ CREATE VIEW v1 AS SELECT a AS 'xyz', b+c AS 'pqr', c-b FROM t1;
+ SELECT * FROM v1 LIMIT 1
+ }
+} {xyz 2 pqr 7 c-b 1}
+do_test view-3.4 {
+ execsql2 {
+ CREATE VIEW v3 AS SELECT a FROM t1 UNION SELECT b FROM t1 ORDER BY b;
+ SELECT * FROM v3 LIMIT 4;
+ }
+} {b 2 b 3 b 5 b 6}
+do_test view-3.5 {
+ execsql2 {
+ CREATE VIEW v4 AS
+ SELECT a, b FROM t1
+ UNION
+ SELECT b AS 'x', a AS 'y' FROM t1
+ ORDER BY x, y;
+ SELECT y FROM v4 ORDER BY y LIMIT 4;
+ }
+} {y 2 y 3 y 5 y 6}
+
+
+do_test view-4.1 {
+ catchsql {
+ DROP VIEW t1;
+ }
+} {1 {use DROP TABLE to delete table t1}}
+do_test view-4.2 {
+ execsql {
+ SELECT 1 FROM t1 LIMIT 1;
+ }
+} 1
+do_test view-4.3 {
+ catchsql {
+ DROP TABLE v1;
+ }
+} {1 {use DROP VIEW to delete view v1}}
+do_test view-4.4 {
+ execsql {
+ SELECT 1 FROM v1 LIMIT 1;
+ }
+} {1}
+do_test view-4.5 {
+ catchsql {
+ CREATE INDEX i1v1 ON v1(xyz);
+ }
+} {1 {views may not be indexed}}
+
+do_test view-5.1 {
+ execsql {
+ CREATE TABLE t2(y,a);
+ INSERT INTO t2 VALUES(22,2);
+ INSERT INTO t2 VALUES(33,3);
+ INSERT INTO t2 VALUES(44,4);
+ INSERT INTO t2 VALUES(55,5);
+ SELECT * FROM t2;
+ }
+} {22 2 33 3 44 4 55 5}
+do_test view-5.2 {
+ execsql {
+ CREATE VIEW v5 AS
+ SELECT t1.x AS v, t2.y AS w FROM t1 JOIN t2 USING(a);
+ SELECT * FROM v5;
+ }
+} {1 22 4 55}
+
+# Verify that the view v5 gets flattened. see sqliteFlattenSubquery().
+# Ticket #272
+do_test view-5.3 {
+ lsearch [execsql {
+ EXPLAIN SELECT * FROM v5;
+ }] OpenTemp
+} {-1}
+do_test view-5.4 {
+ execsql {
+ SELECT * FROM v5 AS a, t2 AS b WHERE a.w=b.y;
+ }
+} {1 22 22 2 4 55 55 5}
+do_test view-5.5 {
+ lsearch [execsql {
+ EXPLAIN SELECT * FROM v5 AS a, t2 AS b WHERE a.w=b.y;
+ }] OpenTemp
+} {-1}
+do_test view-5.6 {
+ execsql {
+ SELECT * FROM t2 AS b, v5 AS a WHERE a.w=b.y;
+ }
+} {22 2 1 22 55 5 4 55}
+do_test view-5.7 {
+ lsearch [execsql {
+ EXPLAIN SELECT * FROM t2 AS b, v5 AS a WHERE a.w=b.y;
+ }] OpenTemp
+} {-1}
+do_test view-5.8 {
+ execsql {
+ SELECT * FROM t1 AS a, v5 AS b, t2 AS c WHERE a.x=b.v AND b.w=c.y;
+ }
+} {1 2 3 4 1 22 22 2 4 5 6 7 4 55 55 5}
+do_test view-5.9 {
+ lsearch [execsql {
+ EXPLAIN SELECT * FROM t1 AS a, v5 AS b, t2 AS c WHERE a.x=b.v AND b.w=c.y;
+ }] OpenTemp
+} {-1}
+
+do_test view-6.1 {
+ execsql {
+ SELECT min(x), min(a), min(b), min(c), min(a+b+c) FROM v2;
+ }
+} {7 8 9 10 27}
+do_test view-6.2 {
+ execsql {
+ SELECT max(x), max(a), max(b), max(c), max(a+b+c) FROM v2;
+ }
+} {11 12 13 14 39}
+
+do_test view-7.1 {
+ execsql {
+ CREATE TABLE test1(id integer primary key, a);
+ CREATE TABLE test2(id integer, b);
+ INSERT INTO test1 VALUES(1,2);
+ INSERT INTO test2 VALUES(1,3);
+ CREATE VIEW test AS
+ SELECT test1.id, a, b
+ FROM test1 JOIN test2 ON test2.id=test1.id;
+ SELECT * FROM test;
+ }
+} {1 2 3}
+do_test view-7.2 {
+ db close
+ sqlite db test.db
+ execsql {
+ SELECT * FROM test;
+ }
+} {1 2 3}
+do_test view-7.3 {
+ execsql {
+ DROP VIEW test;
+ CREATE VIEW test AS
+ SELECT test1.id, a, b
+ FROM test1 JOIN test2 USING(id);
+ SELECT * FROM test;
+ }
+} {1 2 3}
+do_test view-7.4 {
+ db close
+ sqlite db test.db
+ execsql {
+ SELECT * FROM test;
+ }
+} {1 2 3}
+do_test view-7.5 {
+ execsql {
+ DROP VIEW test;
+ CREATE VIEW test AS
+ SELECT test1.id, a, b
+ FROM test1 NATURAL JOIN test2;
+ SELECT * FROM test;
+ }
+} {1 2 3}
+do_test view-7.6 {
+ db close
+ sqlite db test.db
+ execsql {
+ SELECT * FROM test;
+ }
+} {1 2 3}
+
+do_test view-8.1 {
+ execsql {
+ CREATE VIEW v6 AS SELECT pqr, xyz FROM v1;
+ SELECT * FROM v6 ORDER BY xyz;
+ }
+} {7 2 13 5 19 8 27 12}
+do_test view-8.2 {
+ db close
+ sqlite db test.db
+ execsql {
+ SELECT * FROM v6 ORDER BY xyz;
+ }
+} {7 2 13 5 19 8 27 12}
+do_test view-8.3 {
+ execsql {
+ CREATE VIEW v7 AS SELECT pqr+xyz AS a FROM v6;
+ SELECT * FROM v7 ORDER BY a;
+ }
+} {9 18 27 39}
+do_test view-8.4 {
+ execsql {
+ CREATE VIEW v8 AS SELECT max(cnt) AS mx FROM
+ (SELECT a%2 AS eo, count(*) AS cnt FROM t1 GROUP BY eo);
+ SELECT * FROM v8;
+ }
+} 3
+do_test view-8.5 {
+ execsql {
+ SELECT mx+10, mx*2 FROM v8;
+ }
+} {13 6}
+do_test view-8.6 {
+ execsql {
+ SELECT mx+10, pqr FROM v6, v8 WHERE xyz=2;
+ }
+} {13 7}
+do_test view-8.7 {
+ execsql {
+ SELECT mx+10, pqr FROM v6, v8 WHERE xyz>2;
+ }
+} {13 13 13 19 13 27}
+
+# Tests for a bug found by Michiel de Wit involving ORDER BY in a VIEW.
+#
+do_test view-9.1 {
+ execsql {
+ INSERT INTO t2 SELECT * FROM t2 WHERE a<5;
+ INSERT INTO t2 SELECT * FROM t2 WHERE a<4;
+ INSERT INTO t2 SELECT * FROM t2 WHERE a<3;
+ SELECT DISTINCT count(*) FROM t2 GROUP BY a ORDER BY 1;
+ }
+} {1 2 4 8}
+do_test view-9.2 {
+ execsql {
+ SELECT DISTINCT count(*) FROM t2 GROUP BY a ORDER BY 1 LIMIT 3;
+ }
+} {1 2 4}
+do_test view-9.3 {
+ execsql {
+ CREATE VIEW v9 AS
+ SELECT DISTINCT count(*) FROM t2 GROUP BY a ORDER BY 1 LIMIT 3;
+ SELECT * FROM v9;
+ }
+} {1 2 4}
+do_test view-9.4 {
+ execsql {
+ SELECT * FROM v9 ORDER BY 1 DESC;
+ }
+} {4 2 1}
+do_test view-9.5 {
+ execsql {
+ CREATE VIEW v10 AS
+ SELECT DISTINCT a, count(*) FROM t2 GROUP BY a ORDER BY 2 LIMIT 3;
+ SELECT * FROM v10;
+ }
+} {5 1 4 2 3 4}
+do_test view-9.6 {
+ execsql {
+ SELECT * FROM v10 ORDER BY 1;
+ }
+} {3 4 4 2 5 1}
+
+# Tables with columns having peculiar quoted names used in views
+# Ticket #756.
+#
+do_test view-10.1 {
+ execsql {
+ CREATE TABLE t3("9" integer, [4] text);
+ INSERT INTO t3 VALUES(1,2);
+ CREATE VIEW v_t3_a AS SELECT a.[9] FROM t3 AS a;
+ CREATE VIEW v_t3_b AS SELECT "4" FROM t3;
+ SELECT * FROM v_t3_a;
+ }
+} {1}
+do_test view-10.2 {
+ execsql {
+ SELECT * FROM v_t3_b;
+ }
+} {2}
+
+
+finish_test
diff --git a/usr/src/lib/libsqlite/test/where.test b/usr/src/lib/libsqlite/test/where.test
new file mode 100644
index 0000000000..5671de9b7d
--- /dev/null
+++ b/usr/src/lib/libsqlite/test/where.test
@@ -0,0 +1,745 @@
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# 2001 September 15
+#
+# 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 use of indices in WHERE clases.
+#
+# $Id: where.test,v 1.17 2003/06/15 23:42:25 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Build some test data
+#
+do_test where-1.0 {
+ execsql {
+ CREATE TABLE t1(w int, x int, y int);
+ CREATE TABLE t2(p int, q int, r int, s int);
+ }
+ for {set i 1} {$i<=100} {incr i} {
+ set w $i
+ set x [expr {int(log($i)/log(2))}]
+ set y [expr {$i*$i + 2*$i + 1}]
+ execsql "INSERT INTO t1 VALUES($w,$x,$y)"
+ }
+ execsql {
+ INSERT INTO t2 SELECT 101-w, x, (SELECT max(y) FROM t1)+1-y, y FROM t1;
+ CREATE INDEX i1w ON t1(w);
+ CREATE INDEX i1xy ON t1(x,y);
+ CREATE INDEX i2p ON t2(p);
+ CREATE INDEX i2r ON t2(r);
+ CREATE INDEX i2qs ON t2(q, s);
+ }
+} {}
+
+# Do an SQL statement. Append the search count to the end of the result.
+#
+proc count sql {
+ set ::sqlite_search_count 0
+ return [concat [execsql $sql] $::sqlite_search_count]
+}
+
+# Verify that queries use an index. We are using the special variable
+# "sqlite_search_count" which tallys the number of executions of MoveTo
+# and Next operators in the VDBE. By verifing that the search count is
+# small we can be assured that indices are being used properly.
+#
+do_test where-1.1 {
+ count {SELECT x, y FROM t1 WHERE w=10}
+} {3 121 3}
+do_test where-1.2 {
+ count {SELECT x, y FROM t1 WHERE w=11}
+} {3 144 3}
+do_test where-1.3 {
+ count {SELECT x, y FROM t1 WHERE 11=w}
+} {3 144 3}
+do_test where-1.4 {
+ count {SELECT x, y FROM t1 WHERE 11=w AND x>2}
+} {3 144 3}
+do_test where-1.5 {
+ count {SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2}
+} {3 144 3}
+do_test where-1.6 {
+ count {SELECT x, y FROM t1 WHERE y<200 AND x>2 AND w=11}
+} {3 144 3}
+do_test where-1.7 {
+ count {SELECT x, y FROM t1 WHERE w=11 AND y<200 AND x>2}
+} {3 144 3}
+do_test where-1.8 {
+ count {SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3}
+} {3 144 3}
+do_test where-1.9 {
+ count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3}
+} {3 144 3}
+do_test where-1.10 {
+ count {SELECT x, y FROM t1 WHERE x=3 AND w>=10 AND y=121}
+} {3 121 3}
+do_test where-1.11 {
+ count {SELECT x, y FROM t1 WHERE x=3 AND y=100 AND w<10}
+} {3 100 3}
+
+# New for SQLite version 2.1: Verify that that inequality constraints
+# are used correctly.
+#
+do_test where-1.12 {
+ count {SELECT w FROM t1 WHERE x=3 AND y<100}
+} {8 3}
+do_test where-1.13 {
+ count {SELECT w FROM t1 WHERE x=3 AND 100>y}
+} {8 3}
+do_test where-1.14 {
+ count {SELECT w FROM t1 WHERE 3=x AND y<100}
+} {8 3}
+do_test where-1.15 {
+ count {SELECT w FROM t1 WHERE 3=x AND 100>y}
+} {8 3}
+do_test where-1.16 {
+ count {SELECT w FROM t1 WHERE x=3 AND y<=100}
+} {8 9 5}
+do_test where-1.17 {
+ count {SELECT w FROM t1 WHERE x=3 AND 100>=y}
+} {8 9 5}
+do_test where-1.18 {
+ count {SELECT w FROM t1 WHERE x=3 AND y>225}
+} {15 3}
+do_test where-1.19 {
+ count {SELECT w FROM t1 WHERE x=3 AND 225<y}
+} {15 3}
+do_test where-1.20 {
+ count {SELECT w FROM t1 WHERE x=3 AND y>=225}
+} {14 15 5}
+do_test where-1.21 {
+ count {SELECT w FROM t1 WHERE x=3 AND 225<=y}
+} {14 15 5}
+do_test where-1.22 {
+ count {SELECT w FROM t1 WHERE x=3 AND y>121 AND y<196}
+} {11 12 5}
+do_test where-1.23 {
+ count {SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<=196}
+} {10 11 12 13 9}
+do_test where-1.24 {
+ count {SELECT w FROM t1 WHERE x=3 AND 121<y AND 196>y}
+} {11 12 5}
+do_test where-1.25 {
+ count {SELECT w FROM t1 WHERE x=3 AND 121<=y AND 196>=y}
+} {10 11 12 13 9}
+
+# Need to work on optimizing the BETWEEN operator.
+#
+# do_test where-1.26 {
+# count {SELECT w FROM t1 WHERE x=3 AND y BETWEEN 121 AND 196}
+# } {10 11 12 13 9}
+
+do_test where-1.27 {
+ count {SELECT w FROM t1 WHERE x=3 AND y+1==122}
+} {10 17}
+do_test where-1.28 {
+ count {SELECT w FROM t1 WHERE x+1=4 AND y+1==122}
+} {10 99}
+do_test where-1.29 {
+ count {SELECT w FROM t1 WHERE y==121}
+} {10 99}
+
+
+do_test where-1.30 {
+ count {SELECT w FROM t1 WHERE w>97}
+} {98 99 100 6}
+do_test where-1.31 {
+ count {SELECT w FROM t1 WHERE w>=97}
+} {97 98 99 100 8}
+do_test where-1.33 {
+ count {SELECT w FROM t1 WHERE w==97}
+} {97 3}
+do_test where-1.34 {
+ count {SELECT w FROM t1 WHERE w+1==98}
+} {97 99}
+do_test where-1.35 {
+ count {SELECT w FROM t1 WHERE w<3}
+} {1 2 4}
+do_test where-1.36 {
+ count {SELECT w FROM t1 WHERE w<=3}
+} {1 2 3 6}
+do_test where-1.37 {
+ count {SELECT w FROM t1 WHERE w+1<=4 ORDER BY w}
+} {1 2 3 199}
+
+do_test where-1.38 {
+ count {SELECT (w) FROM t1 WHERE (w)>(97)}
+} {98 99 100 6}
+do_test where-1.39 {
+ count {SELECT (w) FROM t1 WHERE (w)>=(97)}
+} {97 98 99 100 8}
+do_test where-1.40 {
+ count {SELECT (w) FROM t1 WHERE (w)==(97)}
+} {97 3}
+do_test where-1.41 {
+ count {SELECT (w) FROM t1 WHERE ((w)+(1))==(98)}
+} {97 99}
+
+
+# Do the same kind of thing except use a join as the data source.
+#
+do_test where-2.1 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE x=q AND y=s AND r=8977
+ }
+} {34 67 6}
+do_test where-2.2 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE x=q AND s=y AND r=8977
+ }
+} {34 67 6}
+do_test where-2.3 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE x=q AND s=y AND r=8977 AND w>10
+ }
+} {34 67 6}
+do_test where-2.4 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE p<80 AND x=q AND s=y AND r=8977 AND w>10
+ }
+} {34 67 6}
+do_test where-2.5 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE p<80 AND x=q AND 8977=r AND s=y AND w>10
+ }
+} {34 67 6}
+do_test where-2.6 {
+ count {
+ SELECT w, p FROM t2, t1
+ WHERE x=q AND p=77 AND s=y AND w>5
+ }
+} {24 77 6}
+do_test where-2.7 {
+ count {
+ SELECT w, p FROM t1, t2
+ WHERE x=q AND p>77 AND s=y AND w=5
+ }
+} {5 96 6}
+
+# Lets do a 3-way join.
+#
+do_test where-3.1 {
+ count {
+ SELECT A.w, B.p, C.w FROM t1 as A, t2 as B, t1 as C
+ WHERE C.w=101-B.p AND B.r=10202-A.y AND A.w=11
+ }
+} {11 90 11 9}
+do_test where-3.2 {
+ count {
+ SELECT A.w, B.p, C.w FROM t1 as A, t2 as B, t1 as C
+ WHERE C.w=101-B.p AND B.r=10202-A.y AND A.w=12
+ }
+} {12 89 12 9}
+do_test where-3.3 {
+ count {
+ SELECT A.w, B.p, C.w FROM t1 as A, t2 as B, t1 as C
+ WHERE A.w=15 AND B.p=C.w AND B.r=10202-A.y
+ }
+} {15 86 86 9}
+
+# Test to see that the special case of a constant WHERE clause is
+# handled.
+#
+do_test where-4.1 {
+ count {
+ SELECT * FROM t1 WHERE 0
+ }
+} {0}
+do_test where-4.2 {
+ count {
+ SELECT * FROM t1 WHERE 1 LIMIT 1
+ }
+} {1 0 4 1}
+do_test where-4.3 {
+ execsql {
+ SELECT 99 WHERE 0
+ }
+} {}
+do_test where-4.4 {
+ execsql {
+ SELECT 99 WHERE 1
+ }
+} {99}
+
+# Verify that IN operators in a WHERE clause are handled correctly.
+#
+do_test where-5.1 {
+ count {
+ SELECT * FROM t1 WHERE rowid IN (1,2,3,1234) order by 1;
+ }
+} {1 0 4 2 1 9 3 1 16 0}
+do_test where-5.2 {
+ count {
+ SELECT * FROM t1 WHERE rowid+0 IN (1,2,3,1234) order by 1;
+ }
+} {1 0 4 2 1 9 3 1 16 199}
+do_test where-5.3 {
+ count {
+ SELECT * FROM t1 WHERE w IN (-1,1,2,3) order by 1;
+ }
+} {1 0 4 2 1 9 3 1 16 10}
+do_test where-5.4 {
+ count {
+ SELECT * FROM t1 WHERE w+0 IN (-1,1,2,3) order by 1;
+ }
+} {1 0 4 2 1 9 3 1 16 199}
+do_test where-5.5 {
+ count {
+ SELECT * FROM t1 WHERE rowid IN
+ (select rowid from t1 where rowid IN (-1,2,4))
+ ORDER BY 1;
+ }
+} {2 1 9 4 2 25 1}
+do_test where-5.6 {
+ count {
+ SELECT * FROM t1 WHERE rowid+0 IN
+ (select rowid from t1 where rowid IN (-1,2,4))
+ ORDER BY 1;
+ }
+} {2 1 9 4 2 25 199}
+do_test where-5.7 {
+ count {
+ SELECT * FROM t1 WHERE w IN
+ (select rowid from t1 where rowid IN (-1,2,4))
+ ORDER BY 1;
+ }
+} {2 1 9 4 2 25 7}
+do_test where-5.8 {
+ count {
+ SELECT * FROM t1 WHERE w+0 IN
+ (select rowid from t1 where rowid IN (-1,2,4))
+ ORDER BY 1;
+ }
+} {2 1 9 4 2 25 199}
+do_test where-5.9 {
+ count {
+ SELECT * FROM t1 WHERE x IN (1,7) ORDER BY 1;
+ }
+} {2 1 9 3 1 16 6}
+do_test where-5.10 {
+ count {
+ SELECT * FROM t1 WHERE x+0 IN (1,7) ORDER BY 1;
+ }
+} {2 1 9 3 1 16 199}
+do_test where-5.11 {
+ count {
+ SELECT * FROM t1 WHERE y IN (6400,8100) ORDER BY 1;
+ }
+} {79 6 6400 89 6 8100 199}
+do_test where-5.12 {
+ count {
+ SELECT * FROM t1 WHERE x=6 AND y IN (6400,8100) ORDER BY 1;
+ }
+} {79 6 6400 89 6 8100 74}
+do_test where-5.13 {
+ count {
+ SELECT * FROM t1 WHERE x IN (1,7) AND y NOT IN (6400,8100) ORDER BY 1;
+ }
+} {2 1 9 3 1 16 6}
+do_test where-5.14 {
+ count {
+ SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,10) ORDER BY 1;
+ }
+} {2 1 9 6}
+
+# This procedure executes the SQL. Then it checks the generated program
+# for the SQL and appends a "nosort" to the result if the program contains the
+# SortCallback opcode. If the program does not contain the SortCallback
+# opcode it appends "sort"
+#
+proc cksort {sql} {
+ set data [execsql $sql]
+ set prog [execsql "EXPLAIN $sql"]
+ if {[regexp SortCallback $prog]} {set x sort} {set x nosort}
+ lappend data $x
+ return $data
+}
+# Check out the logic that attempts to implement the ORDER BY clause
+# using an index rather than by sorting.
+#
+do_test where-6.1 {
+ execsql {
+ CREATE TABLE t3(a,b,c);
+ CREATE INDEX t3a ON t3(a);
+ CREATE INDEX t3bc ON t3(b,c);
+ CREATE INDEX t3acb ON t3(a,c,b);
+ INSERT INTO t3 SELECT w, 101-w, y FROM t1;
+ SELECT count(*), sum(a), sum(b), sum(c) FROM t3;
+ }
+} {100 5050 5050 348550}
+do_test where-6.2 {
+ cksort {
+ SELECT * FROM t3 ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 nosort}
+do_test where-6.3 {
+ cksort {
+ SELECT * FROM t3 ORDER BY a+1 LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 sort}
+do_test where-6.4 {
+ cksort {
+ SELECT * FROM t3 WHERE a<10 ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 nosort}
+do_test where-6.5 {
+ cksort {
+ SELECT * FROM t3 WHERE a>0 AND a<10 ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 nosort}
+do_test where-6.6 {
+ cksort {
+ SELECT * FROM t3 WHERE a>0 ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 nosort}
+do_test where-6.7 {
+ cksort {
+ SELECT * FROM t3 WHERE b>0 ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 sort}
+do_test where-6.8 {
+ cksort {
+ SELECT * FROM t3 WHERE a IN (3,5,7,1,9,4,2) ORDER BY a LIMIT 3
+ }
+} {1 100 4 2 99 9 3 98 16 sort}
+do_test where-6.9.1 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test where-6.9.2 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a,c LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test where-6.9.3 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY c LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test where-6.9.4 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a DESC LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test where-6.9.5 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a DESC, c DESC LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test where-6.9.6 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY c DESC LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test where-6.9.7 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY c,a LIMIT 3
+ }
+} {1 100 4 sort}
+do_test where-6.9.8 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a DESC, c ASC LIMIT 3
+ }
+} {1 100 4 sort}
+do_test where-6.9.9 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a ASC, c DESC LIMIT 3
+ }
+} {1 100 4 sort}
+do_test where-6.10 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test where-6.11 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a,c LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test where-6.12 {
+ cksort {
+ SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a,c,b LIMIT 3
+ }
+} {1 100 4 nosort}
+do_test where-6.13 {
+ cksort {
+ SELECT * FROM t3 WHERE a>0 ORDER BY a DESC LIMIT 3
+ }
+} {100 1 10201 99 2 10000 98 3 9801 nosort}
+do_test where-6.13.1 {
+ cksort {
+ SELECT * FROM t3 WHERE a>0 ORDER BY -a LIMIT 3
+ }
+} {100 1 10201 99 2 10000 98 3 9801 sort}
+do_test where-6.14 {
+ cksort {
+ SELECT * FROM t3 ORDER BY b LIMIT 3
+ }
+} {100 1 10201 99 2 10000 98 3 9801 nosort}
+do_test where-6.15 {
+ cksort {
+ SELECT t3.a, t1.x FROM t3, t1 WHERE t3.a=t1.w ORDER BY t3.a LIMIT 3
+ }
+} {1 0 2 1 3 1 nosort}
+do_test where-6.16 {
+ cksort {
+ SELECT t3.a, t1.x FROM t3, t1 WHERE t3.a=t1.w ORDER BY t1.x, t3.a LIMIT 3
+ }
+} {1 0 2 1 3 1 sort}
+do_test where-6.17 {
+ cksort {
+ SELECT y FROM t1 ORDER BY w COLLATE text LIMIT 3;
+ }
+} {4 121 10201 sort}
+do_test where-6.18 {
+ cksort {
+ SELECT y FROM t1 ORDER BY w COLLATE numeric LIMIT 3;
+ }
+} {4 9 16 sort}
+do_test where-6.19 {
+ cksort {
+ SELECT y FROM t1 ORDER BY w LIMIT 3;
+ }
+} {4 9 16 nosort}
+
+# Tests for reverse-order sorting.
+#
+do_test where-7.1 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 ORDER BY y;
+ }
+} {8 9 10 11 12 13 14 15 nosort}
+do_test where-7.2 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 ORDER BY y DESC;
+ }
+} {15 14 13 12 11 10 9 8 nosort}
+do_test where-7.3 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>100 ORDER BY y LIMIT 3;
+ }
+} {10 11 12 nosort}
+do_test where-7.4 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>100 ORDER BY y DESC LIMIT 3;
+ }
+} {15 14 13 nosort}
+do_test where-7.5 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>121 ORDER BY y DESC;
+ }
+} {15 14 13 12 11 nosort}
+do_test where-7.6 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>=121 ORDER BY y DESC;
+ }
+} {15 14 13 12 11 10 nosort}
+do_test where-7.7 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<196 ORDER BY y DESC;
+ }
+} {12 11 10 nosort}
+do_test where-7.8 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<=196 ORDER BY y DESC;
+ }
+} {13 12 11 10 nosort}
+do_test where-7.9 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>121 AND y<=196 ORDER BY y DESC;
+ }
+} {13 12 11 nosort}
+do_test where-7.10 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>100 AND y<196 ORDER BY y DESC;
+ }
+} {12 11 10 nosort}
+do_test where-7.11 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<196 ORDER BY y;
+ }
+} {10 11 12 nosort}
+do_test where-7.12 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<=196 ORDER BY y;
+ }
+} {10 11 12 13 nosort}
+do_test where-7.13 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>121 AND y<=196 ORDER BY y;
+ }
+} {11 12 13 nosort}
+do_test where-7.14 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>100 AND y<196 ORDER BY y;
+ }
+} {10 11 12 nosort}
+do_test where-7.15 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y<81 ORDER BY y;
+ }
+} {nosort}
+do_test where-7.16 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y<=81 ORDER BY y;
+ }
+} {8 nosort}
+do_test where-7.17 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>256 ORDER BY y;
+ }
+} {nosort}
+do_test where-7.18 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>=256 ORDER BY y;
+ }
+} {15 nosort}
+do_test where-7.19 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y<81 ORDER BY y DESC;
+ }
+} {nosort}
+do_test where-7.20 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y<=81 ORDER BY y DESC;
+ }
+} {8 nosort}
+do_test where-7.21 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>256 ORDER BY y DESC;
+ }
+} {nosort}
+do_test where-7.22 {
+ cksort {
+ SELECT w FROM t1 WHERE x=3 AND y>=256 ORDER BY y DESC;
+ }
+} {15 nosort}
+do_test where-7.23 {
+ cksort {
+ SELECT w FROM t1 WHERE x=0 AND y<4 ORDER BY y;
+ }
+} {nosort}
+do_test where-7.24 {
+ cksort {
+ SELECT w FROM t1 WHERE x=0 AND y<=4 ORDER BY y;
+ }
+} {1 nosort}
+do_test where-7.25 {
+ cksort {
+ SELECT w FROM t1 WHERE x=6 AND y>10201 ORDER BY y;
+ }
+} {nosort}
+do_test where-7.26 {
+ cksort {
+ SELECT w FROM t1 WHERE x=6 AND y>=10201 ORDER BY y;
+ }
+} {100 nosort}
+do_test where-7.27 {
+ cksort {
+ SELECT w FROM t1 WHERE x=0 AND y<4 ORDER BY y DESC;
+ }
+} {nosort}
+do_test where-7.28 {
+ cksort {
+ SELECT w FROM t1 WHERE x=0 AND y<=4 ORDER BY y DESC;
+ }
+} {1 nosort}
+do_test where-7.29 {
+ cksort {
+ SELECT w FROM t1 WHERE x=6 AND y>10201 ORDER BY y DESC;
+ }
+} {nosort}
+do_test where-7.30 {
+ cksort {
+ SELECT w FROM t1 WHERE x=6 AND y>=10201 ORDER BY y DESC;
+ }
+} {100 nosort}
+
+do_test where-8.1 {
+ execsql {
+ CREATE TABLE t4 AS SELECT * FROM t1;
+ CREATE INDEX i4xy ON t4(x,y);
+ }
+ cksort {
+ SELECT w FROM t4 WHERE x=4 and y<1000 ORDER BY y DESC limit 3;
+ }
+} {30 29 28 nosort}
+do_test where-8.2 {
+ execsql {
+ DELETE FROM t4;
+ }
+ cksort {
+ SELECT w FROM t4 WHERE x=4 and y<1000 ORDER BY y DESC limit 3;
+ }
+} {nosort}
+
+# Make sure searches with an index work with an empty table.
+#
+do_test where-9.1 {
+ execsql {
+ CREATE TABLE t5(x PRIMARY KEY);
+ SELECT * FROM t5 WHERE x<10;
+ }
+} {}
+do_test where-9.2 {
+ execsql {
+ SELECT * FROM t5 WHERE x<10 ORDER BY x DESC;
+ }
+} {}
+do_test where-9.3 {
+ execsql {
+ SELECT * FROM t5 WHERE x=10;
+ }
+} {}
+
+do_test where-10.1 {
+ execsql {
+ SELECT 1 WHERE abs(random())<0
+ }
+} {}
+do_test where-10.2 {
+ proc tclvar_func {vname} {return [set ::$vname]}
+ db function tclvar tclvar_func
+ set ::v1 0
+ execsql {
+ SELECT count(*) FROM t1 WHERE tclvar('v1');
+ }
+} {0}
+do_test where-10.3 {
+ set ::v1 1
+ execsql {
+ SELECT count(*) FROM t1 WHERE tclvar('v1');
+ }
+} {100}
+do_test where-10.4 {
+ set ::v1 1
+ proc tclvar_func {vname} {
+ upvar #0 $vname v
+ set v [expr {!$v}]
+ return $v
+ }
+ execsql {
+ SELECT count(*) FROM t1 WHERE tclvar('v1');
+ }
+} {50}
+
+integrity_check {where-99.0}
+
+finish_test