------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Revised\sdocumentation\sfor\ssqlite3_limit().\s\sAdded\ssome\sevidence\smarks\sand\nassert()\sstatements\sto\sverify\ssqlite3_limit()\sbehavior.
-D 2010-09-07T14:59:16
+C Add\stests\sto\se_select.test.
+D 2010-09-07T19:05:28
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in c599a15d268b1db2aeadea19df2adc3bf2eb6bee
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F test/e_expr.test 164e87c1d7b40ceb47c57c3bffa384c81d009aa7
F test/e_fkey.test 6721a741c6499b3ab7e5385923233343c8f1ad05
F test/e_fts3.test 75bb0aee26384ef586165e21018a17f7cd843469
-F test/e_select.test 0c491c94d69adad307fbd331530c012f64984b7a
+F test/e_select.test 844c606826d19583ca6230575bc9685a4124c19c
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P bd700794678613c1fb78ef9fcf2bcd6d48f70dc0
-R 69716d22de4bcacc6f3b2e000a39c9a7
-U drh
-Z 5525c419763660d5eabe8aec9d844974
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFMhlNHoxKgR168RlERAob+AJ9myxkLwt0lv7Z/fVE48Z/mxrAPdQCeKHEr
-v8vaa6Ji96D59ok+PxHqpsk=
-=85Kf
------END PGP SIGNATURE-----
+P 883b9b7441593200def05d8a482bc92d3dc0e96b
+R 8b30d0d15d657e8276f598400d6535e3
+U dan
+Z 9e885c5619cc6ac3f51310d78881d4f0
" {1 {a NATURAL join may not have an ON or USING clause}}
}
+
+#-------
+# Usage: tcl_join <table-data1> <table-data2> <join spec>...
+#
+# Where a join-spec is an optional list of arguments as follows:
+#
+# ?-left?
+# ?-using colname-list using-expr-proc?
+# ?-on on-expr-proc?
+#
+proc tcl_join {data1 data2 args} {
+
+ set testproc ""
+ set usinglist [list]
+ set isleft 0
+ for {set i 0} {$i < [llength $args]} {incr i} {
+ set a [lindex $args $i]
+ switch -- $a {
+ -on { set testproc [lindex $args [incr i]] }
+ -using {
+ set usinglist [lindex $args [incr i]]
+ }
+ -left {
+ set isleft 1
+ }
+
+ default {
+ error "Unknown argument: $a"
+ }
+ }
+ }
+
+ set c1 [lindex $data1 0]
+ set c2 [lindex $data2 0]
+ set omitlist [list]
+ set nullrowlist [list]
+ set cret $c1
+
+ set cidx 0
+ foreach col $c2 {
+ set idx [lsearch $usinglist $col]
+ if {$idx>=0} {lappend omitlist $cidx}
+ if {$idx<0} {
+ lappend nullrowlist {NULL {}}
+ lappend cret $col
+ }
+ incr cidx
+ }
+ set omitlist [lsort -integer -decreasing $omitlist]
+
+
+ set rret [list]
+ foreach r1 [lindex $data1 1] {
+ set one 0
+ foreach r2 [lindex $data2 1] {
+ set ok 1
+ if {$testproc != ""} {
+ set ok [eval $testproc [list $c1 $r1 $c2 $r2]]
+ }
+ if {$ok} {
+ set one 1
+ foreach idx $omitlist {set r2 [lreplace $r2 $idx $idx]}
+ lappend rret [concat $r1 $r2]
+ }
+ }
+
+ if {$isleft && $one==0} {
+ lappend rret [concat $r1 $nullrowlist]
+ }
+ }
+
+ list $cret $rret
+}
+
+proc tcl_tbljoin {db t1 t2 args} {
+ tcl_join [tcl_read_tbl $db $t1] [tcl_read_tbl $db $t2] {*}$args
+}
+
+#----------
+# te_equals ?SWITCHES? c1 c2 cols1 row1 cols2 row2
+#
+proc te_equals {args} {
+
+ if {[llength $args]<6} {error "invalid arguments to te_equals"}
+ foreach {c1 c2 cols1 row1 cols2 row2} [lrange $args end-5 end] break
+
+ set nocase 0
+
+ foreach a [lrange $args 0 end-6] {
+ switch -- $a {
+ -nocase {
+ set nocase 1
+ }
+ default {
+ error "invalid arguments to te_equals"
+ }
+ }
+ }
+
+ set idx1 [lsearch $cols1 $c1]
+ set idx2 [lsearch $cols2 $c2]
+
+ set t1 [lindex $row1 $idx1 0]
+ set t2 [lindex $row2 $idx2 0]
+ set v1 [lindex $row1 $idx1 1]
+ set v2 [lindex $row2 $idx2 1]
+
+ if {$t1 == "NULL" || $t2 == "NULL"} { return 0 }
+ if {$nocase && $t1 == "TEXT"} { set v1 [string tolower $v1] }
+ if {$nocase && $t2 == "TEXT"} { set v2 [string tolower $v2] }
+ return [expr {$t1 == $t2 && $v1 == $v2}]
+}
+
+proc te_and {args} {
+ foreach a [lrange $args 0 end-4] {
+ set res [eval $a [lrange $args end-3 end]]
+ if {$res == 0} {return 0}
+ }
+ return 1
+}
+
+# Read the
+#
+# Table data format:
+#
+# * List of column names.
+#
+# * List of rows. Each row is a list of values. Each value is a list of
+# 2 elements - the value type and string representation.
+#
+proc tcl_read_tbl {db tbl} { tcl_read_sql $db "SELECT * FROM $tbl" }
+
+proc tcl_read_sql {db sql} {
+ set S [sqlite3_prepare_v2 $db $sql -1 DUMMY]
+
+ set cols [list]
+ for {set i 0} {$i < [sqlite3_column_count $S]} {incr i} {
+ lappend cols [sqlite3_column_name $S $i]
+ }
+
+ set rows [list]
+ while {[sqlite3_step $S] == "SQLITE_ROW"} {
+ set r [list]
+ for {set i 0} {$i < [sqlite3_column_count $S]} {incr i} {
+ lappend r [list [sqlite3_column_type $S $i] [sqlite3_column_text $S $i]]
+ }
+ lappend rows $r
+ }
+ sqlite3_finalize $S
+
+ return [list $cols $rows]
+}
+
+drop_all_tables
+do_execsql_test e_select-2.0 {
+ CREATE TABLE t1(a, b);
+ CREATE TABLE t2(a, b);
+ CREATE TABLE t3(b COLLATE nocase);
+
+ INSERT INTO t1 VALUES(1, 'A');
+ INSERT INTO t1 VALUES(2, 'B');
+ INSERT INTO t1 VALUES(3, NULL);
+ INSERT INTO t1 VALUES(4, 'D');
+ INSERT INTO t1 VALUES(NULL, NULL);
+
+ INSERT INTO t2 VALUES(1, 'A');
+ INSERT INTO t2 VALUES(2, NULL);
+ INSERT INTO t2 VALUES(3, 'C');
+ INSERT INTO t2 VALUES(5, 'E');
+ INSERT INTO t2 VALUES(NULL, NULL);
+
+ INSERT INTO t3 VALUES('a');
+ INSERT INTO t3 VALUES('b');
+ INSERT INTO t3 VALUES('c');
+} {}
+
+foreach {tn sqljoin tbljoinargs} {
+ 1 "t1, t2" {t1 t2}
+ 2 "t1, t2 ON (t1.a=t2.a)" {t1 t2 -on {te_equals a a}}
+ 3 "t1 LEFT JOIN t2 ON (t1.a=t2.a)" {t1 t2 -left -on {te_equals a a}}
+ 4 "t1 LEFT JOIN t2 USING (a)"
+ {t1 t2 -left -using a -on {te_equals a a}}
+
+ 5 "t1 CROSS JOIN t2 USING(b, a)"
+ {t1 t2 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+
+ 6 "t1 NATURAL JOIN t2"
+ {t1 t2 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+ 7 "t1 NATURAL INNER JOIN t2"
+ {t1 t2 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+ 8 "t1 NATURAL CROSS JOIN t2"
+ {t1 t2 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+ 9 "t1 NATURAL INNER JOIN t2"
+ {t1 t2 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+ 10 "t1 NATURAL LEFT JOIN t2"
+ {t1 t2 -left -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+ 11 "t1 NATURAL LEFT OUTER JOIN t2"
+ {t1 t2 -left -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+
+ 12 "t2 NATURAL JOIN t1"
+ {t2 t1 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+ 13 "t2 NATURAL INNER JOIN t1"
+ {t2 t1 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+ 14 "t2 NATURAL CROSS JOIN t1"
+ {t2 t1 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+ 15 "t2 NATURAL INNER JOIN t1"
+ {t2 t1 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+ 16 "t2 NATURAL LEFT JOIN t1"
+ {t2 t1 -left -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+ 17 "t2 NATURAL LEFT OUTER JOIN t1"
+ {t2 t1 -left -using {a b} -on {te_and {te_equals a a} {te_equals b b}}}
+
+ 18 "t1 LEFT JOIN t2 USING (b)"
+ {t1 t2 -left -using b -on {te_equals b b}}
+
+ 19 "t1 JOIN t3 USING(b)" {t1 t3 -using b -on {te_equals b b}}
+ 20 "t3 JOIN t1 USING(b)" {t3 t1 -using b -on {te_equals -nocase b b}}
+ 21 "t1 NATURAL JOIN t3" {t1 t3 -using b -on {te_equals b b}}
+ 22 "t3 NATURAL JOIN t1" {t3 t1 -using b -on {te_equals -nocase b b}}
+ 23 "t1 NATURAL LEFT JOIN t3" {t1 t3 -left -using b -on {te_equals b b}}
+ 24 "t3 NATURAL LEFT JOIN t1"
+ {t3 t1 -left -using b -on {te_equals -nocase b b}}
+
+ 25 "t1 LEFT JOIN t3 ON (t3.b=t1.b)"
+ {t1 t3 -left -on {te_equals -nocase b b}}
+ 26 "t1 LEFT JOIN t3 ON (t1.b=t3.b)"
+ {t1 t3 -left -on {te_equals b b}}
+
+} {
+
+ do_test e_select-2.1.$tn [list tcl_read_sql db "SELECT * FROM $sqljoin"
+ ] [tcl_tbljoin db {*}$tbljoinargs]
+
+}
+
finish_test
+