Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix cases where modifying bound variables using the clear_bindings() or transfer_bindings() APIs can invalidate a query plan. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
e6808c988c9cd7b2db23f18b5fe21771 |
User & Date: | dan 2009-10-20 07:01:24.000 |
Context
2009-10-20
| ||
14:08 | Update documentation on the sqlite3_prepare_v2() interface. No changes to code. (check-in: 3b00e769cd user: drh tags: trunk) | |
07:01 | Fix cases where modifying bound variables using the clear_bindings() or transfer_bindings() APIs can invalidate a query plan. (check-in: e6808c988c user: dan tags: trunk) | |
2009-10-19
| ||
22:41 | Remove an unreachable condition in the WHERE clause processing of bound parameters and replace it with an assert(), for test coverage. (check-in: 3bcd78a1d7 user: drh tags: trunk) | |
Changes
Changes to src/vdbeapi.c.
︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 103 104 105 106 107 | #if SQLITE_THREADSAFE sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; #endif sqlite3_mutex_enter(mutex); for(i=0; i<p->nVar; i++){ sqlite3VdbeMemRelease(&p->aVar[i]); p->aVar[i].flags = MEM_Null; } sqlite3_mutex_leave(mutex); return rc; } /**************************** sqlite3_value_ ******************************* | > > > | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | #if SQLITE_THREADSAFE sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; #endif sqlite3_mutex_enter(mutex); for(i=0; i<p->nVar; i++){ sqlite3VdbeMemRelease(&p->aVar[i]); p->aVar[i].flags = MEM_Null; } if( p->isPrepareV2 && p->expmask ){ p->expired = 1; } sqlite3_mutex_leave(mutex); return rc; } /**************************** sqlite3_value_ ******************************* |
︙ | ︙ | |||
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 | ** SQLITE_OK is returned. */ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ Vdbe *pFrom = (Vdbe*)pFromStmt; Vdbe *pTo = (Vdbe*)pToStmt; if( pFrom->nVar!=pTo->nVar ){ return SQLITE_ERROR; } return sqlite3TransferBindings(pFromStmt, pToStmt); } #endif /* ** Return the sqlite3* database handle to which the prepared statement given | > > > > > > | 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 | ** SQLITE_OK is returned. */ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ Vdbe *pFrom = (Vdbe*)pFromStmt; Vdbe *pTo = (Vdbe*)pToStmt; if( pFrom->nVar!=pTo->nVar ){ return SQLITE_ERROR; } if( pTo->isPrepareV2 && pTo->expmask ){ pTo->expired = 1; } if( pFrom->isPrepareV2 && pFrom->expmask ){ pFrom->expired = 1; } return sqlite3TransferBindings(pFromStmt, pToStmt); } #endif /* ** Return the sqlite3* database handle to which the prepared statement given |
︙ | ︙ |
Changes to test/analyze3.test.
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 | # analyze3-3.*: Test that binding to a variable does not invalidate the # query plan when there is no way in which replanning the # query may produce a superior outcome. # # analyze3-4.*: Test that SQL or authorization callback errors occuring # within sqlite3Reprepare() are handled correctly. # proc getvar {varname} { uplevel #0 set $varname } db function var getvar proc eqp {sql {db db}} { uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db } | > > > > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | # analyze3-3.*: Test that binding to a variable does not invalidate the # query plan when there is no way in which replanning the # query may produce a superior outcome. # # analyze3-4.*: Test that SQL or authorization callback errors occuring # within sqlite3Reprepare() are handled correctly. # # analyze3-5.*: Check that the query plans of applicable statements are # invalidated if the values of SQL parameter are modified # using the clear_bindings() or transfer_bindings() APIs. # proc getvar {varname} { uplevel #0 set $varname } db function var getvar proc eqp {sql {db db}} { uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db } |
︙ | ︙ | |||
522 523 524 525 526 527 528 529 530 | execsql { CREATE TABLE t2(d, e, f) } db auth auth sqlite3_step $S } {SQLITE_SCHEMA} do_test analyze3-4.3.2 { sqlite3_finalize $S } {SQLITE_SCHEMA} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 595 596 597 598 599 600 601 | execsql { CREATE TABLE t2(d, e, f) } db auth auth sqlite3_step $S } {SQLITE_SCHEMA} do_test analyze3-4.3.2 { sqlite3_finalize $S } {SQLITE_SCHEMA} db auth {} #------------------------------------------------------------------------- # Test that modifying bound variables using the clear_bindings() or # transfer_bindings() APIs works. # # analyze3-5.1.*: sqlite3_clear_bindings() # analyze3-5.2.*: sqlite3_transfer_bindings() # do_test analyze3-5.1.1 { drop_all_tables execsql { CREATE TABLE t1(x TEXT COLLATE NOCASE); CREATE INDEX i1 ON t1(x); INSERT INTO t1 VALUES('aaa'); INSERT INTO t1 VALUES('abb'); INSERT INTO t1 VALUES('acc'); INSERT INTO t1 VALUES('baa'); INSERT INTO t1 VALUES('bbb'); INSERT INTO t1 VALUES('bcc'); } set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x LIKE ?" -1 dummy] sqlite3_bind_text $S 1 "a%" 2 set R [list] while { "SQLITE_ROW" == [sqlite3_step $S] } { lappend R [sqlite3_column_text $S 0] } concat [sqlite3_reset $S] $R } {SQLITE_OK aaa abb acc} do_test analyze3-5.1.2 { sqlite3_clear_bindings $S set R [list] while { "SQLITE_ROW" == [sqlite3_step $S] } { lappend R [sqlite3_column_text $S 0] } concat [sqlite3_reset $S] $R } {SQLITE_OK} do_test analyze3-5.1.3 { sqlite3_finalize $S } {SQLITE_OK} do_test analyze3-5.1.1 { set S1 [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x LIKE ?" -1 dummy] sqlite3_bind_text $S1 1 "b%" 2 set R [list] while { "SQLITE_ROW" == [sqlite3_step $S1] } { lappend R [sqlite3_column_text $S1 0] } concat [sqlite3_reset $S1] $R } {SQLITE_OK baa bbb bcc} do_test analyze3-5.1.2 { set S2 [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x = ?" -1 dummy] sqlite3_bind_text $S2 1 "a%" 2 sqlite3_transfer_bindings $S2 $S1 set R [list] while { "SQLITE_ROW" == [sqlite3_step $S1] } { lappend R [sqlite3_column_text $S1 0] } concat [sqlite3_reset $S1] $R } {SQLITE_OK aaa abb acc} do_test analyze3-5.1.3 { sqlite3_finalize $S2 sqlite3_finalize $S1 } {SQLITE_OK} finish_test |