Home | History | Annotate | Download | only in test
      1 # 2009 August 06
      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 regression tests for SQLite library. This file 
     13 # implements tests for range and LIKE constraints that use bound variables
     14 # instead of literal constant arguments.
     15 #
     16 
     17 set testdir [file dirname $argv0]
     18 source $testdir/tester.tcl
     19 
     20 ifcapable !stat2 {
     21   finish_test
     22   return
     23 }
     24 
     25 #----------------------------------------------------------------------
     26 # Test Organization:
     27 #
     28 # analyze3-1.*: Test that the values of bound parameters are considered 
     29 #               in the same way as constants when planning queries that
     30 #               use range constraints.
     31 #
     32 # analyze3-2.*: Test that the values of bound parameters are considered 
     33 #               in the same way as constants when planning queries that
     34 #               use LIKE expressions in the WHERE clause.
     35 #
     36 # analyze3-3.*: Test that binding to a variable does not invalidate the 
     37 #               query plan when there is no way in which replanning the
     38 #               query may produce a superior outcome.
     39 #
     40 # analyze3-4.*: Test that SQL or authorization callback errors occuring
     41 #               within sqlite3Reprepare() are handled correctly.
     42 #
     43 # analyze3-5.*: Check that the query plans of applicable statements are
     44 #               invalidated if the values of SQL parameter are modified
     45 #               using the clear_bindings() or transfer_bindings() APIs.
     46 #
     47 
     48 proc getvar {varname} { uplevel #0 set $varname }
     49 db function var getvar
     50 
     51 proc eqp {sql {db db}} {
     52   uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
     53 }
     54 
     55 proc sf_execsql {sql {db db}} {
     56   set ::sqlite_search_count 0
     57   set r [uplevel [list execsql $sql $db]]
     58 
     59   concat $::sqlite_search_count [$db status step] $r
     60 }
     61 
     62 #-------------------------------------------------------------------------
     63 #
     64 # analyze3-1.1.1: 
     65 #   Create a table with two columns. Populate the first column (affinity 
     66 #   INTEGER) with integer values from 100 to 1100. Create an index on this 
     67 #   column. ANALYZE the table.
     68 #
     69 # analyze3-1.1.2 - 3.1.3
     70 #   Show that there are two possible plans for querying the table with
     71 #   a range constraint on the indexed column - "full table scan" or "use 
     72 #   the index". When the range is specified using literal values, SQLite
     73 #   is able to pick the best plan based on the samples in sqlite_stat2.
     74 #
     75 # analyze3-1.1.4 - 3.1.9
     76 #   Show that using SQL variables produces the same results as using
     77 #   literal values to constrain the range scan.
     78 #
     79 #   These tests also check that the compiler code considers column 
     80 #   affinities when estimating the number of rows scanned by the "use 
     81 #   index strategy".
     82 #
     83 do_test analyze3-1.1.1 {
     84   execsql {
     85     BEGIN;
     86     CREATE TABLE t1(x INTEGER, y);
     87     CREATE INDEX i1 ON t1(x);
     88   }
     89   for {set i 0} {$i < 1000} {incr i} {
     90     execsql { INSERT INTO t1 VALUES($i+100, $i) }
     91   }
     92   execsql {
     93     COMMIT;
     94     ANALYZE;
     95   }
     96 } {}
     97 
     98 do_eqp_test analyze3-1.1.2 {
     99   SELECT sum(y) FROM t1 WHERE x>200 AND x<300
    100 } {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?) (~100 rows)}}
    101 do_eqp_test analyze3-1.1.3 {
    102   SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 
    103 } {0 0 0 {SCAN TABLE t1 (~111 rows)}}
    104 
    105 do_test analyze3-1.1.4 {
    106   sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
    107 } {199 0 14850}
    108 do_test analyze3-1.1.5 {
    109   set l [string range "200" 0 end]
    110   set u [string range "300" 0 end]
    111   sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
    112 } {199 0 14850}
    113 do_test analyze3-1.1.6 {
    114   set l [expr int(200)]
    115   set u [expr int(300)]
    116   sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
    117 } {199 0 14850}
    118 do_test analyze3-1.1.7 {
    119   sf_execsql { SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 }
    120 } {999 999 499500}
    121 do_test analyze3-1.1.8 {
    122   set l [string range "0" 0 end]
    123   set u [string range "1100" 0 end]
    124   sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
    125 } {999 999 499500}
    126 do_test analyze3-1.1.9 {
    127   set l [expr int(0)]
    128   set u [expr int(1100)]
    129   sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
    130 } {999 999 499500}
    131 
    132 
    133 # The following tests are similar to the block above. The difference is
    134 # that the indexed column has TEXT affinity in this case. In the tests
    135 # above the affinity is INTEGER.
    136 #
    137 do_test analyze3-1.2.1 {
    138   execsql {
    139     BEGIN;
    140       CREATE TABLE t2(x TEXT, y);
    141       INSERT INTO t2 SELECT * FROM t1;
    142       CREATE INDEX i2 ON t2(x);
    143     COMMIT;
    144     ANALYZE;
    145   }
    146 } {}
    147 do_eqp_test analyze3-1.2.2 {
    148   SELECT sum(y) FROM t2 WHERE x>1 AND x<2
    149 } {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?) (~200 rows)}}
    150 do_eqp_test analyze3-1.2.3 {
    151   SELECT sum(y) FROM t2 WHERE x>0 AND x<99
    152 } {0 0 0 {SCAN TABLE t2 (~111 rows)}}
    153 do_test analyze3-1.2.4 {
    154   sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
    155 } {161 0 4760}
    156 do_test analyze3-1.2.5 {
    157   set l [string range "12" 0 end]
    158   set u [string range "20" 0 end]
    159   sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
    160 } {161 0 text text 4760}
    161 do_test analyze3-1.2.6 {
    162   set l [expr int(12)]
    163   set u [expr int(20)]
    164   sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
    165 } {161 0 integer integer 4760}
    166 do_test analyze3-1.2.7 {
    167   sf_execsql { SELECT sum(y) FROM t2 WHERE x>0 AND x<99 }
    168 } {999 999 490555}
    169 do_test analyze3-1.2.8 {
    170   set l [string range "0" 0 end]
    171   set u [string range "99" 0 end]
    172   sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
    173 } {999 999 text text 490555}
    174 do_test analyze3-1.2.9 {
    175   set l [expr int(0)]
    176   set u [expr int(99)]
    177   sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
    178 } {999 999 integer integer 490555}
    179 
    180 # Same tests a third time. This time, column x has INTEGER affinity and
    181 # is not the leftmost column of the table. This triggered a bug causing
    182 # SQLite to use sub-optimal query plans in 3.6.18 and earlier.
    183 #
    184 do_test analyze3-1.3.1 {
    185   execsql {
    186     BEGIN;
    187       CREATE TABLE t3(y TEXT, x INTEGER);
    188       INSERT INTO t3 SELECT y, x FROM t1;
    189       CREATE INDEX i3 ON t3(x);
    190     COMMIT;
    191     ANALYZE;
    192   }
    193 } {}
    194 do_eqp_test analyze3-1.3.2 {
    195   SELECT sum(y) FROM t3 WHERE x>200 AND x<300
    196 } {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?) (~100 rows)}}
    197 do_eqp_test analyze3-1.3.3 {
    198   SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
    199 } {0 0 0 {SCAN TABLE t3 (~111 rows)}}
    200 
    201 do_test analyze3-1.3.4 {
    202   sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
    203 } {199 0 14850}
    204 do_test analyze3-1.3.5 {
    205   set l [string range "200" 0 end]
    206   set u [string range "300" 0 end]
    207   sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
    208 } {199 0 14850}
    209 do_test analyze3-1.3.6 {
    210   set l [expr int(200)]
    211   set u [expr int(300)]
    212   sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
    213 } {199 0 14850}
    214 do_test analyze3-1.3.7 {
    215   sf_execsql { SELECT sum(y) FROM t3 WHERE x>0 AND x<1100 }
    216 } {999 999 499500}
    217 do_test analyze3-1.3.8 {
    218   set l [string range "0" 0 end]
    219   set u [string range "1100" 0 end]
    220   sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
    221 } {999 999 499500}
    222 do_test analyze3-1.3.9 {
    223   set l [expr int(0)]
    224   set u [expr int(1100)]
    225   sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
    226 } {999 999 499500}
    227 
    228 #-------------------------------------------------------------------------
    229 # Test that the values of bound SQL variables may be used for the LIKE
    230 # optimization.
    231 #
    232 drop_all_tables
    233 do_test analyze3-2.1 {
    234   execsql {
    235     PRAGMA case_sensitive_like=off;
    236     BEGIN;
    237     CREATE TABLE t1(a, b TEXT COLLATE nocase);
    238     CREATE INDEX i1 ON t1(b);
    239   }
    240   for {set i 0} {$i < 1000} {incr i} {
    241     set t ""
    242     append t [lindex {a b c d e f g h i j} [expr $i/100]]
    243     append t [lindex {a b c d e f g h i j} [expr ($i/10)%10]]
    244     append t [lindex {a b c d e f g h i j} [expr ($i%10)]]
    245     execsql { INSERT INTO t1 VALUES($i, $t) }
    246   }
    247   execsql COMMIT
    248 } {}
    249 do_eqp_test analyze3-2.2 {
    250   SELECT count(a) FROM t1 WHERE b LIKE 'a%'
    251 } {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?) (~30000 rows)}}
    252 do_eqp_test analyze3-2.3 {
    253   SELECT count(a) FROM t1 WHERE b LIKE '%a'
    254 } {0 0 0 {SCAN TABLE t1 (~500000 rows)}}
    255 
    256 do_test analyze3-2.4 {
    257   sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE 'a%' }
    258 } {101 0 100}
    259 do_test analyze3-2.5 {
    260   sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE '%a' }
    261 } {999 999 100}
    262 
    263 do_test analyze3-2.4 {
    264   set like "a%"
    265   sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
    266 } {101 0 100}
    267 do_test analyze3-2.5 {
    268   set like "%a"
    269   sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
    270 } {999 999 100}
    271 do_test analyze3-2.6 {
    272   set like "a"
    273   sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
    274 } {101 0 0}
    275 do_test analyze3-2.7 {
    276   set like "ab"
    277   sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
    278 } {11 0 0}
    279 do_test analyze3-2.8 {
    280   set like "abc"
    281   sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
    282 } {2 0 1}
    283 do_test analyze3-2.9 {
    284   set like "a_c"
    285   sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
    286 } {101 0 10}
    287 
    288 
    289 #-------------------------------------------------------------------------
    290 # This block of tests checks that statements are correctly marked as
    291 # expired when the values bound to any parameters that may affect the 
    292 # query plan are modified.
    293 #
    294 drop_all_tables
    295 db auth auth
    296 proc auth {args} {
    297   set ::auth 1
    298   return SQLITE_OK
    299 }
    300 
    301 do_test analyze3-3.1 {
    302   execsql {
    303     BEGIN;
    304     CREATE TABLE t1(a, b, c);
    305     CREATE INDEX i1 ON t1(b);
    306   }
    307   for {set i 0} {$i < 100} {incr i} {
    308     execsql { INSERT INTO t1 VALUES($i, $i, $i) }
    309   }
    310   execsql COMMIT
    311   execsql ANALYZE
    312 } {}
    313 
    314 do_test analyze3-3.2.1 {
    315   set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE b>?" -1 dummy]
    316   sqlite3_expired $S
    317 } {0}
    318 do_test analyze3-3.2.2 {
    319   sqlite3_bind_text $S 1 "abc" 3
    320   sqlite3_expired $S
    321 } {1}
    322 do_test analyze3-3.2.4 {
    323   sqlite3_finalize $S
    324 } {SQLITE_OK}
    325 
    326 do_test analyze3-3.2.5 {
    327   set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE b=?" -1 dummy]
    328   sqlite3_expired $S
    329 } {0}
    330 do_test analyze3-3.2.6 {
    331   sqlite3_bind_text $S 1 "abc" 3
    332   sqlite3_expired $S
    333 } {0}
    334 do_test analyze3-3.2.7 {
    335   sqlite3_finalize $S
    336 } {SQLITE_OK}
    337 
    338 do_test analyze3-3.4.1 {
    339   set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
    340   sqlite3_expired $S
    341 } {0}
    342 do_test analyze3-3.4.2 {
    343   sqlite3_bind_text $S 1 "abc" 3
    344   sqlite3_expired $S
    345 } {0}
    346 do_test analyze3-3.4.3 {
    347   sqlite3_bind_text $S 2 "def" 3
    348   sqlite3_expired $S
    349 } {1}
    350 do_test analyze3-3.4.4 {
    351   sqlite3_bind_text $S 2 "ghi" 3
    352   sqlite3_expired $S
    353 } {1}
    354 do_test analyze3-3.4.5 {
    355   sqlite3_expired $S
    356 } {1}
    357 do_test analyze3-3.4.6 {
    358   sqlite3_finalize $S
    359 } {SQLITE_OK}
    360 
    361 do_test analyze3-3.5.1 {
    362   set S [sqlite3_prepare_v2 db {
    363     SELECT * FROM t1 WHERE a IN (
    364       ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10,
    365       ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20,
    366       ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29, ?30, ?31
    367     ) AND b>?32;
    368   } -1 dummy]
    369   sqlite3_expired $S
    370 } {0}
    371 do_test analyze3-3.5.2 {
    372   sqlite3_bind_text $S 31 "abc" 3
    373   sqlite3_expired $S
    374 } {0}
    375 do_test analyze3-3.5.3 {
    376   sqlite3_bind_text $S 32 "def" 3
    377   sqlite3_expired $S
    378 } {1}
    379 do_test analyze3-3.5.5 {
    380   sqlite3_finalize $S
    381 } {SQLITE_OK}
    382 
    383 do_test analyze3-3.6.1 {
    384   set S [sqlite3_prepare_v2 db {
    385     SELECT * FROM t1 WHERE a IN (
    386       ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10,
    387       ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20,
    388       ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29, ?30, ?31, ?32
    389     ) AND b>?33;
    390   } -1 dummy]
    391   sqlite3_expired $S
    392 } {0}
    393 do_test analyze3-3.6.2 {
    394   sqlite3_bind_text $S 32 "abc" 3
    395   sqlite3_expired $S
    396 } {1}
    397 do_test analyze3-3.6.3 {
    398   sqlite3_bind_text $S 33 "def" 3
    399   sqlite3_expired $S
    400 } {1}
    401 do_test analyze3-3.6.5 {
    402   sqlite3_finalize $S
    403 } {SQLITE_OK}
    404 
    405 do_test analyze3-3.7.1 {
    406   set S [sqlite3_prepare_v2 db {
    407     SELECT * FROM t1 WHERE a IN (
    408       ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?33,
    409       ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20,
    410       ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29, ?30, ?31, ?32
    411     ) AND b>?10;
    412   } -1 dummy]
    413   sqlite3_expired $S
    414 } {0}
    415 do_test analyze3-3.7.2 {
    416   sqlite3_bind_text $S 32 "abc" 3
    417   sqlite3_expired $S
    418 } {0}
    419 do_test analyze3-3.7.3 {
    420   sqlite3_bind_text $S 33 "def" 3
    421   sqlite3_expired $S
    422 } {0}
    423 do_test analyze3-3.7.4 {
    424   sqlite3_bind_text $S 10 "def" 3
    425   sqlite3_expired $S
    426 } {1}
    427 do_test analyze3-3.7.6 {
    428   sqlite3_finalize $S
    429 } {SQLITE_OK}
    430 
    431 do_test analyze3-3.8.1 {
    432   execsql {
    433     CREATE TABLE t4(x, y TEXT COLLATE NOCASE);
    434     CREATE INDEX i4 ON t4(y);
    435   }
    436 } {}
    437 do_test analyze3-3.8.2 {
    438   set S [sqlite3_prepare_v2 db {
    439     SELECT * FROM t4 WHERE x != ? AND y LIKE ?
    440   } -1 dummy]
    441   sqlite3_expired $S
    442 } {0}
    443 do_test analyze3-3.8.3 {
    444   sqlite3_bind_text $S 1 "abc" 3
    445   sqlite3_expired $S
    446 } {0}
    447 do_test analyze3-3.8.4 {
    448   sqlite3_bind_text $S 2 "def" 3
    449   sqlite3_expired $S
    450 } {1}
    451 do_test analyze3-3.8.7 {
    452   sqlite3_bind_text $S 2 "ghi%" 4
    453   sqlite3_expired $S
    454 } {1}
    455 do_test analyze3-3.8.8 {
    456   sqlite3_expired $S
    457 } {1}
    458 do_test analyze3-3.8.9 {
    459   sqlite3_bind_text $S 2 "ghi%def" 7
    460   sqlite3_expired $S
    461 } {1}
    462 do_test analyze3-3.8.10 {
    463   sqlite3_expired $S
    464 } {1}
    465 do_test analyze3-3.8.11 {
    466   sqlite3_bind_text $S 2 "%ab" 3
    467   sqlite3_expired $S
    468 } {1}
    469 do_test analyze3-3.8.12 {
    470   sqlite3_expired $S
    471 } {1}
    472 do_test analyze3-3.8.12 {
    473   sqlite3_bind_text $S 2 "%de" 3
    474   sqlite3_expired $S
    475 } {1}
    476 do_test analyze3-3.8.13 {
    477   sqlite3_expired $S
    478 } {1}
    479 do_test analyze3-3.8.14 {
    480   sqlite3_finalize $S
    481 } {SQLITE_OK}
    482 
    483 #-------------------------------------------------------------------------
    484 # These tests check that errors encountered while repreparing an SQL
    485 # statement within sqlite3Reprepare() are handled correctly.
    486 #
    487 
    488 # Check a schema error.
    489 #
    490 do_test analyze3-4.1.1 {
    491   set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
    492   sqlite3_step $S
    493 } {SQLITE_DONE}
    494 do_test analyze3-4.1.2 {
    495   sqlite3_reset $S
    496   sqlite3_bind_text $S 2 "abc" 3
    497   execsql { DROP TABLE t1 }
    498   sqlite3_step $S
    499 } {SQLITE_ERROR}
    500 do_test analyze3-4.1.3 {
    501   sqlite3_finalize $S
    502 } {SQLITE_ERROR}
    503 
    504 # Check an authorization error.
    505 #
    506 do_test analyze3-4.2.1 {
    507   execsql {
    508     BEGIN;
    509     CREATE TABLE t1(a, b, c);
    510     CREATE INDEX i1 ON t1(b);
    511   }
    512   for {set i 0} {$i < 100} {incr i} {
    513     execsql { INSERT INTO t1 VALUES($i, $i, $i) }
    514   }
    515   execsql COMMIT
    516   execsql ANALYZE
    517   set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
    518   sqlite3_step $S
    519 } {SQLITE_DONE}
    520 db auth auth
    521 proc auth {args} {
    522   if {[lindex $args 0] == "SQLITE_READ"} {return SQLITE_DENY}
    523   return SQLITE_OK
    524 }
    525 do_test analyze3-4.2.2 {
    526   sqlite3_reset $S
    527   sqlite3_bind_text $S 2 "abc" 3
    528   sqlite3_step $S
    529 } {SQLITE_AUTH}
    530 do_test analyze3-4.2.4 {
    531   sqlite3_finalize $S
    532 } {SQLITE_AUTH}
    533 
    534 # Check the effect of an authorization error that occurs in a re-prepare
    535 # performed by sqlite3_step() is the same as one that occurs within
    536 # sqlite3Reprepare().
    537 #
    538 do_test analyze3-4.3.1 {
    539   db auth {}
    540   set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
    541   execsql { CREATE TABLE t2(d, e, f) }
    542   db auth auth
    543   sqlite3_step $S
    544 } {SQLITE_AUTH}
    545 do_test analyze3-4.3.2 {
    546   sqlite3_finalize $S
    547 } {SQLITE_AUTH}
    548 db auth {}
    549 
    550 #-------------------------------------------------------------------------
    551 # Test that modifying bound variables using the clear_bindings() or
    552 # transfer_bindings() APIs works.
    553 #
    554 #   analyze3-5.1.*: sqlite3_clear_bindings()
    555 #   analyze3-5.2.*: sqlite3_transfer_bindings()
    556 #
    557 do_test analyze3-5.1.1 {
    558   drop_all_tables
    559   execsql {
    560     CREATE TABLE t1(x TEXT COLLATE NOCASE);
    561     CREATE INDEX i1 ON t1(x);
    562     INSERT INTO t1 VALUES('aaa');
    563     INSERT INTO t1 VALUES('abb');
    564     INSERT INTO t1 VALUES('acc');
    565     INSERT INTO t1 VALUES('baa');
    566     INSERT INTO t1 VALUES('bbb');
    567     INSERT INTO t1 VALUES('bcc');
    568   }
    569 
    570   set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x LIKE ?" -1 dummy]
    571   sqlite3_bind_text $S 1 "a%" 2
    572   set R [list]
    573   while { "SQLITE_ROW" == [sqlite3_step $S] } {
    574     lappend R [sqlite3_column_text $S 0]
    575   }
    576   concat [sqlite3_reset $S] $R
    577 } {SQLITE_OK aaa abb acc}
    578 do_test analyze3-5.1.2 {
    579   sqlite3_clear_bindings $S
    580   set R [list]
    581   while { "SQLITE_ROW" == [sqlite3_step $S] } {
    582     lappend R [sqlite3_column_text $S 0]
    583   }
    584   concat [sqlite3_reset $S] $R
    585 } {SQLITE_OK}
    586 do_test analyze3-5.1.3 {
    587   sqlite3_finalize $S
    588 } {SQLITE_OK}
    589 
    590 do_test analyze3-5.1.1 {
    591   set S1 [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x LIKE ?" -1 dummy]
    592   sqlite3_bind_text $S1 1 "b%" 2
    593   set R [list]
    594   while { "SQLITE_ROW" == [sqlite3_step $S1] } {
    595     lappend R [sqlite3_column_text $S1 0]
    596   }
    597   concat [sqlite3_reset $S1] $R
    598 } {SQLITE_OK baa bbb bcc}
    599 
    600 do_test analyze3-5.1.2 {
    601   set S2 [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x = ?" -1 dummy]
    602   sqlite3_bind_text $S2 1 "a%" 2
    603   sqlite3_transfer_bindings $S2 $S1
    604   set R [list]
    605   while { "SQLITE_ROW" == [sqlite3_step $S1] } {
    606     lappend R [sqlite3_column_text $S1 0]
    607   }
    608   concat [sqlite3_reset $S1] $R
    609 } {SQLITE_OK aaa abb acc}
    610 do_test analyze3-5.1.3 {
    611   sqlite3_finalize $S2
    612   sqlite3_finalize $S1
    613 } {SQLITE_OK}
    614 
    615 finish_test
    616