github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/bestindex5.test (about)

     1  # 2017 September 10
     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  # Test the virtual table interface. In particular the xBestIndex
    12  # method.
    13  #
    14  
    15  set testdir [file dirname $argv0]
    16  source $testdir/tester.tcl
    17  set testprefix bestindex4
    18  
    19  ifcapable !vtab {
    20    finish_test
    21    return
    22  }
    23  
    24  #-------------------------------------------------------------------------
    25  # Virtual table callback for a virtual table named $tbl.
    26  #  
    27  proc vtab_cmd {method args} {
    28  
    29    set binops(ne)    !=
    30    set binops(eq)    =
    31    set binops(isnot) "IS NOT"
    32    set binops(is)    "IS"
    33  
    34    set unops(isnotnull) "IS NOT NULL"
    35    set unops(isnull)    "IS NULL"
    36  
    37    set cols(0) a
    38    set cols(1) b
    39    set cols(2) c
    40  
    41    switch -- $method {
    42      xConnect {
    43        return "CREATE TABLE t1(a, b, c)"
    44      }
    45  
    46      xBestIndex {
    47        foreach {clist orderby mask} $args {}
    48  
    49        set cost 1000000.0
    50        set ret [list]
    51        set str [list]
    52  
    53        set v 0
    54        for {set i 0} {$i < [llength $clist]} {incr i} {
    55          array unset C
    56          array set C [lindex $clist $i]
    57          if {$C(usable)} {
    58            if {[info exists binops($C(op))]} {
    59              lappend ret omit $i
    60              lappend str "$cols($C(column)) $binops($C(op)) %$v%"
    61              incr v
    62              set cost [expr $cost / 2]
    63            }
    64            if {[info exists unops($C(op))]} {
    65              lappend ret omit $i
    66              lappend str "$cols($C(column)) $unops($C(op))"
    67              incr v
    68              set cost [expr $cost / 2]
    69            }
    70          }
    71        }
    72  
    73        lappend ret idxstr [join $str " AND "]
    74        lappend ret cost $cost
    75        return $ret
    76      }
    77  
    78      xFilter {
    79        set q [lindex $args 1]
    80        set a [lindex $args 2]
    81        for {set v 0} {$v < [llength $a]} {incr v} {
    82          set val [lindex $a $v]
    83          set q [string map [list %$v% '$val'] $q]
    84        }
    85        if {$q==""} { set q 1 }
    86        lappend ::xFilterQueries "WHERE $q"
    87        return [list sql "SELECT rowid, * FROM t1x WHERE $q"]
    88      }
    89    }
    90    return ""
    91  }
    92  
    93  proc vtab_simple {method args} {
    94    switch -- $method {
    95      xConnect {
    96        return "CREATE TABLE t2(x)"
    97      }
    98      xBestIndex {
    99        return [list cost 999999.0]
   100      }
   101      xFilter {
   102        return [list sql "SELECT rowid, * FROM t2x"]
   103      }
   104    }
   105    return ""
   106  }
   107  
   108  register_tcl_module db
   109  
   110  proc do_vtab_query_test {tn query result} {
   111    set ::xFilterQueries [list]
   112    uplevel [list
   113      do_test $tn [string map [list %QUERY% $query] {
   114        set r [execsql {%QUERY%}]
   115        set r [concat $::xFilterQueries $r]
   116        set r
   117      }] [list {*}$result]
   118    ]
   119  }
   120  
   121  do_execsql_test 1.0 {
   122    CREATE VIRTUAL TABLE t1 USING tcl('vtab_cmd');
   123    CREATE TABLE t1x(a INTEGER, b TEXT, c REAL);
   124    INSERT INTO t1x VALUES(1, 2, 3);
   125    INSERT INTO t1x VALUES(4, 5, 6);
   126    INSERT INTO t1x VALUES(7, 8, 9);
   127  
   128    CREATE VIRTUAL TABLE t2 USING tcl('vtab_simple');
   129    CREATE TABLE t2x(x INTEGER);
   130    INSERT INTO t2x VALUES(1);
   131  }
   132  
   133  do_vtab_query_test 1.1 { SELECT * FROM t1 WHERE a!='hello'; } {
   134    "WHERE a != 'hello'"
   135    1 2 3.0 4 5 6.0 7 8 9.0
   136  }
   137  
   138  do_vtab_query_test 1.2.1 { SELECT * FROM t1 WHERE b!=8 } {
   139    "WHERE b != '8'"
   140    1 2 3.0 4 5 6.0
   141  }
   142  do_vtab_query_test 1.2.2 { SELECT * FROM t1 WHERE 8!=b } {
   143    "WHERE b != '8'"
   144    1 2 3.0 4 5 6.0
   145  }
   146  
   147  do_vtab_query_test 1.3 { SELECT * FROM t1 WHERE c IS NOT 3 } {
   148    "WHERE c IS NOT '3'"
   149    4 5 6.0 7 8 9.0
   150  }
   151  do_vtab_query_test 1.3.2 { SELECT * FROM t1 WHERE 3 IS NOT c } {
   152    "WHERE c IS NOT '3'"
   153    4 5 6.0 7 8 9.0
   154  }
   155  
   156  do_vtab_query_test 1.4.1 { SELECT * FROM t1, t2 WHERE x != a } {
   157    "WHERE a != '1'"
   158    4 5 6.0 1   7 8 9.0 1
   159  }
   160  do_vtab_query_test 1.4.2 { SELECT * FROM t1, t2 WHERE a != x } {
   161    "WHERE a != '1'"
   162    4 5 6.0 1   7 8 9.0 1
   163  }
   164  
   165  do_vtab_query_test 1.5.1 { SELECT * FROM t1 WHERE a IS NOT NULL } {
   166    "WHERE a IS NOT NULL"
   167    1 2 3.0 4 5 6.0 7 8 9.0
   168  }
   169  do_vtab_query_test 1.5.2 { SELECT * FROM t1 WHERE NULL IS NOT a } {
   170    "WHERE a IS NOT ''"
   171    1 2 3.0 4 5 6.0 7 8 9.0
   172  }
   173  
   174  do_vtab_query_test 1.6.1 { SELECT * FROM t1 WHERE a IS NULL } {
   175    "WHERE a IS NULL"
   176  }
   177  
   178  do_vtab_query_test 1.6.2 { SELECT * FROM t1 WHERE NULL IS a } {
   179    "WHERE a IS ''"
   180  }
   181  
   182  do_vtab_query_test 1.7.1 { SELECT * FROM t1 WHERE (a, b) IS (1, 2) } {
   183    "WHERE a IS '1' AND b IS '2'"
   184    1 2 3.0
   185  }
   186  do_vtab_query_test 1.7.2 { SELECT * FROM t1 WHERE (5, 4) IS (b, a) } {
   187    {WHERE b IS '5' AND a IS '4'} 
   188    4 5 6.0
   189  }
   190  
   191  #---------------------------------------------------------------------
   192  do_execsql_test 2.0.0 {
   193    DELETE FROM t1x;
   194    INSERT INTO t1x VALUES('a', 'b', 'c');
   195  }
   196  do_execsql_test 2.0.1 { SELECT * FROM t1 } {a b c}
   197  do_execsql_test 2.0.2 { SELECT * FROM t1 WHERE (a, b) != ('a', 'b'); } {}
   198  
   199  do_execsql_test 2.1.0 {
   200    DELETE FROM t1x;
   201    INSERT INTO t1x VALUES(7, 8, 9);
   202  }
   203  do_execsql_test 2.1.1 { SELECT * FROM t1 } {7 8 9.0}
   204  do_execsql_test 2.1.2 { SELECT * FROM t1 WHERE (a, b) != (7, '8') } {}
   205  do_execsql_test 2.1.3 { SELECT * FROM t1 WHERE a!=7 OR b!='8' }
   206  do_execsql_test 2.1.4 { SELECT * FROM t1 WHERE a!=7 OR b!='8' }
   207  
   208  
   209  do_execsql_test 2.2.1 {
   210    CREATE TABLE t3(a INTEGER, b TEXT);
   211    INSERT INTO t3 VALUES(45, 46);
   212  }
   213  do_execsql_test 2.2.2 { SELECT * FROM t3 WHERE (a, b) != (45, 46); }
   214  do_execsql_test 2.2.3 { SELECT * FROM t3 WHERE (a, b) != ('45', '46'); }
   215  do_execsql_test 2.2.4 { SELECT * FROM t3 WHERE (a, b) == (45, 46); } {45 46}
   216  do_execsql_test 2.2.5 { SELECT * FROM t3 WHERE (a, b) == ('45', '46'); } {45 46}
   217  
   218  #---------------------------------------------------------------------
   219  # Test the != operator on a virtual table with column affinities.
   220  #
   221  proc vtab_simple_integer {method args} {
   222    switch -- $method {
   223      xConnect {
   224        return "CREATE TABLE t4(x INTEGER)"
   225      }
   226      xBestIndex {
   227        return [list cost 999999.0]
   228      }
   229      xFilter {
   230        return [list sql "SELECT rowid, * FROM t4x"]
   231      }
   232    }
   233    return ""
   234  }
   235  
   236  do_execsql_test 3.0 {
   237    CREATE TABLE t4x(a INTEGER);
   238    INSERT INTO t4x VALUES(245);
   239    CREATE VIRTUAL TABLE t4 USING tcl('vtab_simple_integer');
   240  }
   241  do_execsql_test 3.1 { SELECT rowid, * FROM t4 WHERE x=245; } {1 245}
   242  do_execsql_test 3.2 { SELECT rowid, * FROM t4 WHERE x='245'; } {1 245}
   243  do_execsql_test 3.3 { SELECT rowid, * FROM t4 WHERE x!=245; } {}
   244  do_execsql_test 3.4 { SELECT rowid, * FROM t4 WHERE x!='245'; } {}
   245  
   246  do_execsql_test 3.5 { SELECT rowid, * FROM t4 WHERE rowid!=1 OR x!='245'; } {}
   247  
   248  
   249  finish_test