]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Have the schemalint output distinguish between existing and recommended indexes.
authordan <dan@noemail.net>
Thu, 18 Feb 2016 19:10:02 +0000 (19:10 +0000)
committerdan <dan@noemail.net>
Thu, 18 Feb 2016 19:10:02 +0000 (19:10 +0000)
FossilOrigin-Name: 4ab3df25f1fee7c8fea19d0c64b3e0e4d3b9c3cf

manifest
manifest.uuid
src/shell_indexes.c

index ff57fedd263511a3106c3db5247b6e216a37c420..c8c283d441a9a58d59e6e96546a8b4b604643a11 100644 (file)
--- 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
index 2e9ca33ba0d8ab724febd9d2153ce982f65ed56a..9ede1c42e8a641a2bd2e3e694cbd56e6fe1be1f1 100644 (file)
@@ -1 +1 @@
-cf0f7eeb4f6490b1e3f05b45e83b87cd64640846
\ No newline at end of file
+4ab3df25f1fee7c8fea19d0c64b3e0e4d3b9c3cf
\ No newline at end of file
index 54b59cd421fd651e395734f95d753999f7494746..755fff6403938402118d22f333dbc76a132a5b0e 100644 (file)
@@ -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);