SQLite

Check-in [282dae7edf]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add tests to e_select.test.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 282dae7edf7209197fffb6c58b038b3aae1a0367
User & Date: dan 2010-09-07 19:05:28.000
Context
2010-09-07
19:10
Update the sqlite3_limit() documentation to explain that SQLITE_LIMIT_VDBE_OP is not enforced. (check-in: 17be9beeab user: drh tags: trunk)
19:05
Add tests to e_select.test. (check-in: 282dae7edf user: dan tags: trunk)
14:59
Revised documentation for sqlite3_limit(). Added some evidence marks and assert() statements to verify sqlite3_limit() behavior. (check-in: 883b9b7441 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to test/e_select.test.
351
352
353
354
355
356
357











































































































































































































































358

  3 {SELECT * FROM t1 NATURAL LEFT JOIN t2 ON (45)}
} {
  do_catchsql_test e_select-1.12.$tn "
    $sql
  " {1 {a NATURAL join may not have an ON or USING clause}}
}












































































































































































































































finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  3 {SELECT * FROM t1 NATURAL LEFT JOIN t2 ON (45)}
} {
  do_catchsql_test e_select-1.12.$tn "
    $sql
  " {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