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