Annotation of embedaddon/sqlite3/test/e_select2.test, revision 1.1
1.1 ! misho 1: # 2010 September 24
! 2: #
! 3: # The author disclaims copyright to this source code. In place of
! 4: # a legal notice, here is a blessing:
! 5: #
! 6: # May you do good and not evil.
! 7: # May you find forgiveness for yourself and forgive others.
! 8: # May you share freely, never taking more than you give.
! 9: #
! 10: #***********************************************************************
! 11: #
! 12: # This file implements tests to verify that the "testable statements" in
! 13: # the lang_select.html document are correct.
! 14: #
! 15:
! 16: set testdir [file dirname $argv0]
! 17: source $testdir/tester.tcl
! 18:
! 19: #-------------------------------------------------------------------------
! 20: # te_* commands:
! 21: #
! 22: #
! 23: # te_read_sql DB SELECT-STATEMENT
! 24: # te_read_tbl DB TABLENAME
! 25: #
! 26: # These two commands are used to read a dataset from the database. A dataset
! 27: # consists of N rows of M named columns of values each, where each value has a
! 28: # type (null, integer, real, text or blob) and a value within the types domain.
! 29: # The tcl format for a "dataset" is a list of two elements:
! 30: #
! 31: # * A list of the column names.
! 32: # * A list of data rows. Each row is itself a list, where each element is
! 33: # the contents of a column of the row. Each of these is a list of two
! 34: # elements, the type name and the actual value.
! 35: #
! 36: # For example, the contents of table [t1] as a dataset is:
! 37: #
! 38: # CREATE TABLE t1(a, b);
! 39: # INSERT INTO t1 VALUES('abc', NULL);
! 40: # INSERT INTO t1 VALUES(43.1, 22);
! 41: #
! 42: # {a b} {{{TEXT abc} {NULL {}}} {{REAL 43.1} {INTEGER 22}}}
! 43: #
! 44: # The [te_read_tbl] command returns a dataset read from a table. The
! 45: # [te_read_sql] returns the dataset that results from executing a SELECT
! 46: # command.
! 47: #
! 48: #
! 49: # te_tbljoin ?SWITCHES? LHS-TABLE RHS-TABLE
! 50: # te_join ?SWITCHES? LHS-DATASET RHS-DATASET
! 51: #
! 52: # This command joins the two datasets and returns the resulting dataset. If
! 53: # there are no switches specified, then the results is the cartesian product
! 54: # of the two inputs. The [te_tbljoin] command reads the left and right-hand
! 55: # datasets from the specified tables. The [te_join] command is passed the
! 56: # datasets directly.
! 57: #
! 58: # Optional switches are as follows:
! 59: #
! 60: # -on SCRIPT
! 61: # -using COLUMN-LIST
! 62: # -left
! 63: #
! 64: # The -on option specifies a tcl script that is executed for each row in the
! 65: # cartesian product of the two datasets. The script has 4 arguments appended
! 66: # to it, in the following order:
! 67: #
! 68: # * The list of column-names from the left-hand dataset.
! 69: # * A single row from the left-hand dataset (one "data row" list as
! 70: # described above.
! 71: # * The list of column-names from the right-hand dataset.
! 72: # * A single row from the right-hand dataset.
! 73: #
! 74: # The script must return a boolean value - true if the combination of rows
! 75: # should be included in the output dataset, or false otherwise.
! 76: #
! 77: # The -using option specifies a list of the columns from the right-hand
! 78: # dataset that should be omitted from the output dataset.
! 79: #
! 80: # If the -left option is present, the join is done LEFT JOIN style.
! 81: # Specifically, an extra row is inserted if after the -on script is run there
! 82: # exist rows in the left-hand dataset that have no corresponding rows in
! 83: # the output. See the implementation for more specific comments.
! 84: #
! 85: #
! 86: # te_equals ?SWITCHES? COLNAME1 COLNAME2 <-on script args>
! 87: #
! 88: # The only supported switch is "-nocase". If it is present, then text values
! 89: # are compared in a case-independent fashion. Otherwise, they are compared
! 90: # as if using the SQLite BINARY collation sequence.
! 91: #
! 92: #
! 93: # te_and ONSCRIPT1 ONSCRIPT2...
! 94: #
! 95: #
! 96:
! 97:
! 98: #
! 99: # te_read_tbl DB TABLENAME
! 100: # te_read_sql DB SELECT-STATEMENT
! 101: #
! 102: # These two procs are used to extract datasets from the database, either
! 103: # by reading the contents of a named table (te_read_tbl), or by executing
! 104: # a SELECT statement (t3_read_sql).
! 105: #
! 106: # See the comment above, describing "te_* commands", for details of the
! 107: # return values.
! 108: #
! 109: proc te_read_tbl {db tbl} {
! 110: te_read_sql $db "SELECT * FROM '$tbl'"
! 111: }
! 112: proc te_read_sql {db sql} {
! 113: set S [sqlite3_prepare_v2 $db $sql -1 DUMMY]
! 114:
! 115: set cols [list]
! 116: for {set i 0} {$i < [sqlite3_column_count $S]} {incr i} {
! 117: lappend cols [sqlite3_column_name $S $i]
! 118: }
! 119:
! 120: set rows [list]
! 121: while {[sqlite3_step $S] == "SQLITE_ROW"} {
! 122: set r [list]
! 123: for {set i 0} {$i < [sqlite3_column_count $S]} {incr i} {
! 124: lappend r [list [sqlite3_column_type $S $i] [sqlite3_column_text $S $i]]
! 125: }
! 126: lappend rows $r
! 127: }
! 128: sqlite3_finalize $S
! 129:
! 130: return [list $cols $rows]
! 131: }
! 132:
! 133: #-------
! 134: # Usage: te_join <table-data1> <table-data2> <join spec>...
! 135: #
! 136: # Where a join-spec is an optional list of arguments as follows:
! 137: #
! 138: # ?-left?
! 139: # ?-using colname-list?
! 140: # ?-on on-expr-proc?
! 141: #
! 142: proc te_join {data1 data2 args} {
! 143:
! 144: set testproc ""
! 145: set usinglist [list]
! 146: set isleft 0
! 147: for {set i 0} {$i < [llength $args]} {incr i} {
! 148: set a [lindex $args $i]
! 149: switch -- $a {
! 150: -on { set testproc [lindex $args [incr i]] }
! 151: -using { set usinglist [lindex $args [incr i]] }
! 152: -left { set isleft 1 }
! 153: default {
! 154: error "Unknown argument: $a"
! 155: }
! 156: }
! 157: }
! 158:
! 159: set c1 [lindex $data1 0]
! 160: set c2 [lindex $data2 0]
! 161: set omitlist [list]
! 162: set nullrowlist [list]
! 163: set cret $c1
! 164:
! 165: set cidx 0
! 166: foreach col $c2 {
! 167: set idx [lsearch $usinglist $col]
! 168: if {$idx>=0} {lappend omitlist $cidx}
! 169: if {$idx<0} {
! 170: lappend nullrowlist {NULL {}}
! 171: lappend cret $col
! 172: }
! 173: incr cidx
! 174: }
! 175: set omitlist [lsort -integer -decreasing $omitlist]
! 176:
! 177:
! 178: set rret [list]
! 179: foreach r1 [lindex $data1 1] {
! 180: set one 0
! 181: foreach r2 [lindex $data2 1] {
! 182: set ok 1
! 183: if {$testproc != ""} {
! 184: set ok [eval $testproc [list $c1 $r1 $c2 $r2]]
! 185: }
! 186: if {$ok} {
! 187: set one 1
! 188: foreach idx $omitlist {set r2 [lreplace $r2 $idx $idx]}
! 189: lappend rret [concat $r1 $r2]
! 190: }
! 191: }
! 192:
! 193: if {$isleft && $one==0} {
! 194: lappend rret [concat $r1 $nullrowlist]
! 195: }
! 196: }
! 197:
! 198: list $cret $rret
! 199: }
! 200:
! 201: proc te_tbljoin {db t1 t2 args} {
! 202: te_join [te_read_tbl $db $t1] [te_read_tbl $db $t2] {*}$args
! 203: }
! 204:
! 205: proc te_apply_affinity {affinity typevar valvar} {
! 206: upvar $typevar type
! 207: upvar $valvar val
! 208:
! 209: switch -- $affinity {
! 210: integer {
! 211: if {[string is double $val]} { set type REAL }
! 212: if {[string is wideinteger $val]} { set type INTEGER }
! 213: if {$type == "REAL" && int($val)==$val} {
! 214: set type INTEGER
! 215: set val [expr {int($val)}]
! 216: }
! 217: }
! 218: text {
! 219: set type TEXT
! 220: }
! 221: none { }
! 222:
! 223: default { error "invalid affinity: $affinity" }
! 224: }
! 225: }
! 226:
! 227: #----------
! 228: # te_equals ?SWITCHES? c1 c2 cols1 row1 cols2 row2
! 229: #
! 230: proc te_equals {args} {
! 231:
! 232: if {[llength $args]<6} {error "invalid arguments to te_equals"}
! 233: foreach {c1 c2 cols1 row1 cols2 row2} [lrange $args end-5 end] break
! 234:
! 235: set nocase 0
! 236: set affinity none
! 237:
! 238: for {set i 0} {$i < ([llength $args]-6)} {incr i} {
! 239: set a [lindex $args $i]
! 240: switch -- $a {
! 241: -nocase {
! 242: set nocase 1
! 243: }
! 244: -affinity {
! 245: set affinity [string tolower [lindex $args [incr i]]]
! 246: }
! 247: default {
! 248: error "invalid arguments to te_equals"
! 249: }
! 250: }
! 251: }
! 252:
! 253: set idx2 [if {[string is integer $c2]} { set c2 } else { lsearch $cols2 $c2 }]
! 254: set idx1 [if {[string is integer $c1]} { set c1 } else { lsearch $cols1 $c1 }]
! 255:
! 256: set t1 [lindex $row1 $idx1 0]
! 257: set t2 [lindex $row2 $idx2 0]
! 258: set v1 [lindex $row1 $idx1 1]
! 259: set v2 [lindex $row2 $idx2 1]
! 260:
! 261: te_apply_affinity $affinity t1 v1
! 262: te_apply_affinity $affinity t2 v2
! 263:
! 264: if {$t1 == "NULL" || $t2 == "NULL"} { return 0 }
! 265: if {$nocase && $t1 == "TEXT"} { set v1 [string tolower $v1] }
! 266: if {$nocase && $t2 == "TEXT"} { set v2 [string tolower $v2] }
! 267:
! 268:
! 269: set res [expr {$t1 == $t2 && [string equal $v1 $v2]}]
! 270: return $res
! 271: }
! 272:
! 273: proc te_false {args} { return 0 }
! 274: proc te_true {args} { return 1 }
! 275:
! 276: proc te_and {args} {
! 277: foreach a [lrange $args 0 end-4] {
! 278: set res [eval $a [lrange $args end-3 end]]
! 279: if {$res == 0} {return 0}
! 280: }
! 281: return 1
! 282: }
! 283:
! 284:
! 285: proc te_dataset_eq {testname got expected} {
! 286: uplevel #0 [list do_test $testname [list set {} $got] $expected]
! 287: }
! 288: proc te_dataset_eq_unordered {testname got expected} {
! 289: lset got 1 [lsort [lindex $got 1]]
! 290: lset expected 1 [lsort [lindex $expected 1]]
! 291: te_dataset_eq $testname $got $expected
! 292: }
! 293:
! 294: proc te_dataset_ne {testname got unexpected} {
! 295: uplevel #0 [list do_test $testname [list string equal $got $unexpected] 0]
! 296: }
! 297: proc te_dataset_ne_unordered {testname got unexpected} {
! 298: lset got 1 [lsort [lindex $got 1]]
! 299: lset unexpected 1 [lsort [lindex $unexpected 1]]
! 300: te_dataset_ne $testname $got $unexpected
! 301: }
! 302:
! 303:
! 304: #-------------------------------------------------------------------------
! 305: #
! 306: proc test_join {tn sqljoin tbljoinargs} {
! 307: set sql [te_read_sql db "SELECT * FROM $sqljoin"]
! 308: set te [te_tbljoin db {*}$tbljoinargs]
! 309: te_dataset_eq_unordered $tn $sql $te
! 310: }
! 311:
! 312: drop_all_tables
! 313: do_execsql_test e_select-2.0 {
! 314: CREATE TABLE t1(a, b);
! 315: CREATE TABLE t2(a, b);
! 316: CREATE TABLE t3(b COLLATE nocase);
! 317:
! 318: INSERT INTO t1 VALUES(2, 'B');
! 319: INSERT INTO t1 VALUES(1, 'A');
! 320: INSERT INTO t1 VALUES(4, 'D');
! 321: INSERT INTO t1 VALUES(NULL, NULL);
! 322: INSERT INTO t1 VALUES(3, NULL);
! 323:
! 324: INSERT INTO t2 VALUES(1, 'A');
! 325: INSERT INTO t2 VALUES(2, NULL);
! 326: INSERT INTO t2 VALUES(5, 'E');
! 327: INSERT INTO t2 VALUES(NULL, NULL);
! 328: INSERT INTO t2 VALUES(3, 'C');
! 329:
! 330: INSERT INTO t3 VALUES('a');
! 331: INSERT INTO t3 VALUES('c');
! 332: INSERT INTO t3 VALUES('b');
! 333: } {}
! 334:
! 335: foreach {tn indexes} {
! 336: e_select-2.1.1 { }
! 337: e_select-2.1.2 { CREATE INDEX i1 ON t1(a) }
! 338: e_select-2.1.3 { CREATE INDEX i1 ON t2(a) }
! 339: e_select-2.1.4 { CREATE INDEX i1 ON t3(b) }
! 340: } {
! 341:
! 342: catchsql { DROP INDEX i1 }
! 343: catchsql { DROP INDEX i2 }
! 344: catchsql { DROP INDEX i3 }
! 345: execsql $indexes
! 346:
! 347: # EVIDENCE-OF: R-46122-14930 If the join-op is "CROSS JOIN", "INNER
! 348: # JOIN", "JOIN" or a comma (",") and there is no ON or USING clause,
! 349: # then the result of the join is simply the cartesian product of the
! 350: # left and right-hand datasets.
! 351: #
! 352: # EVIDENCE-OF: R-46256-57243 There is no difference between the "INNER
! 353: # JOIN", "JOIN" and "," join operators.
! 354: #
! 355: # EVIDENCE-OF: R-07544-24155 The "CROSS JOIN" join operator produces the
! 356: # same data as the "INNER JOIN", "JOIN" and "," operators
! 357: #
! 358: test_join $tn.1.1 "t1, t2" {t1 t2}
! 359: test_join $tn.1.2 "t1 INNER JOIN t2" {t1 t2}
! 360: test_join $tn.1.3 "t1 CROSS JOIN t2" {t1 t2}
! 361: test_join $tn.1.4 "t1 JOIN t2" {t1 t2}
! 362: test_join $tn.1.5 "t2, t3" {t2 t3}
! 363: test_join $tn.1.6 "t2 INNER JOIN t3" {t2 t3}
! 364: test_join $tn.1.7 "t2 CROSS JOIN t3" {t2 t3}
! 365: test_join $tn.1.8 "t2 JOIN t3" {t2 t3}
! 366: test_join $tn.1.9 "t2, t2 AS x" {t2 t2}
! 367: test_join $tn.1.10 "t2 INNER JOIN t2 AS x" {t2 t2}
! 368: test_join $tn.1.11 "t2 CROSS JOIN t2 AS x" {t2 t2}
! 369: test_join $tn.1.12 "t2 JOIN t2 AS x" {t2 t2}
! 370:
! 371: # EVIDENCE-OF: R-22775-56496 If there is an ON clause specified, then
! 372: # the ON expression is evaluated for each row of the cartesian product
! 373: # as a boolean expression. All rows for which the expression evaluates
! 374: # to false are excluded from the dataset.
! 375: #
! 376: test_join $tn.2.1 "t1, t2 ON (t1.a=t2.a)" {t1 t2 -on {te_equals a a}}
! 377: test_join $tn.2.2 "t2, t1 ON (t1.a=t2.a)" {t2 t1 -on {te_equals a a}}
! 378: test_join $tn.2.3 "t2, t1 ON (1)" {t2 t1 -on te_true}
! 379: test_join $tn.2.4 "t2, t1 ON (NULL)" {t2 t1 -on te_false}
! 380: test_join $tn.2.5 "t2, t1 ON (1.1-1.1)" {t2 t1 -on te_false}
! 381: test_join $tn.2.6 "t1, t2 ON (1.1-1.0)" {t1 t2 -on te_true}
! 382:
! 383:
! 384: test_join $tn.3 "t1 LEFT JOIN t2 ON (t1.a=t2.a)" {t1 t2 -left -on {te_equals a a}}
! 385: test_join $tn.4 "t1 LEFT JOIN t2 USING (a)" {
! 386: t1 t2 -left -using a -on {te_equals a a}
! 387: }
! 388: test_join $tn.5 "t1 CROSS JOIN t2 USING(b, a)" {
! 389: t1 t2 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 390: }
! 391: test_join $tn.6 "t1 NATURAL JOIN t2" {
! 392: t1 t2 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 393: }
! 394: test_join $tn.7 "t1 NATURAL INNER JOIN t2" {
! 395: t1 t2 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 396: }
! 397: test_join $tn.8 "t1 NATURAL CROSS JOIN t2" {
! 398: t1 t2 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 399: }
! 400: test_join $tn.9 "t1 NATURAL INNER JOIN t2" {
! 401: t1 t2 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 402: }
! 403: test_join $tn.10 "t1 NATURAL LEFT JOIN t2" {
! 404: t1 t2 -left -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 405: }
! 406: test_join $tn.11 "t1 NATURAL LEFT OUTER JOIN t2" {
! 407: t1 t2 -left -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 408: }
! 409: test_join $tn.12 "t2 NATURAL JOIN t1" {
! 410: t2 t1 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 411: }
! 412: test_join $tn.13 "t2 NATURAL INNER JOIN t1" {
! 413: t2 t1 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 414: }
! 415: test_join $tn.14 "t2 NATURAL CROSS JOIN t1" {
! 416: t2 t1 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 417: }
! 418: test_join $tn.15 "t2 NATURAL INNER JOIN t1" {
! 419: t2 t1 -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 420: }
! 421: test_join $tn.16 "t2 NATURAL LEFT JOIN t1" {
! 422: t2 t1 -left -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 423: }
! 424: test_join $tn.17 "t2 NATURAL LEFT OUTER JOIN t1" {
! 425: t2 t1 -left -using {a b} -on {te_and {te_equals a a} {te_equals b b}}
! 426: }
! 427: test_join $tn.18 "t1 LEFT JOIN t2 USING (b)" {
! 428: t1 t2 -left -using b -on {te_equals b b}
! 429: }
! 430: test_join $tn.19 "t1 JOIN t3 USING(b)" {t1 t3 -using b -on {te_equals b b}}
! 431: test_join $tn.20 "t3 JOIN t1 USING(b)" {
! 432: t3 t1 -using b -on {te_equals -nocase b b}
! 433: }
! 434: test_join $tn.21 "t1 NATURAL JOIN t3" {
! 435: t1 t3 -using b -on {te_equals b b}
! 436: }
! 437: test_join $tn.22 "t3 NATURAL JOIN t1" {
! 438: t3 t1 -using b -on {te_equals -nocase b b}
! 439: }
! 440: test_join $tn.23 "t1 NATURAL LEFT JOIN t3" {
! 441: t1 t3 -left -using b -on {te_equals b b}
! 442: }
! 443: test_join $tn.24 "t3 NATURAL LEFT JOIN t1" {
! 444: t3 t1 -left -using b -on {te_equals -nocase b b}
! 445: }
! 446: test_join $tn.25 "t1 LEFT JOIN t3 ON (t3.b=t1.b)" {
! 447: t1 t3 -left -on {te_equals -nocase b b}
! 448: }
! 449: test_join $tn.26 "t1 LEFT JOIN t3 ON (t1.b=t3.b)" {
! 450: t1 t3 -left -on {te_equals b b}
! 451: }
! 452: test_join $tn.27 "t1 JOIN t3 ON (t1.b=t3.b)" { t1 t3 -on {te_equals b b} }
! 453:
! 454: # EVIDENCE-OF: R-28760-53843 When more than two tables are joined
! 455: # together as part of a FROM clause, the join operations are processed
! 456: # in order from left to right. In other words, the FROM clause (A
! 457: # join-op-1 B join-op-2 C) is computed as ((A join-op-1 B) join-op-2 C).
! 458: #
! 459: # Tests 28a and 28b show that the statement above is true for this case.
! 460: # Test 28c shows that if the parenthesis force a different order of
! 461: # evaluation the result is different. Test 28d verifies that the result
! 462: # of the query with the parenthesis forcing a different order of evaluation
! 463: # is as calculated by the [te_*] procs.
! 464: #
! 465: set t3_natural_left_join_t2 [
! 466: te_tbljoin db t3 t2 -left -using {b} -on {te_equals -nocase b b}
! 467: ]
! 468: set t1 [te_read_tbl db t1]
! 469: te_dataset_eq_unordered $tn.28a [
! 470: te_read_sql db "SELECT * FROM t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1"
! 471: ] [te_join $t3_natural_left_join_t2 $t1 \
! 472: -using {a b} -on {te_and {te_equals a a} {te_equals -nocase b b}} \
! 473: ]
! 474:
! 475: te_dataset_eq_unordered $tn.28b [
! 476: te_read_sql db "SELECT * FROM (t3 NATURAL LEFT JOIN t2) NATURAL JOIN t1"
! 477: ] [te_join $t3_natural_left_join_t2 $t1 \
! 478: -using {a b} -on {te_and {te_equals a a} {te_equals -nocase b b}} \
! 479: ]
! 480:
! 481: te_dataset_ne_unordered $tn.28c [
! 482: te_read_sql db "SELECT * FROM (t3 NATURAL LEFT JOIN t2) NATURAL JOIN t1"
! 483: ] [
! 484: te_read_sql db "SELECT * FROM t3 NATURAL LEFT JOIN (t2 NATURAL JOIN t1)"
! 485: ]
! 486:
! 487: set t2_natural_join_t1 [te_tbljoin db t2 t1 -using {a b} \
! 488: -using {a b} -on {te_and {te_equals a a} {te_equals -nocase b b}} \
! 489: ]
! 490: set t3 [te_read_tbl db t3]
! 491: te_dataset_eq_unordered $tn.28d [
! 492: te_read_sql db "SELECT * FROM t3 NATURAL LEFT JOIN (t2 NATURAL JOIN t1)"
! 493: ] [te_join $t3 $t2_natural_join_t1 \
! 494: -left -using {b} -on {te_equals -nocase b b} \
! 495: ]
! 496: }
! 497:
! 498: do_execsql_test e_select-2.2.0 {
! 499: CREATE TABLE t4(x TEXT COLLATE nocase);
! 500: CREATE TABLE t5(y INTEGER, z TEXT COLLATE binary);
! 501:
! 502: INSERT INTO t4 VALUES('2.0');
! 503: INSERT INTO t4 VALUES('TWO');
! 504: INSERT INTO t5 VALUES(2, 'two');
! 505: } {}
! 506:
! 507: # EVIDENCE-OF: R-55824-40976 A sub-select specified in the join-source
! 508: # following the FROM clause in a simple SELECT statement is handled as
! 509: # if it was a table containing the data returned by executing the
! 510: # sub-select statement.
! 511: #
! 512: # EVIDENCE-OF: R-42612-06757 Each column of the sub-select dataset
! 513: # inherits the collation sequence and affinity of the corresponding
! 514: # expression in the sub-select statement.
! 515: #
! 516: foreach {tn subselect select spec} {
! 517: 1 "SELECT * FROM t2" "SELECT * FROM t1 JOIN %ss%"
! 518: {t1 %ss%}
! 519:
! 520: 2 "SELECT * FROM t2" "SELECT * FROM t1 JOIN %ss% AS x ON (t1.a=x.a)"
! 521: {t1 %ss% -on {te_equals 0 0}}
! 522:
! 523: 3 "SELECT * FROM t2" "SELECT * FROM %ss% AS x JOIN t1 ON (t1.a=x.a)"
! 524: {%ss% t1 -on {te_equals 0 0}}
! 525:
! 526: 4 "SELECT * FROM t1, t2" "SELECT * FROM %ss% AS x JOIN t3"
! 527: {%ss% t3}
! 528:
! 529: 5 "SELECT * FROM t1, t2" "SELECT * FROM %ss% NATURAL JOIN t3"
! 530: {%ss% t3 -using b -on {te_equals 1 0}}
! 531:
! 532: 6 "SELECT * FROM t1, t2" "SELECT * FROM t3 NATURAL JOIN %ss%"
! 533: {t3 %ss% -using b -on {te_equals -nocase 0 1}}
! 534:
! 535: 7 "SELECT * FROM t1, t2" "SELECT * FROM t3 NATURAL LEFT JOIN %ss%"
! 536: {t3 %ss% -left -using b -on {te_equals -nocase 0 1}}
! 537:
! 538: 8 "SELECT count(*) AS y FROM t4" "SELECT * FROM t5, %ss% USING (y)"
! 539: {t5 %ss% -using y -on {te_equals -affinity text 0 0}}
! 540:
! 541: 9 "SELECT count(*) AS y FROM t4" "SELECT * FROM %ss%, t5 USING (y)"
! 542: {%ss% t5 -using y -on {te_equals -affinity text 0 0}}
! 543:
! 544: 10 "SELECT x AS y FROM t4" "SELECT * FROM %ss% JOIN t5 USING (y)"
! 545: {%ss% t5 -using y -on {te_equals -nocase -affinity integer 0 0}}
! 546:
! 547: 11 "SELECT x AS y FROM t4" "SELECT * FROM t5 JOIN %ss% USING (y)"
! 548: {t5 %ss% -using y -on {te_equals -nocase -affinity integer 0 0}}
! 549:
! 550: 12 "SELECT y AS x FROM t5" "SELECT * FROM %ss% JOIN t4 USING (x)"
! 551: {%ss% t4 -using x -on {te_equals -nocase -affinity integer 0 0}}
! 552:
! 553: 13 "SELECT y AS x FROM t5" "SELECT * FROM t4 JOIN %ss% USING (x)"
! 554: {t4 %ss% -using x -on {te_equals -nocase -affinity integer 0 0}}
! 555:
! 556: 14 "SELECT +y AS x FROM t5" "SELECT * FROM %ss% JOIN t4 USING (x)"
! 557: {%ss% t4 -using x -on {te_equals -nocase -affinity text 0 0}}
! 558:
! 559: 15 "SELECT +y AS x FROM t5" "SELECT * FROM t4 JOIN %ss% USING (x)"
! 560: {t4 %ss% -using x -on {te_equals -nocase -affinity text 0 0}}
! 561: } {
! 562:
! 563: # Create a temporary table named %ss% containing the data returned by
! 564: # the sub-select. Then have the [te_tbljoin] proc use this table to
! 565: # compute the expected results of the $select query. Drop the temporary
! 566: # table before continuing.
! 567: #
! 568: execsql "CREATE TEMP TABLE '%ss%' AS $subselect"
! 569: set te [eval te_tbljoin db $spec]
! 570: execsql "DROP TABLE '%ss%'"
! 571:
! 572: # Check that the actual data returned by the $select query is the same
! 573: # as the expected data calculated using [te_tbljoin] above.
! 574: #
! 575: te_dataset_eq_unordered e_select-2.2.1.$tn [
! 576: te_read_sql db [string map [list %ss% "($subselect)"] $select]
! 577: ] $te
! 578: }
! 579:
! 580: finish_test
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>