Annotation of embedaddon/sqlite3/test/e_select2.test, revision 1.1.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>