]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Changes to allow indexes to be recommended for queries on SQL views.
authordan <dan@noemail.net>
Thu, 6 Apr 2017 18:44:18 +0000 (18:44 +0000)
committerdan <dan@noemail.net>
Thu, 6 Apr 2017 18:44:18 +0000 (18:44 +0000)
FossilOrigin-Name: 0884ff1da2e27b146c764b73cf299a1f2cfe213c4a79bde34dec02d1fc946e70

manifest
manifest.uuid
src/shell_indexes.c
test/shell6.test

index 0e690d166db2b3df63281b96b1cc6721d59dd129..ce8fc158938447312a34310cb8c660b0d2eb1b90 100644 (file)
--- 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
index 7669c54b05f7b7ba993bbef3e1b15f74466505c8..3b9f56b1a1bedbc7fe12dc9ecf88a069cfec3136 100644 (file)
@@ -1 +1 @@
-5cd070000da1d9e399090677b4db75dc5639c33211385d6eb84f14a4d0b617cd
\ No newline at end of file
+0884ff1da2e27b146c764b73cf299a1f2cfe213c4a79bde34dec02d1fc946e70
\ No newline at end of file
index e061f04d3f7f93ba31e27152fce9e080f6df1481..c05672e9e09d3c78f01a80c84d05b7c453865316 100644 (file)
@@ -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<?
 **
-** The above is decomposed into 5 AND connected clauses. The first two are
+** The above is decomposed into 6 AND connected clauses. The first four are
 ** added to the IdxWhere.pEq linked list, the following two into 
-** IdxWhere.pOr and the last into IdxWhere.pRange.
+** IdxWhere.pRange.
 **
 ** IdxWhere.pEq and IdxWhere.pRange are simple linked lists of IdxConstraint
 ** objects linked by the IdxConstraint.pNext field.
-**
-** The list headed at IdxWhere.pOr and linked by IdxWhere.pNextOr contains
-** all "OR" terms that belong to the current WHERE clause. In the example
-** above, there are two OR terms:
-**
-**   ((c=? AND d=?) OR e=?)
-**   (f=? OR g=?)
-**
-** Within an OR term, the OR connected sub-expressions are termed siblings.
-** These are connected into a linked list by the pSibling pointers. Each OR
-** term above consists of two siblings.
-**
-**   pOr -> (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);
     }
index c44ccf0bd16483f83304076742d39ba27350bc56..2f7c2518272112372121ee7d1d83e85c10861ef8 100644 (file)
@@ -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<?)
 }
 
@@ -84,7 +84,7 @@ do_setup_rec_test 1.4 {
 } {
   SELECT a FROM t1 ORDER BY b;
 } {
-  CREATE INDEX t1_idx_00000062 ON t1(b) 
+  CREATE INDEX t1_idx_00000062 ON t1(b);
   0|0|0|SCAN TABLE t1 USING INDEX t1_idx_00000062
 }
 
@@ -93,7 +93,7 @@ do_setup_rec_test 1.5 {
 } {
   SELECT a FROM t1 WHERE a=? ORDER BY b;
 } {
-  CREATE INDEX t1_idx_000123a7 ON t1(a, b) 
+  CREATE INDEX t1_idx_000123a7 ON t1(a, b);
   0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
 }
 
@@ -102,7 +102,7 @@ do_setup_rec_test 1.6 {
 } {
   SELECT min(a) FROM t1
 } {
-  CREATE INDEX t1_idx_00000061 ON t1(a) 
+  CREATE INDEX t1_idx_00000061 ON t1(a);
   0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
 }
 
@@ -111,7 +111,7 @@ do_setup_rec_test 1.7 {
 } {
   SELECT * FROM t1 ORDER BY a, b, c;
 } {
-  CREATE INDEX t1_idx_033e95fe ON t1(a, b, c) 
+  CREATE INDEX t1_idx_033e95fe ON t1(a, b, c);
   0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
 }
 
@@ -120,7 +120,7 @@ do_setup_rec_test 1.8 {
 } {
   SELECT * FROM t1 ORDER BY a ASC, b COLLATE nocase DESC, c ASC;
 } {
-  CREATE INDEX t1_idx_5be6e222 ON t1(a, b COLLATE NOCASE DESC, c)
+  CREATE INDEX t1_idx_5be6e222 ON t1(a, b COLLATE NOCASE DESC, c);
   0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_5be6e222
 }
 
@@ -129,7 +129,7 @@ do_setup_rec_test 1.9 {
 } {
   SELECT * FROM t1 WHERE a=?
 } {
-  CREATE INDEX t1_idx_00000061 ON t1(a) 
+  CREATE INDEX t1_idx_00000061 ON t1(a);
   0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
 }
 
@@ -141,7 +141,7 @@ do_setup_rec_test 8.1 {
 } {
   SELECT * FROM "t t" WHERE a=?
 } {
-  CREATE INDEX 't t_idx_00000061' ON 't t'(a)
+  CREATE INDEX 't t_idx_00000061' ON 't t'(a);
   0|0|0|SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?) 
 }
 
@@ -150,7 +150,7 @@ do_setup_rec_test 8.2 {
 } {
   SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
 } {
-  CREATE INDEX 't t_idx_00000062' ON 't t'(b) 
+  CREATE INDEX 't t_idx_00000062' ON 't t'(b);
   0|0|0|SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b<?)
 }
 
@@ -161,7 +161,7 @@ do_setup_rec_test 9.1 {
 } {
   SELECT * FROM t3 WHERE "b b" = ?
 } {
-  CREATE INDEX t3_idx_00050c52 ON t3('b b') 
+  CREATE INDEX t3_idx_00050c52 ON t3('b b');
   0|0|0|SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
 }
 
@@ -170,7 +170,7 @@ do_setup_rec_test 9.2 {
 } {
   SELECT * FROM t3 ORDER BY "b b"
 } {
-  CREATE INDEX t3_idx_00050c52 ON t3('b b') 
+  CREATE INDEX t3_idx_00050c52 ON t3('b b');
   0|0|0|SCAN TABLE t3 USING INDEX t3_idx_00050c52
 }
 
@@ -182,8 +182,8 @@ do_setup_rec_test 10.1 {
 } {
   SELECT * FROM t5, t6 WHERE a=? AND b=c AND c=?
 } {
-  CREATE INDEX t5_idx_000123a7 ON t5(a, b) 
-  CREATE INDEX t6_idx_00000063 ON t6(c) 
+  CREATE INDEX t5_idx_000123a7 ON t5(a, b);
+  CREATE INDEX t6_idx_00000063 ON t6(c);
   0|0|1|SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?) 
   0|1|0|SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
 }
@@ -195,8 +195,8 @@ do_setup_rec_test 11.1 {
 } {
   SELECT * FROM t7 WHERE a=? OR b=?
 } {
-  CREATE INDEX t7_idx_00000061 ON t7(a) 
-  CREATE INDEX t7_idx_00000062 ON t7(b)
+  CREATE INDEX t7_idx_00000061 ON t7(a);
+  CREATE INDEX t7_idx_00000062 ON t7(b);
   0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?) 
   0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
 }