sqlite3_index_info *pIdxInfo
){
int i; /* Loop over constraints */
- int idx4 = -1; /* Index in pIdxInfo->aConstraint of PATH= */
- int idx5 = -1; /* Index in pIdxInfo->aConstraint of DIR= */
+ int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */
+ int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */
+ int seenPath = 0; /* True if an unusable PATH= constraint is seen */
+ int seenDir = 0; /* True if an unusable DIR= constraint is seen */
const struct sqlite3_index_constraint *pConstraint;
(void)tab;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- if( pConstraint->iColumn==4 && pConstraint->usable ) idx4 = i;
- if( pConstraint->iColumn==5 ) idx5 = i;
+ switch( pConstraint->iColumn ){
+ case FSDIR_COLUMN_PATH: {
+ if( pConstraint->usable ){
+ idxPath = i;
+ seenPath = 0;
+ }else if( idxPath<0 ){
+ seenPath = 1;
+ }
+ break;
+ }
+ case FSDIR_COLUMN_DIR: {
+ if( pConstraint->usable ){
+ idxDir = i;
+ seenDir = 0;
+ }else if( idxDir<0 ){
+ seenDir = 1;
+ }
+ break;
+ }
+ }
+ }
+ if( seenPath || seenDir ){
+ /* If input parameters are unusable, disallow this plan */
+ return SQLITE_CONSTRAINT;
}
- if( idx4<0 || (idx5>=0 && pIdxInfo->aConstraint[idx5].usable==0) ){
+ if( idxPath<0 ){
pIdxInfo->idxNum = 0;
- pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 60);
+ /* The pIdxInfo->estimatedCost should have been initialized to a huge
+ ** number. Leave it unchanged. */
+ pIdxInfo->estimatedRows = 0x7fffffff;
}else{
- pIdxInfo->aConstraintUsage[idx4].omit = 1;
- pIdxInfo->aConstraintUsage[idx4].argvIndex = 1;
- if( idx5>=0 ){
- pIdxInfo->aConstraintUsage[idx5].omit = 1;
- pIdxInfo->aConstraintUsage[idx5].argvIndex = 2;
+ pIdxInfo->aConstraintUsage[idxPath].omit = 1;
+ pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
+ if( idxDir>=0 ){
+ pIdxInfo->aConstraintUsage[idxDir].omit = 1;
+ pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
pIdxInfo->idxNum = 2;
pIdxInfo->estimatedCost = 10.0;
}else{
-C Fix\scomments\sand\smake\smagic\snumbers\sinto\s#defines\sin\sthe\sfsdir\nimplementation.
-D 2018-11-16T13:06:30.577
+C Enhance\sthe\sxBestIndex\sinterface\sof\svirtual\stable\sso\sthat\sif\sthe\sxBestIndex\nmethod\sreturns\sSQLITE_CONSTRAINT\sthen\sthat\sparticular\scombination\sof\nconstraints\sis\sconsidered\sunusable\sand\sdoes\snot\sparticipate\sfurther\sin\nquery\splanning.
+D 2018-11-16T13:56:15.713
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in b730006b54c990461d864c5387f2e6f13aadb0236804555fb010ed6865a5f058
F ext/misc/dbdump.c 12389a10c410fadf1e68eeb382def92d5a7fa9ce7cce4fb86a736fa2bac1000a
F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3
F ext/misc/explain.c c82dd86f1156d32b284e0523a4bf6a93a85ab2a812caed48963e0774f3327185
-F ext/misc/fileio.c 45acde5c065cc13bc9e65d4c3d623fa47441daf6d4a996d0ac9e6c9907b1d550
+F ext/misc/fileio.c e3153b04433897a18a3d17185845f286892e96fdf87f4301290d09c36ae1759f
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
F ext/misc/json1.c b0fba11c4f4e7c80534b08e120a296a8b301ee7e4d1a33f6647f1c047c8ce8e2
F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66
-F src/where.c f5da1079f084c569aa70fd4ada6b7e45b356e19708f1e5307493cc65857ec9e4
+F src/where.c 23f955de6db320fa5afcbe569687e649e5c9be1380c742fe7c5e9939e18cbcbe
F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f
F src/wherecode.c c45f03aefc2266b990df0fc4d7acc4e27f56f881f4fc0fc355b7cbc4d7189da5
F src/whereexpr.c 491f0894ad9903750cdecb7894437a0cabdffdd88f574d2b1c9ac85d14fe4b9c
F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a9a9224a
F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928
F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e
-F test/bestindex4.test 210eac9323ef88881212d6ae90c84dad86ec14d82c6f4fc9a9ee24c76a8f2014
+F test/bestindex4.test 038e3d0789332f3f1d61474f9bbc9c6d08c6bd1783a978f31f38ad82688de601
F test/bestindex5.test 67c1166131bb59f9e47c00118f7d432ca5491e6cae6ca3f87ca9db20103a78f9
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 7fffcee0fc3fe8d036f0d93ec17673992c3edcf2bb454dc90d80142435b37946
-R 2a2c80e2a75c50071a742aace6ac9b0f
+P c537c9c3630ca979bdccab977275bfc11cce33ea54adb71a4bd4f46c85f65c6f
+R bb405b8b26464e39757216d3bb32f7e9
U drh
-Z 0d4f2c0f6de8a62406810148e0ad4826
+Z ba10548cd8043453179e425b1b595795
-c537c9c3630ca979bdccab977275bfc11cce33ea54adb71a4bd4f46c85f65c6f
\ No newline at end of file
+684013cef6bfcfd920a4aec645df9f5d41ace8b34e75fca61759c1b4f82cc89e
\ No newline at end of file
** method of the virtual table with the sqlite3_index_info object that
** comes in as the 3rd argument to this function.
**
-** If an error occurs, pParse is populated with an error message and a
-** non-zero value is returned. Otherwise, 0 is returned and the output
-** part of the sqlite3_index_info structure is left populated.
+** If an error occurs, pParse is populated with an error message and an
+** appropriate error code is returned. A return of SQLITE_CONSTRAINT from
+** xBestIndex is not considered an error. SQLITE_CONSTRAINT indicates that
+** the current configuration of "unusable" flags in sqlite3_index_info can
+** not result in a valid plan.
**
** Whether or not an error is returned, it is the responsibility of the
** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates
rc = pVtab->pModule->xBestIndex(pVtab, p);
TRACE_IDX_OUTPUTS(p);
- if( rc!=SQLITE_OK ){
+ if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
if( rc==SQLITE_NOMEM ){
sqlite3OomFault(pParse->db);
}else if( !pVtab->zErrMsg ){
}
sqlite3_free(pVtab->zErrMsg);
pVtab->zErrMsg = 0;
-
-#if 0
- /* This error is now caught by the caller.
- ** Search for "xBestIndex malfunction" below */
- for(i=0; i<p->nConstraint; i++){
- if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
- sqlite3ErrorMsg(pParse,
- "table %s: xBestIndex returned an invalid plan", pTab->zName);
- }
- }
-#endif
-
- return pParse->nErr;
+ // assert( pParse->nErr==0 || (rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT) );
+ return rc;
}
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
/* Invoke the virtual table xBestIndex() method */
rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
- if( rc ) return rc;
+ if( rc ){
+ if( rc==SQLITE_CONSTRAINT ){
+ /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
+ ** that the particular combination of parameters provided is unusable.
+ ** Make no entries in the loop table.
+ */
+ return SQLITE_OK;
+ }
+ return rc;
+ }
mxTerm = -1;
assert( pNew->nLSlot>=nConstraint );
CREATE TABLE t1 (x INT PRIMARY KEY);
} {}
-do_execsql_test 2.1 {
- EXPLAIN QUERY PLAN SELECT * FROM t1, x1 WHERE x1.d=t1.x;
+do_eqp_test 2.1 {
+ SELECT * FROM t1, x1 WHERE x1.d=t1.x;
} {
- 3 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 0:}
- 7 0 0 {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?)}
+ QUERY PLAN
+ |--SCAN TABLE x1 VIRTUAL TABLE INDEX 0:
+ `--SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?)
}
-do_execsql_test 2.2 {
- EXPLAIN QUERY PLAN SELECT * FROM t1, x1(t1.x)
+do_eqp_test 2.2 {
+ SELECT * FROM t1, x1(t1.x)
} {
- 3 0 0 {SCAN TABLE t1}
- 5 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:}
+ QUERY PLAN
+ |--SCAN TABLE t1
+ `--SCAN TABLE x1 VIRTUAL TABLE INDEX 555:
}