Add SQLITE_DBCONFIG_ENABLE_QPSG that forces the query planner stability

guarantee.  This is the fix for ticket [b9f010107724c]

FossilOrigin-Name: b82efd2a24914ace39acf99df75175042471fd73a8d31d66a40b15f63b342e10
This commit is contained in:
drh 2017-06-27 23:36:44 +00:00
commit a5e906f307
16 changed files with 163 additions and 69 deletions

View File

@ -1,5 +1,5 @@
C Fix\sa\svirtual\stable\sproblem\sthat\scan\soccur\swhen\sthe\svtab\sis\son\sthe\sRHS\sof\sa\nLEFT\sJOIN\sand\sthere\sis\sa\sMATCH\sconstraint\sin\sthe\sON\sclause,\sor\swhen\sthe\svtab\nis\sin\sa\ssub-query\sthat\sis\sthe\sRHS\sof\sa\sLEFT\sJOIN\sand\sthere\sis\sa\sMATCH\nconstraint\sin\sthe\sWHERE\sclause\sof\sthe\ssub-query.
D 2017-06-27T16:39:01.302
C Add\sSQLITE_DBCONFIG_ENABLE_QPSG\sthat\sforces\sthe\squery\splanner\sstability\nguarantee.\s\sThis\sis\sthe\sfix\sfor\sticket\s[b9f010107724c]
D 2017-06-27T23:36:44.838
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 8eeb80162074004e906b53d7340a12a14c471a83743aab975947e95ce061efcc
@ -349,7 +349,7 @@ F src/auth.c 79f96c6f33bf0e5da8d1c282cee5ebb1852bb8a6ccca3e485d7c459b035d9c3c
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
F src/btree.c 430e34151e6ef37e42d3f956bb062907c80ff91e1380704b967b8c1a02a98f64
F src/btree.c 00579ff9c2831d6f98cc993f8f2a34c0ff996e89b3cd2f27928f75796bc3a58a
F src/btree.h 3edc5329bc59534d2d15b4f069a9f54b779a7e51289e98fa481ae3c0e526a5ca
F src/btreeInt.h a392d353104b4add58b4a59cb185f5d5693dde832c565b77d8d4c343ed98f610
F src/build.c 88a8cdc11d1c081ed565aa3e795bdf9160f4556463b4c4555e9860b59dd80340
@ -371,7 +371,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 974499a3999d339a4c1ba8ef129a988d9f136b3789e423808b38cdc19d28adbe
F src/legacy.c e88ed13c2d531decde75d42c2e35623fb9ce3cb0
F src/loadext.c a72909474dadce771d3669bf84bf689424f6f87d471fee898589c3ef9b2acfd9
F src/main.c 18f2145d572069dae91161add89446aec680aab296492a92ae5afcc2fc7c6b5a
F src/main.c 747ec45346c3826113bc081cafe1aa2df945e50540c4b3fb13ec02b5e231c3db
F src/malloc.c e20bb2b48abec52d3faf01cce12e8b4f95973755fafec98d45162dfdab111978
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@ -400,23 +400,23 @@ F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
F src/pcache.h 521bb9610d38ef17a3cc9b5ddafd4546c2ea67fa3d0e464823d73c2a28d50e11
F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc
F src/pragma.c 2362670a9d28b71708aecb2b9b10b3f7be71f4c950961c07e81dc400e3ce6371
F src/pragma.h a8a949000214fefb6210330eed8ccbbb4f752619a9871f31b3dedd4a240277fd
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/pragma.h 99d3df4a3d2f12c5227ad403f767334910e6356325b6d155a9a99b4037093460
F src/prepare.c a80a740b306a5fb2f2594d68776aade4ce1920687932e7c4dc0320ebdadcbb5d
F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c adf3ef9843135b1383321ad751f16f5a40c3f37925154555a3e61653d2a954e8
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 35ccfae64cecfa843d54a5898c4ab7d6595ce03d147267fa5eecdc8eab39cd6a
F src/shell.c 227b86f2bdd707d0a177a4805a5c0b0378ef8337ab1ad04f5d79dc479568735a
F src/sqlite.h.in 67fa8bd29808e7988e0ce36c8d4c6043eb1727f94522fc612687aa5af51931e6
F src/sqlite.h.in 2555ff1b79a1aadeb4eb761740351dc3027fa08120bf84511633ba75a630e7a8
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28
F src/sqliteInt.h 34a54fb47de2da1465f3d3ba1cd373db880bd5d588b0fe862a073ecacd6ddaae
F src/sqliteInt.h 620093497e54998c6b2a01ad98aed9b561716c3db4bde0cc37c8bf2416200bed
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c cbf6313f86400acdf7dbf55fcd218cd28d43110a1210967efbc4f250646f81c0
F src/test1.c c99f0442918a7a5d5b68a95d6024c211989e6c782c15ced5a558994baaf76a5e
F src/test1.c 735f7711e787f30ad4e0001220c580ce456d9f731e22e0e5f86dd5c7e41ccd4d
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
@ -473,13 +473,13 @@ F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c fc081ec6f63448dcd80d3dfad35baecfa104823254a815b081a4d9fe76e1db23
F src/vacuum.c 874c0f2f15ab2908748297d587d22d485ea96d55aaec91d4775dddb2e24d2ecf
F src/vdbe.c 6783778df820f3e0c68289fe5d12ddd34168b0eb1acf248668fec6e2ea1012d5
F src/vdbe.c 50f4f47bb190099b61fe87e239de17ad00636a522a271dd9b28329053091401d
F src/vdbe.h 70a409d171d4e51b962f0d53abf15c33c404c6aa4c9d62fb3a931b5a62ba9615
F src/vdbeInt.h cdcdabad4f5d6bf7a3beb826a7f33ee6f8f1cb220042bedd5b7d4bf2ea1d179f
F src/vdbeapi.c c961d8d9e0f52e2df60a6ddbbccd7d99dc4d00103db7e53f77fcef44fbd23178
F src/vdbeaux.c bc9b3228f6d99bef0d0ecaf3a0e0e8358b3873242d0d2fe944226de3fdf9521e
F src/vdbeaux.c d7c7a57f59dc22c05e9a16177615f604fe73588b0ebdc84b540ba5efe3ada430
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
F src/vdbemem.c 94b17d851f31d4fd075d47d373d4b33ed3962a6ecb82cf385018025751091360
F src/vdbemem.c 8d78df62becfd2dce3c317f64b32a94ecaff8346d814bc8b0b877b38a1ad3718
F src/vdbesort.c f512c68d0bf7e0105316a5594c4329358c8ee9cae3b25138df041d97516c0372
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
F src/vtab.c 35b9bdc2b41de32a417141d12097bcc4e29a77ed7cdb8f836d1d2305d946b61b
@ -490,7 +490,7 @@ F src/walker.c d46044e7a5842560dfe7122d93ff5145dd4a96f4d0bf5ba5910a7731b8c01e79
F src/where.c 74b0a05487e44e8c5d28ebe3bd77ca9719b1d5114235bed48079aee309a0bb4e
F src/whereInt.h 2a4b634d63ce488b46d4b0da8f2eaa8f9aeab202bc25ef76f007de5e3fba1f20
F src/wherecode.c 339ee802d9d311acf0cba8b5a9a092e167ef71c3a777d4b3e57de25d193251c7
F src/whereexpr.c 837c4a74cd023553b914e244c361a92c868a8b848783f4ff2387ccd61b6ccbc9
F src/whereexpr.c 61035ab300a5e2ee37aa531cbb621bc33873631a28dcacceb9e71c3b884c4d1d
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@ -505,7 +505,7 @@ F test/alter4.test b6d7b86860111864f6cddb54af313f5862dda23b
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 3eb35a4af972f98422e5dc0586501b17d103d321
F test/analyze3.test 1dccda46a6c374018af617fba00bfe297a61d442
F test/analyze3.test 8b3ef8ba6d1096b76c40e0925c0fe51e700d2b779cdda40914580de3f9b9d80f
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
@ -929,7 +929,7 @@ F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/kvtest.c d2b8cfc91047ebf6cac4f3a04f19c3a864e4ecfd683bbb65c395df450b8dc79c
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/like.test 0603f4fa0dad50987f70032c05800cbfa8985302
F test/like.test e7b1e724c731a219c4338e37cfe2c5861cd1cd7a856bbdd1d6045ae4f83dc7c7
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
@ -1522,7 +1522,7 @@ F tool/mkmsvcmin.tcl cbd93f1cfa3a0a9ae56fc958510aa3fc3ac65e29cb111716199e3d0e66e
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl bdd4c76449e9e0874ae7f0846868c42583e63b47a081b177a97f94e2b702b3e7
F tool/mkpragmatab.tcl aa94395a91b5bd47022b7db0c08126f047887e0d299cc19ec1c23a9e5b136961
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
F tool/mksqlite3c.tcl 226da6d794d7d43a31e159a6fa89db867bf1f5eafe4b37d031222287ef8dbadc
@ -1584,7 +1584,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 18f0616e15684ca327fb10a1d133331af1d3b75f609498982290f6ad69fcaced
R 956ace4d151b9d18ca3bfa0998026b83
U dan
Z 227909c502fe08051a0386f1253486e4
P 87b381663398f029f52cb5598aadd069b03034b6f833ce80ba762b406075a44e ebcfa73e1c8ebb4fc371a6dcf77f97b6e06e405a299c66182aa4b20423d519ec
R bb6b907fdeee773111627b13bd53e940
T +closed ebcfa73e1c8ebb4fc371a6dcf77f97b6e06e405a299c66182aa4b20423d519ec
U drh
Z cfbd76746fc81ebc7a88eb549c6e1ee7

View File

@ -1 +1 @@
87b381663398f029f52cb5598aadd069b03034b6f833ce80ba762b406075a44e
b82efd2a24914ace39acf99df75175042471fd73a8d31d66a40b15f63b342e10

View File

@ -152,7 +152,7 @@ static int hasSharedCacheTableLock(
** Return true immediately.
*/
if( (pBtree->sharable==0)
|| (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted))
|| (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommit))
){
return 1;
}
@ -229,7 +229,7 @@ static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
if( p->pgnoRoot==iRoot
&& p->pBtree!=pBtree
&& 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted)
&& 0==(p->pBtree->db->flags & SQLITE_ReadUncommit)
){
return 1;
}
@ -251,7 +251,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
assert( sqlite3BtreeHoldsMutex(p) );
assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
assert( p->db!=0 );
assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 );
assert( !(p->db->flags&SQLITE_ReadUncommit)||eLock==WRITE_LOCK||iTab==1 );
/* If requesting a write-lock, then the Btree must have an open write
** transaction on this file. And, obviously, for this to be so there
@ -329,7 +329,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
** obtain a read-lock using this function. The only read-lock obtained
** by a connection in read-uncommitted mode is on the sqlite_master
** table, and that lock is obtained in BtreeBeginTrans(). */
assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK );
assert( 0==(p->db->flags&SQLITE_ReadUncommit) || eLock==WRITE_LOCK );
/* This function should only be called on a sharable b-tree after it
** has been determined that no other b-tree holds a conflicting lock. */
@ -3021,7 +3021,7 @@ static int lockBtree(BtShared *pBt){
pageSize-usableSize);
return rc;
}
if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPage>nPageFile ){
if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){
rc = SQLITE_CORRUPT_BKPT;
goto page1_init_failed;
}

View File

@ -811,6 +811,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
{ SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
{ SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
{ SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose },
{ SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG },
};
unsigned int i;
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
@ -2915,6 +2916,9 @@ static int openDatabase(
#endif
#if defined(SQLITE_ENABLE_FTS3_TOKENIZER)
| SQLITE_Fts3Tokenizer
#endif
#if defined(SQLITE_ENABLE_QPSG)
| SQLITE_EnableQPSG
#endif
;
sqlite3HashInit(&db->aCollSeq);

View File

@ -458,7 +458,7 @@ static const PragmaName aPragmaName[] = {
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_ReadUncommitted },
/* iArg: */ SQLITE_ReadUncommit },
{/* zName: */ "recursive_triggers",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
@ -610,7 +610,7 @@ static const PragmaName aPragmaName[] = {
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
/* iArg: */ SQLITE_WriteSchema },
#endif
};
/* Number of pragmas: 60 on by default, 74 total. */

View File

@ -25,7 +25,7 @@ static void corruptSchema(
const char *zExtra /* Error information */
){
sqlite3 *db = pData->db;
if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){
if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){
char *z;
if( zObj==0 ) zObj = "?";
z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
@ -312,8 +312,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
}
if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
/* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){
/* Black magic: If the SQLITE_WriteSchema flag is set, then consider
** the schema loaded, even if errors occurred. In this situation the
** current sqlite3_prepare() operation will fail, but the following one
** will attempt to compile the supplied statement against whatever subset
@ -561,7 +561,7 @@ static int sqlite3Prepare(
if( rc ){
const char *zDb = db->aDb[i].zDbSName;
sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
testcase( db->flags & SQLITE_ReadUncommitted );
testcase( db->flags & SQLITE_ReadUncommit );
goto end_prepare;
}
}

View File

@ -2007,6 +2007,17 @@ struct sqlite3_mem_methods {
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
**
** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
** <dd>The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
** the [query planner stability guarantee] (QPSG). When the QPSG is active,
** a single SQL query statement will always use the same algorithm regardless
** of values of [bound parameters]. The QPSG disables some query optimizations
** that look at the values of bound parameters, which can make some queries
** slower. But the QPSG has the advantage of more predictable behavior. With
** the QPSG active, SQLite will always use the same query plan in the field as
** was used during testing in the lab.
** </dd>
**
** </dl>
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
@ -2016,6 +2027,7 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
/*

View File

@ -1450,8 +1450,8 @@ struct sqlite3 {
** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
** SQLITE_CacheSpill == PAGER_CACHE_SPILL
*/
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_MASTER */
#define SQLITE_LegacyFileFmt 0x00000002 /* Create new databases in format 1 */
#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
#define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */
@ -1462,29 +1462,34 @@ struct sqlite3 {
/* the count using a callback. */
#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
/* result set is empty */
#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */
#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */
#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */
#define SQLITE_VdbeAddopTrace 0x00001000 /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */
#define SQLITE_ReadUncommitted 0x0004000 /* For shared-cache mode */
#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */
#define SQLITE_RecoveryMode 0x00010000 /* Ignore schema errors */
#define SQLITE_ReverseOrder 0x00020000 /* Reverse unordered SELECTs */
#define SQLITE_RecTriggers 0x00040000 /* Enable recursive triggers */
#define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */
#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */
#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */
#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
#define SQLITE_LoadExtFunc 0x00800000 /* Enable load_extension() SQL func */
#define SQLITE_EnableTrigger 0x01000000 /* True to enable triggers */
#define SQLITE_DeferFKs 0x02000000 /* Defer all FK constraints */
#define SQLITE_QueryOnly 0x04000000 /* Disable database changes */
#define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */
#define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
#define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */
#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */
#define SQLITE_ReadUncommit 0x00000400 /* READ UNCOMMITTED in shared-cache */
#define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */
#define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */
#define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */
#define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */
#define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */
#define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */
#define SQLITE_EnableTrigger 0x00020000 /* True to enable triggers */
#define SQLITE_DeferFKs 0x00040000 /* Defer all FK constraints */
#define SQLITE_QueryOnly 0x00080000 /* Disable database changes */
#define SQLITE_CellSizeCk 0x00100000 /* Check btree cell sizes on load */
#define SQLITE_Fts3Tokenizer 0x00200000 /* Enable fts3_tokenizer(2) */
#define SQLITE_EnableQPSG 0x00400000 /* Query Planner Stability Guarantee */
/* The next four values are not used by PRAGMAs or by sqlite3_dbconfig() and
** could be factored out into a separate bit vector of the sqlite3 object. */
#define SQLITE_InternChanges 0x00800000 /* Uncommitted Hash table changes */
#define SQLITE_LoadExtFunc 0x01000000 /* Enable load_extension() SQL func */
#define SQLITE_PreferBuiltin 0x02000000 /* Preference to built-in funcs */
#define SQLITE_Vacuum 0x04000000 /* Currently in a VACUUM */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */
#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */
#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */
#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */
#endif
/*

View File

@ -7317,6 +7317,7 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
{ "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
{ "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
{ "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
{ "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG },
};
int i;
int v;

View File

@ -6571,7 +6571,7 @@ case OP_Expire: {
*/
case OP_TableLock: {
u8 isWriteLock = (u8)pOp->p3;
if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){
int p1 = pOp->p1;
assert( p1>=0 && p1<db->nDb );
assert( DbMaskTest(p->btreeMask, p1) );

View File

@ -4542,6 +4542,7 @@ sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
assert( iVar>0 );
if( v ){
Mem *pMem = &v->aVar[iVar-1];
assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
if( 0==(pMem->flags & MEM_Null) ){
sqlite3_value *pRet = sqlite3ValueNew(v->db);
if( pRet ){
@ -4561,6 +4562,7 @@ sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
*/
void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
assert( iVar>0 );
assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
if( iVar>=32 ){
v->expmask |= 0x80000000;
}else{

View File

@ -1482,14 +1482,13 @@ static int stat4ValueFromExpr(
/* Skip over any TK_COLLATE nodes */
pExpr = sqlite3ExprSkipCollate(pExpr);
assert( pExpr==0 || pExpr->op!=TK_REGISTER || pExpr->op2!=TK_VARIABLE );
if( !pExpr ){
pVal = valueNew(db, pAlloc);
if( pVal ){
sqlite3VdbeMemSetNull((Mem*)pVal);
}
}else if( pExpr->op==TK_VARIABLE
|| NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
){
}else if( pExpr->op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
Vdbe *v;
int iBindVar = pExpr->iColumn;
sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar);
@ -1497,9 +1496,7 @@ static int stat4ValueFromExpr(
pVal = valueNew(db, pAlloc);
if( pVal ){
rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
if( rc==SQLITE_OK ){
sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
}
sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
pVal->db = pParse->db;
}
}

View File

@ -216,7 +216,7 @@ static int isLikeOrGlob(
pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr);
op = pRight->op;
if( op==TK_VARIABLE ){
if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
Vdbe *pReprepare = pParse->pReprepare;
int iCol = pRight->iColumn;
pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB);

View File

@ -123,6 +123,36 @@ do_eqp_test analyze3-1.1.3 {
SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
} {0 0 0 {SCAN TABLE t1}}
# 2017-06-26: Verify that the SQLITE_DBCONFIG_ENABLE_QPSG setting disables
# the use of bound parameters by STAT4
#
db cache flush
unset -nocomplain l
unset -nocomplain u
do_eqp_test analyze3-1.1.3.100 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
set l 200
set u 300
do_eqp_test analyze3-1.1.3.101 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
set l 0
set u 1100
do_eqp_test analyze3-1.1.3.102 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
} {0 0 0 {SCAN TABLE t1}}
db cache flush
sqlite3_db_config db ENABLE_QPSG 1
do_eqp_test analyze3-1.1.3.103 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
db cache flush
sqlite3_db_config db ENABLE_QPSG 0
do_eqp_test analyze3-1.1.3.104 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
} {0 0 0 {SCAN TABLE t1}}
do_test analyze3-1.1.4 {
sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
} {199 0 14850}

View File

@ -160,6 +160,7 @@ ifcapable !like_opt {
#
proc queryplan {sql} {
set ::sqlite_sort_count 0
db cache flush
set data [execsql $sql]
if {$::sqlite_sort_count} {set x sort} {set x nosort}
lappend data $x
@ -196,7 +197,7 @@ do_test like-3.2 {
# With an index on t1.x and case sensitivity on, optimize completely.
#
do_test like-3.3 {
do_test like-3.3.100 {
set sqlite_like_count 0
execsql {
PRAGMA case_sensitive_like=on;
@ -206,10 +207,51 @@ do_test like-3.3 {
SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
}
} {abc abcd nosort {} i1}
do_test like-3.4 {
do_test like-3.3.101 {
set sqlite_like_count
} 0
# The like optimization works even when the pattern is a bound parameter
#
do_test like-3.3.102 {
set sqlite_like_count 0
unset -nocomplain ::likepat
set ::likepat abc%
queryplan {
SELECT x FROM t1 WHERE x LIKE $::likepat ORDER BY 1;
}
} {abc abcd nosort {} i1}
do_test like-3.3.103 {
set sqlite_like_count
} 0
# Except, the like optimization does not work for bound parameters if
# the query planner stability guarantee is active.
#
do_test like-3.3.104 {
set sqlite_like_count 0
sqlite3_db_config db QPSG 1
queryplan {
SELECT x FROM t1 WHERE x LIKE $::likepat ORDER BY 1;
}
} {abc abcd nosort {} i1}
do_test like-3.3.105 {
set sqlite_like_count
} 12
# The query planner stability guarantee does not disrupt explicit patterns
#
do_test like-3.3.105 {
set sqlite_like_count 0
queryplan {
SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
}
} {abc abcd nosort {} i1}
do_test like-3.3.106 {
set sqlite_like_count
} 0
sqlite3_db_config db QPSG 0
# The LIKE optimization still works when the RHS is a string with no
# wildcard. Ticket [e090183531fc2747]
#

View File

@ -120,12 +120,12 @@ set pragma_def {
NAME: writable_schema
TYPE: FLAG
ARG: SQLITE_WriteSchema|SQLITE_RecoveryMode
ARG: SQLITE_WriteSchema
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
NAME: read_uncommitted
TYPE: FLAG
ARG: SQLITE_ReadUncommitted
ARG: SQLITE_ReadUncommit
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
NAME: recursive_triggers