From: dan Date: Thu, 18 Feb 2016 19:10:02 +0000 (+0000) Subject: Have the schemalint output distinguish between existing and recommended indexes. X-Git-Tag: version-3.22.0~147^2~52 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b12dfd01259fc16b7f0ac522aeec185daf7c128f;p=thirdparty%2Fsqlite.git Have the schemalint output distinguish between existing and recommended indexes. FossilOrigin-Name: 4ab3df25f1fee7c8fea19d0c64b3e0e4d3b9c3cf --- diff --git a/manifest b/manifest index ff57fedd26..c8c283d441 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Schemalint\schanges:\sAvoid\screating\scandidate\sindexes\sif\sa\scompatible\sindex\sexists.\sDo\snot\squote\sidentifiers\sthat\sdo\snot\srequire\sit. -D 2016-02-17T20:06:12.566 +C Have\sthe\sschemalint\soutput\sdistinguish\sbetween\sexisting\sand\srecommended\sindexes. +D 2016-02-18T19:10:02.440 F Makefile.in dac2776c84e0d533b158a9af6e57e05c4a6b19f3 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b0493f10caddb8adf992a4e6f1943141fc7c6816 @@ -350,7 +350,7 @@ F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c ff80004a9a6ece891a8d9327a88e7b6e2588ee6d F src/shell.c 2cde87e03712204231167c4a6c61b0eb5129e105 -F src/shell_indexes.c 6cc207072469f1ded8c3bb9de1d4b6590a28abb8 +F src/shell_indexes.c 277eb75b8cfb3c2bcf76e062baaa419779f824e7 F src/sqlite.h.in c7db059d3b810b70b83d9ed1436fa813eba22462 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d @@ -1430,7 +1430,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 73a7f010937828c5195a198604f976e8458cef73 -R 3a9a4af7276c9c00e5b2666c0bfe324e +P cf0f7eeb4f6490b1e3f05b45e83b87cd64640846 +R f54b8a1f9b5e206798931d383b1eb3a6 U dan -Z 82976e1002963ffa4a1c502f357a9ae9 +Z 5c18fceb59d8462f5aec79ee219a18a2 diff --git a/manifest.uuid b/manifest.uuid index 2e9ca33ba0..9ede1c42e8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cf0f7eeb4f6490b1e3f05b45e83b87cd64640846 \ No newline at end of file +4ab3df25f1fee7c8fea19d0c64b3e0e4d3b9c3cf \ No newline at end of file diff --git a/src/shell_indexes.c b/src/shell_indexes.c index 54b59cd421..755fff6403 100644 --- a/src/shell_indexes.c +++ b/src/shell_indexes.c @@ -98,12 +98,14 @@ struct IdxScan { ** Context object passed to idxWhereInfo() */ struct IdxContext { + char **pzErrmsg; IdxWhere *pCurrent; /* Current where clause */ int rc; /* Error code (if error has occurred) */ IdxScan *pScan; /* List of scan objects */ sqlite3 *dbm; /* In-memory db for this analysis */ sqlite3 *db; /* User database under analysis */ sqlite3_stmt *pInsertMask; /* To write to aux.depmask */ + i64 iIdxRowid; /* Rowid of first index created */ }; /* @@ -587,11 +589,12 @@ static int idxFindCompatible( } static int idxCreateFromCons( - sqlite3 *dbm, + IdxContext *pCtx, IdxScan *pScan, IdxConstraint *pEq, IdxConstraint *pTail ){ + sqlite3 *dbm = pCtx->dbm; int rc = SQLITE_OK; if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){ IdxTable *pTab = pScan->pTable; @@ -608,8 +611,8 @@ static int idxCreateFromCons( zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); } - /* Hash the list of columns to come up with a name for the index */ if( rc==SQLITE_OK ){ + /* Hash the list of columns to come up with a name for the index */ int i; for(i=0; zCols[i]; i++){ h += ((h<<3) + zCols[i]); @@ -630,6 +633,18 @@ static int idxCreateFromCons( #endif } } + if( rc==SQLITE_OK && pCtx->iIdxRowid==0 ){ + int rc2; + sqlite3_stmt *pLast = 0; + rc = idxPrepareStmt(dbm, &pLast, pCtx->pzErrmsg, + "SELECT max(rowid) FROM sqlite_master" + ); + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLast) ){ + pCtx->iIdxRowid = sqlite3_column_int64(pLast, 0); + } + rc2 = sqlite3_finalize(pLast); + if( rc==SQLITE_OK ) rc = rc2; + } sqlite3_free(zIdx); sqlite3_free(zCols); @@ -638,11 +653,11 @@ static int idxCreateFromCons( } static int idxCreateFromWhere( - sqlite3*, i64, IdxScan*, IdxWhere*, IdxConstraint*, IdxConstraint* + IdxContext*, i64, IdxScan*, IdxWhere*, IdxConstraint*, IdxConstraint* ); static int idxCreateForeachOr( - sqlite3 *dbm, + IdxContext *pCtx, i64 mask, /* Consider only these constraints */ IdxScan *pScan, /* Create indexes for this scan */ IdxWhere *pWhere, /* Read constraints from here */ @@ -653,22 +668,23 @@ static int idxCreateForeachOr( IdxWhere *p1; IdxWhere *p2; for(p1=pWhere->pOr; p1 && rc==SQLITE_OK; p1=p1->pNextOr){ - rc = idxCreateFromWhere(dbm, mask, pScan, p1, pEq, pTail); + rc = idxCreateFromWhere(pCtx, mask, pScan, p1, pEq, pTail); for(p2=p1->pSibling; p2 && rc==SQLITE_OK; p2=p2->pSibling){ - rc = idxCreateFromWhere(dbm, mask, pScan, p2, pEq, pTail); + rc = idxCreateFromWhere(pCtx, mask, pScan, p2, pEq, pTail); } } return rc; } static int idxCreateFromWhere( - sqlite3 *dbm, + 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 */ ){ + sqlite3 *dbm = pCtx->dbm; IdxConstraint *p1 = pEq; IdxConstraint *pCon; int rc; @@ -683,9 +699,9 @@ 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(dbm, pScan, p1, pTail); + rc = idxCreateFromCons(pCtx, pScan, p1, pTail); if( rc==SQLITE_OK ){ - rc = idxCreateForeachOr(dbm, mask, pScan, pWhere, p1, pTail); + rc = idxCreateForeachOr(pCtx, mask, pScan, pWhere, p1, pTail); } /* If no range/ORDER BY passed by the caller, create a version of the @@ -694,9 +710,9 @@ static int idxCreateFromWhere( for(pCon=pWhere->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){ assert( pCon->pLink==0 ); if( (mask & pCon->depmask)==pCon->depmask ){ - rc = idxCreateFromCons(dbm, pScan, p1, pCon); + rc = idxCreateFromCons(pCtx, pScan, p1, pCon); if( rc==SQLITE_OK ){ - rc = idxCreateForeachOr(dbm, mask, pScan, pWhere, p1, pCon); + rc = idxCreateForeachOr(pCtx, mask, pScan, pWhere, p1, pCon); } } } @@ -709,25 +725,24 @@ static int idxCreateFromWhere( ** Create candidate indexes in database [dbm] based on the data in ** linked-list pScan. */ -static int idxCreateCandidates( - sqlite3 *dbm, - IdxScan *pScan, - char **pzErrmsg -){ +static int idxCreateCandidates(IdxContext *pCtx){ + sqlite3 *dbm = pCtx->dbm; int rc2; int rc = SQLITE_OK; sqlite3_stmt *pDepmask; /* Foreach depmask */ IdxScan *pIter; - rc = idxPrepareStmt(dbm, &pDepmask, pzErrmsg, "SELECT mask FROM depmask"); + rc = idxPrepareStmt(pCtx->dbm, &pDepmask, pCtx->pzErrmsg, + "SELECT mask FROM depmask" + ); - for(pIter=pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){ + for(pIter=pCtx->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){ IdxWhere *pWhere = &pIter->where; while( SQLITE_ROW==sqlite3_step(pDepmask) && rc==SQLITE_OK ){ i64 mask = sqlite3_column_int64(pDepmask, 0); - rc = idxCreateFromWhere(dbm, mask, pIter, pWhere, 0, 0); + rc = idxCreateFromWhere(pCtx, mask, pIter, pWhere, 0, 0); if( rc==SQLITE_OK && pIter->pOrder ){ - rc = idxCreateFromWhere(dbm, mask, pIter, pWhere, 0, pIter->pOrder); + rc = idxCreateFromWhere(pCtx, mask, pIter, pWhere, 0, pIter->pOrder); } } } @@ -747,20 +762,22 @@ static void idxScanFree(IdxScan *pScan){ } int idxFindIndexes( - sqlite3 *dbm, /* Database handle */ + IdxContext *pCtx, const char *zSql, /* SQL to find indexes for */ void (*xOut)(void*, const char*), /* Output callback */ void *pOutCtx, /* Context for xOut() */ char **pzErr /* OUT: Error message (sqlite3_malloc) */ ){ + sqlite3 *dbm = pCtx->dbm; sqlite3_stmt *pExplain = 0; sqlite3_stmt *pSelect = 0; int rc, rc2; + int bFound = 0; rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,"EXPLAIN QUERY PLAN %s",zSql); if( rc==SQLITE_OK ){ rc = idxPrepareStmt(dbm, &pSelect, pzErr, - "SELECT sql FROM sqlite_master WHERE name = ?" + "SELECT rowid, sql FROM sqlite_master WHERE name = ?" ); } @@ -776,7 +793,12 @@ int idxFindIndexes( while( zIdx[nIdx]!='\0' && zIdx[nIdx]!=' ' ) nIdx++; sqlite3_bind_text(pSelect, 1, zIdx, nIdx, SQLITE_STATIC); if( SQLITE_ROW==sqlite3_step(pSelect) ){ - xOut(pOutCtx, sqlite3_column_text(pSelect, 0)); + i64 iRowid = sqlite3_column_int64(pSelect, 0); + const char *zSql = (const char*)sqlite3_column_text(pSelect, 1); + if( iRowid>=pCtx->iIdxRowid ){ + xOut(pOutCtx, zSql); + bFound = 1; + } } rc = sqlite3_reset(pSelect); break; @@ -785,7 +807,10 @@ int idxFindIndexes( } rc2 = sqlite3_reset(pExplain); if( rc==SQLITE_OK ) rc = rc2; - if( rc==SQLITE_OK ) xOut(pOutCtx, ""); + if( rc==SQLITE_OK ){ + if( bFound==0 ) xOut(pOutCtx, "(no new indexes)"); + xOut(pOutCtx, ""); + } while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){ int iSelectid = sqlite3_column_int(pExplain, 0); @@ -841,6 +866,7 @@ int shellIndexesCommand( rc = sqlite3_exec(dbm, "ATTACH ':memory:' AS aux;" "CREATE TABLE aux.depmask(mask PRIMARY KEY) WITHOUT ROWID;" + "CREATE TABLE aux.indexes(name PRIMARY KEY) WITHOUT ROWID;" "INSERT INTO aux.depmask VALUES(0);" , 0, 0, pzErrmsg ); @@ -872,13 +898,13 @@ int shellIndexesCommand( /* Create candidate indexes within the in-memory database file */ if( rc==SQLITE_OK ){ - rc = idxCreateCandidates(dbm, ctx.pScan, pzErrmsg); + rc = idxCreateCandidates(&ctx); } /* Figure out which of the candidate indexes are preferred by the query ** planner and report the results to the user. */ if( rc==SQLITE_OK ){ - rc = idxFindIndexes(dbm, zSql, xOut, pOutCtx, pzErrmsg); + rc = idxFindIndexes(&ctx, zSql, xOut, pOutCtx, pzErrmsg); } idxScanFree(ctx.pScan);