From: dan Date: Thu, 6 Apr 2017 18:44:18 +0000 (+0000) Subject: Changes to allow indexes to be recommended for queries on SQL views. X-Git-Tag: version-3.22.0~147^2~42 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d8ac297233b9af6cc74f92a14834eaacda781676;p=thirdparty%2Fsqlite.git Changes to allow indexes to be recommended for queries on SQL views. FossilOrigin-Name: 0884ff1da2e27b146c764b73cf299a1f2cfe213c4a79bde34dec02d1fc946e70 --- diff --git a/manifest b/manifest index 0e690d166d..ce8fc15893 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssome\ssupport\sfor\sOR\sterms\sto\ssqlite3_whereinfo_hook(). -D 2017-04-04T17:50:31.913 +C Changes\sto\sallow\sindexes\sto\sbe\srecommended\sfor\squeries\son\sSQL\sviews. +D 2017-04-06T18:44:18.391 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a @@ -403,7 +403,7 @@ F src/resolve.c 3e518b962d932a997fae373366880fc028c75706 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 2496d0cc6368dabe7ad2e4c7f5ed3ad9aa3b4d11cd90f33fa1d1ef72493f43aa F src/shell.c e524688c2544167f835ba43e24309f8707ca60c8ab6eb5c263a12c8618a233b8 -F src/shell_indexes.c d40ea0a81112df7bdccd7232238bee0bbb39699085ea78cc08fd863bf052a63b +F src/shell_indexes.c 1f5ab036ec189411aeea27e6e74ab0009d831764d5d8517455dcb6b6a734beb7 F src/sqlite.h.in ae5c9cbf2e77492c319fca08769575d9695e64718a16d32324944d24e291bcf7 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28 @@ -1120,7 +1120,7 @@ F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1 F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d F test/shell5.test 50a732c1c2158b1cd62cf53975ce1ea7ce6b9dc9 -F test/shell6.test 081067c1afcb38da50134ffd5ccc0a59ede14f41959486f733ffbba689c0ccfa +F test/shell6.test f37998b26dfde19beaaf06a4cb60c476f66a7b54affff3870a2a011402c13efc F test/shell7.test 07751911b294698e0c5df67bcbd29e7d2f0f2907 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 @@ -1571,7 +1571,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a54aef35da11f7508a8888a159372036a362fc52afa1df752dc835db334c4330 -R 51e547bc1c25ea79dd375d8f020224f3 +P 5cd070000da1d9e399090677b4db75dc5639c33211385d6eb84f14a4d0b617cd +R aa13547c61fd31f43629472eaf9b4008 U dan -Z fe378068686ea107c39185021a17b4ae +Z 2f3b5e2a515dd18e4123d763066c9a33 diff --git a/manifest.uuid b/manifest.uuid index 7669c54b05..3b9f56b1a1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5cd070000da1d9e399090677b4db75dc5639c33211385d6eb84f14a4d0b617cd \ No newline at end of file +0884ff1da2e27b146c764b73cf299a1f2cfe213c4a79bde34dec02d1fc946e70 \ No newline at end of file diff --git a/src/shell_indexes.c b/src/shell_indexes.c index e061f04d3f..c05672e9e0 100644 --- a/src/shell_indexes.c +++ b/src/shell_indexes.c @@ -43,44 +43,18 @@ struct IdxConstraint { /* ** A WHERE clause. Made up of IdxConstraint objects. Example WHERE clause: ** -** a=? AND b=? AND ((c=? AND d=?) OR e=?) AND (f=? OR g=?) AND h>? +** a=? AND b=? AND c=? AND d=? AND e>? AND f (c=? AND d=?) -> pNextOr -> (f=?) -** | | -** pSibling pSibling -** | | -** V V -** (e=?) (g=?) -** -** IdxWhere.pParent is only used while constructing a tree of IdxWhere -** structures. It is NULL for the root IdxWhere. For all others, the parent -** WHERE clause. */ struct IdxWhere { IdxConstraint *pEq; /* List of == constraints */ IdxConstraint *pRange; /* List of < constraints */ - IdxWhere *pOr; /* List of OR constraints */ - IdxWhere *pNextOr; /* Next in OR constraints of same IdxWhere */ - IdxWhere *pSibling; /* Next branch in single OR constraint */ - IdxWhere *pParent; /* Parent object (or NULL) */ }; /* @@ -246,40 +220,6 @@ static void idxDatabaseError( *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); } -static char *idxQueryToList( - sqlite3 *db, - const char *zBind, - int *pRc, - char **pzErrmsg, - const char *zSql -){ - char *zRet = 0; - if( *pRc==SQLITE_OK ){ - sqlite3_stmt *pStmt = 0; - int rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_text(pStmt, 1, zBind, -1, SQLITE_TRANSIENT); - while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ - const char *z = (const char*)sqlite3_column_text(pStmt, 0); - zRet = sqlite3_mprintf("%z%s%Q", zRet, zRet?", ":"", z); - if( zRet==0 ){ - rc = SQLITE_NOMEM; - } - } - rc = sqlite3_finalize(pStmt); - } - - if( rc ){ - idxDatabaseError(db, pzErrmsg); - sqlite3_free(zRet); - zRet = 0; - } - *pRc = rc; - } - - return zRet; -} - static int idxPrepareStmt( sqlite3 *db, /* Database handle to compile against */ sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */ @@ -331,7 +271,7 @@ static int idxGetTableInfo( rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTbl); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ - const char *zCol = sqlite3_column_text(p1, 1); + const char *zCol = (const char*)sqlite3_column_text(p1, 1); nByte += 1 + strlen(zCol); rc = sqlite3_table_column_metadata( db, "main", zTbl, zCol, 0, &zCol, 0, 0, 0 @@ -354,7 +294,7 @@ static int idxGetTableInfo( nCol = 0; while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ - const char *zCol = sqlite3_column_text(p1, 1); + const char *zCol = (const char*)sqlite3_column_text(p1, 1); int nCopy = strlen(zCol) + 1; pNew->aCol[nCol].zName = pCsr; pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5); @@ -392,38 +332,24 @@ static int idxCreateTables( char **pzErrmsg /* OUT: Error message */ ){ int rc = SQLITE_OK; + int rc2; IdxScan *pIter; - for(pIter=pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){ - rc = idxGetTableInfo(db, pIter, pzErrmsg); + sqlite3_stmt *pSql = 0; - /* Test if table has already been created. If so, jump to the next - ** iteration of the loop. */ - if( rc==SQLITE_OK ){ - sqlite3_stmt *pSql = 0; - rc = idxPrintfPrepareStmt(dbm, &pSql, pzErrmsg, - "SELECT 1 FROM sqlite_master WHERE tbl_name = %Q", pIter->zTable - ); - if( rc==SQLITE_OK ){ - int bSkip = 0; - if( sqlite3_step(pSql)==SQLITE_ROW ) bSkip = 1; - rc = sqlite3_finalize(pSql); - if( bSkip ) continue; - } - } + /* Copy the entire schema of database [db] into [dbm]. */ + rc = idxPrintfPrepareStmt(db, &pSql, pzErrmsg, + "SELECT sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%%'" + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ + const char *zSql = (const char*)sqlite3_column_text(pSql, 0); + rc = sqlite3_exec(dbm, zSql, 0, 0, pzErrmsg); + } + rc2 = sqlite3_finalize(pSql); + if( rc==SQLITE_OK ) rc = rc2; - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_stmt *pSql = 0; - rc = idxPrintfPrepareStmt(db, &pSql, pzErrmsg, - "SELECT sql FROM sqlite_master WHERE tbl_name = %Q", pIter->zTable - ); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ - const char *zSql = (const char*)sqlite3_column_text(pSql, 0); - rc = sqlite3_exec(dbm, zSql, 0, 0, pzErrmsg); - } - rc2 = sqlite3_finalize(pSql); - if( rc==SQLITE_OK ) rc = rc2; - } + /* Load IdxTable objects */ + for(pIter=pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){ + rc = idxGetTableInfo(db, pIter, pzErrmsg); } return rc; } @@ -655,26 +581,6 @@ static int idxCreateFromWhere( IdxContext*, i64, IdxScan*, IdxWhere*, IdxConstraint*, IdxConstraint* ); -static int idxCreateForeachOr( - IdxContext *pCtx, - i64 mask, /* Consider only these constraints */ - IdxScan *pScan, /* Create indexes for this scan */ - IdxWhere *pWhere, /* Read constraints from here */ - IdxConstraint *pEq, /* == constraints for inclusion */ - IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */ -){ - int rc = SQLITE_OK; - IdxWhere *p1; - IdxWhere *p2; - for(p1=pWhere->pOr; p1 && rc==SQLITE_OK; p1=p1->pNextOr){ - rc = idxCreateFromWhere(pCtx, mask, pScan, p1, pEq, pTail); - for(p2=p1->pSibling; p2 && rc==SQLITE_OK; p2=p2->pSibling){ - rc = idxCreateFromWhere(pCtx, mask, pScan, p2, pEq, pTail); - } - } - return rc; -} - /* ** Return true if list pList (linked by IdxConstraint.pLink) contains ** a constraint compatible with *p. Otherwise return false. @@ -695,7 +601,6 @@ static int idxCreateFromWhere( IdxConstraint *pEq, /* == constraints for inclusion */ IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */ ){ - sqlite3 *dbm = pCtx->dbm; IdxConstraint *p1 = pEq; IdxConstraint *pCon; int rc; @@ -714,9 +619,6 @@ static int idxCreateFromWhere( /* Create an index using the == constraints collected above. And the ** range constraint/ORDER BY terms passed in by the caller, if any. */ rc = idxCreateFromCons(pCtx, pScan, p1, pTail); - if( rc==SQLITE_OK ){ - rc = idxCreateForeachOr(pCtx, mask, pScan, pWhere, p1, pTail); - } /* If no range/ORDER BY passed by the caller, create a version of the ** index for each range constraint that matches the mask. */ @@ -728,9 +630,6 @@ static int idxCreateFromWhere( && idxFindConstraint(pTail, pCon)==0 ){ rc = idxCreateFromCons(pCtx, pScan, p1, pCon); - if( rc==SQLITE_OK ){ - rc = idxCreateForeachOr(pCtx, mask, pScan, pWhere, p1, pCon); - } } } } @@ -749,7 +648,7 @@ static int idxCreateCandidates(IdxContext *pCtx){ sqlite3_stmt *pDepmask; /* Foreach depmask */ IdxScan *pIter; - rc = idxPrepareStmt(pCtx->dbm, &pDepmask, pCtx->pzErrmsg, + rc = idxPrepareStmt(dbm, &pDepmask, pCtx->pzErrmsg, "SELECT mask FROM depmask" ); @@ -774,7 +673,6 @@ static void idxScanFree(IdxScan *pScan){ IdxScan *pNext; for(pIter=pScan; pIter; pIter=pNext){ pNext = pIter->pNextScan; - } } @@ -841,11 +739,11 @@ int idxFindIndexes( if( rc==SQLITE_OK ) rc = rc2; if( rc==SQLITE_OK ){ sqlite3_stmt *pLoop = 0; - rc = idxPrepareStmt(dbm, &pLoop, pzErr, "SELECT name FROM aux.indexes"); + rc = idxPrepareStmt(dbm, &pLoop, pzErr,"SELECT name||';' FROM aux.indexes"); if( rc==SQLITE_OK ){ while( SQLITE_ROW==sqlite3_step(pLoop) ){ bFound = 1; - xOut(pOutCtx, sqlite3_column_text(pLoop, 0)); + xOut(pOutCtx, (const char*)sqlite3_column_text(pLoop, 0)); } rc = sqlite3_finalize(pLoop); } diff --git a/test/shell6.test b/test/shell6.test index c44ccf0bd1..2f7c251827 100644 --- a/test/shell6.test +++ b/test/shell6.test @@ -66,7 +66,7 @@ do_setup_rec_test 1.2 { } { SELECT * FROM t1 WHERE b>?; } { - CREATE INDEX t1_idx_00000062 ON t1(b) + CREATE INDEX t1_idx_00000062 ON t1(b); 0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?) } @@ -75,7 +75,7 @@ do_setup_rec_test 1.3 { } { SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ? } { - CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE) + CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE); 0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b? AND b