]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix handling of partial indexes in checkindex.c (sqlite3_checker).
authordan <dan@noemail.net>
Tue, 7 Nov 2017 19:02:00 +0000 (19:02 +0000)
committerdan <dan@noemail.net>
Tue, 7 Nov 2017 19:02:00 +0000 (19:02 +0000)
FossilOrigin-Name: 31932a9eb8dbb33d5535715ae8bbfdc55ce66b1a1a0abd57cefe720eeb31e231

ext/repair/checkindex.c
ext/repair/test/checkindex01.test
manifest
manifest.uuid

index 46ecc12fc43ce899a85c3fef75b794ba703731a0..58706c1aab483471c9688e146ea7e8ba7c840176 100644 (file)
@@ -59,6 +59,7 @@ struct CidxColumn {
 
 typedef struct CidxIndex CidxIndex;
 struct CidxIndex {
+  char *zWhere;                   /* WHERE clause, if any */
   int nCol;                       /* Elements in aCol[] array */
   CidxColumn aCol[1];             /* Array of indexed columns */
 };
@@ -293,6 +294,7 @@ static void cidxFreeIndex(CidxIndex *pIdx){
     for(i=0; i<pIdx->nCol; i++){
       sqlite3_free(pIdx->aCol[i].zExpr);
     }
+    sqlite3_free(pIdx->zWhere);
     sqlite3_free(pIdx);
   }
 }
@@ -312,6 +314,24 @@ static int cidx_isident(char c){
 #define CIDX_PARSE_OPEN  2      /*  "(" */
 #define CIDX_PARSE_CLOSE 3      /*  ")" */
 
+/*
+** Argument zIn points into the start, middle or end of a CREATE INDEX
+** statement. If argument pbDoNotTrim is non-NULL, then this function
+** scans the input until it finds EOF, a comma (",") or an open or
+** close parenthesis character. It then sets (*pzOut) to point to said
+** character and returns a CIDX_PARSE_XXX constant as appropriate. The
+** parser is smart enough that special characters inside SQL strings
+** or comments are not returned for.
+**
+** Or, if argument pbDoNotTrim is NULL, then this function sets *pzOut
+** to point to the first character of the string that is not whitespace
+** or part of an SQL comment and returns CIDX_PARSE_EOF.
+**
+** Additionally, if pbDoNotTrim is not NULL and the element immediately
+** before (*pzOut) is an SQL comment of the form "-- comment", then
+** (*pbDoNotTrim) is set before returning. In all other cases it is
+** cleared.
+*/
 static int cidxFindNext(
   const char *zIn, 
   const char **pzOut,
@@ -320,6 +340,7 @@ static int cidxFindNext(
   const char *z = zIn;
 
   while( 1 ){
+    while( cidx_isspace(*z) ) z++;
     if( z[0]=='-' && z[1]=='-' ){
       z += 2;
       while( z[0]!='\n' ){
@@ -327,9 +348,18 @@ static int cidxFindNext(
         z++;
       }
       while( cidx_isspace(*z) ) z++;
-      *pbDoNotTrim = 1;
+      if( pbDoNotTrim ) *pbDoNotTrim = 1;
+    }else
+    if( z[0]=='/' && z[1]=='*' ){
+      z += 2;
+      while( z[0]!='*' || z[1]!='/' ){
+        if( z[1]=='\0' ) return CIDX_PARSE_EOF;
+        z++;
+      }
+      z += 2;
     }else{
       *pzOut = z;
+      if( pbDoNotTrim==0 ) return CIDX_PARSE_EOF;
       switch( *z ){
         case '\0':
           return CIDX_PARSE_EOF;
@@ -359,17 +389,6 @@ static int cidxFindNext(
           while( *z++!=']' );
           break;
   
-        case '/':
-          if( z[1]=='*' ){
-            z += 2;
-            while( z[0]!='*' || z[1]!='/' ){
-              if( z[1]=='\0' ) return CIDX_PARSE_EOF;
-              z++;
-            }
-            z += 2;
-            break;
-          }
-  
         default:
           z++;
           break;
@@ -424,6 +443,14 @@ static int cidxParseSQL(CidxCursor *pCsr, CidxIndex *pIdx, const char *zSql){
     z++;
   }
 
+  /* Search for a WHERE clause */
+  cidxFindNext(z, &z, 0);
+  if( 0==sqlite3_strnicmp(z, "where", 5) ){
+    pIdx->zWhere = cidxMprintf(&rc, "%s\n", &z[5]);
+  }else if( z[0]!='\0' ){
+    goto parse_error;
+  }
+
   return rc;
 
  parse_error:
@@ -477,6 +504,7 @@ static int cidxLookupIndex(
           p->zExpr = 0;
         }
         pIdx->nCol = iCol;
+        pIdx->zWhere = 0;
       }
       cidxFinalize(&rc, pInfo);
     }
@@ -700,36 +728,45 @@ int cidxGenerateScanSql(
     rc = cidxDecodeAfter(pCsr, pIdx->nCol, zAfterKey, &azAfter);
   }
 
-  if( rc || zAfterKey==0 ){
-    *pzSqlOut = cidxMprintf(&rc,
-        "SELECT (SELECT %s FROM %Q AS t WHERE %s), %s "
-        "FROM (SELECT %s FROM %Q ORDER BY %s) AS i",
-        zSubExpr, zTab, zSubWhere, zCurrentKey, 
-        zSrcList, zTab, zOrderBy
-    );
-  }else{
-    const char *zSep = "";
-    char *zSql;
-    int i;
-
-    zSql = cidxMprintf(&rc, 
-        "SELECT (SELECT %s FROM %Q WHERE %s), %s FROM (",
-        zSubExpr, zTab, zSubWhere, zCurrentKey
-    );
-    for(i=pIdx->nCol-1; i>=0; i--){
-      int j;
-      if( pIdx->aCol[i].bDesc && azAfter[i]==0 ) continue;
-      for(j=0; j<2; j++){
-        char *zWhere = cidxWhere(&rc, pIdx->aCol, azAfter, i, j);
-        zSql = cidxMprintf(&rc, "%z"
-            "%sSELECT * FROM (SELECT %s FROM %Q WHERE %z ORDER BY %s)",
-            zSql, zSep, zSrcList, zTab, zWhere, zOrderBy
-        );
-        zSep = " UNION ALL ";
-        if( pIdx->aCol[i].bDesc==0 ) break;
+  if( rc==SQLITE_OK ){
+    if( zAfterKey==0 ){
+      *pzSqlOut = cidxMprintf(&rc,
+          "SELECT (SELECT %s FROM %Q AS t WHERE %s), %s "
+          "FROM (SELECT %s FROM %Q INDEXED BY %Q %s%sORDER BY %s) AS i",
+          zSubExpr, zTab, zSubWhere, zCurrentKey, 
+          zSrcList, zTab, zIdxName, 
+          (pIdx->zWhere ? "WHERE " : ""), (pIdx->zWhere ? pIdx->zWhere : ""),
+          zOrderBy
+      );
+    }else{
+      const char *zSep = "";
+      char *zSql;
+      int i;
+  
+      zSql = cidxMprintf(&rc, 
+          "SELECT (SELECT %s FROM %Q WHERE %s), %s FROM (",
+          zSubExpr, zTab, zSubWhere, zCurrentKey
+      );
+      for(i=pIdx->nCol-1; i>=0; i--){
+        int j;
+        if( pIdx->aCol[i].bDesc && azAfter[i]==0 ) continue;
+        for(j=0; j<2; j++){
+          char *zWhere = cidxWhere(&rc, pIdx->aCol, azAfter, i, j);
+          zSql = cidxMprintf(&rc, "%z"
+              "%sSELECT * FROM ("
+                "SELECT %s FROM %Q INDEXED BY %Q WHERE %s%s%z ORDER BY %s"
+              ")",
+              zSql, zSep, zSrcList, zTab, zIdxName, 
+              pIdx->zWhere ? pIdx->zWhere : "",
+              pIdx->zWhere ? " AND " : "",
+              zWhere, zOrderBy
+          );
+          zSep = " UNION ALL ";
+          if( pIdx->aCol[i].bDesc==0 ) break;
+        }
       }
+      *pzSqlOut = cidxMprintf(&rc, "%z) AS i", zSql);
     }
-    *pzSqlOut = cidxMprintf(&rc, "%z) AS i", zSql);
   }
 
   sqlite3_free(zTab);
index d4abdcea7ec62ad7ad5d65137ff441b3e3b92412..25930397d36850ff063d712f07dfa224d6a96c7f 100644 (file)
@@ -60,7 +60,7 @@ do_execsql_test 1.2.2 {
   'five',5
   i1
   {}
-  {SELECT (SELECT a IS i.i0 FROM 't1' AS t WHERE "rowid" COLLATE BINARY IS i.i1), quote(i0)||','||quote(i1) FROM (SELECT (a) AS i0, ("rowid" COLLATE BINARY) AS i1 FROM 't1' ORDER BY 1,2) AS i}
+  {SELECT (SELECT a IS i.i0 FROM 't1' AS t WHERE "rowid" COLLATE BINARY IS i.i1), quote(i0)||','||quote(i1) FROM (SELECT (a) AS i0, ("rowid" COLLATE BINARY) AS i1 FROM 't1' INDEXED BY 'i1' ORDER BY 1,2) AS i}
 }
 
 do_index_check_test 1.3 i1 {
@@ -319,3 +319,33 @@ do_index_check_test 6.2 t6x3 {
   {} 3,2,1 
   {} 6,5,4
 }
+
+#-------------------------------------------------------------------------
+#
+do_execsql_test 7.0 {
+  CREATE TABLE t7(x INTEGER PRIMARY KEY, y, z);
+  INSERT INTO t7 VALUES(1, 1, 1);
+  INSERT INTO t7 VALUES(2, 2, 0);
+  INSERT INTO t7 VALUES(3, 3, 1);
+  INSERT INTO t7 VALUES(4, 4, 0);
+
+  CREATE INDEX t7i1 ON t7(y) WHERE z=1;
+  CREATE INDEX t7i2 ON t7(y) /* hello,world */ WHERE z=1;
+  CREATE INDEX t7i3 ON t7(y) WHERE -- yep 
+  z=1;
+  CREATE INDEX t7i4 ON t7(y) WHERE z=1 -- yep;
+}
+do_index_check_test 7.1 t7i1 {
+  {} 1,1 {} 3,3
+}
+do_index_check_test 7.2 t7i2 {
+  {} 1,1 {} 3,3
+}
+do_index_check_test 7.3 t7i3 {
+  {} 1,1 {} 3,3
+}
+do_index_check_test 7.4 t7i4 {
+  {} 1,1 {} 3,3
+}
+
+
index e2118d2f81d1a79bf24cbdf11c8e2ff106c75967..004ac6c071448e7f4e2dfe32c1cfbd6bcde6c82f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sproblem\scausing\san\sINDEXED\sBY\sspecifying\san\sunusable\spartial\sindex\sto\sbe\nmishandled.
-D 2017-11-07T18:20:15.108
+C Fix\shandling\sof\spartial\sindexes\sin\scheckindex.c\s(sqlite3_checker).
+D 2017-11-07T19:02:00.173
 F Makefile.in b142eb20482922153ebc77b261cdfd0a560ed05a81e9f6d9a2b0e8192922a1d2
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc a55372a22454e742ba7c8f6edf05b83213ec01125166ad7dcee0567e2f7fc81b
@@ -328,12 +328,12 @@ F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d0
 F ext/rbu/test_rbu.c 7073979b9cc80912bb03599ac8d85ab5d3bf03cfacd3463f2dcdd7822997533a
 F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
 F ext/repair/checkfreelist.c 0dbae18c1b552f58d64f8969e4fb1e7f11930c60a8c2a9a8d50b7f15bdfd54bd
-F ext/repair/checkindex.c 50264729469ae44abe9ce6c78944ec577e50faf26e362f3036142425807a8b67
+F ext/repair/checkindex.c 7d28c01a2e012ac64257d230fc452b2cafb78311a91a343633d01d95220f66f3
 F ext/repair/sqlite3_checker.c.in 4a5a3af3f450fe503e5a2985e98516dc2a6b9ad247449e284c1cf140fc91720f
 F ext/repair/sqlite3_checker.tcl cc69e7fbc163f94da4a6400609be001543442d9f8f57a797d1eeb7b897585730
 F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e
 F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc78249442da72ff3f8297398a69
-F ext/repair/test/checkindex01.test c4c9e62b1068ddb2d8b5c75580c3036713fc27ec105bbc579114da4ab29d53f4
+F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
 F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
 F ext/rtree/rtree.c cc91b6905bf55512c6ebc7dfdd37ac81c86f1753db8cfa6d62f0ee864464044f
@@ -1673,7 +1673,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 dc217b7cfe680044d8742e317701abd0269162da8f5cb097361ae7f47fd9ba2d
-R da22ae68c1c6ec503942cfb34af1b16b
+P 292a04086a902634fc514b379a2b245eb2681c1b84d9bb950b6ecb9aab28b468
+R 34ab99e7735ca564d873e9e5cddc35ee
 U dan
-Z 75bfd7248538a99270ce42b4a5b4456f
+Z e9b579d9d018f181ffb82f5d81fd8f28
index f26af75224e129def3855a537e7eb01e72edc737..ab0b7bdaafbf24963247668f08b5c3f67d7b9963 100644 (file)
@@ -1 +1 @@
-292a04086a902634fc514b379a2b245eb2681c1b84d9bb950b6ecb9aab28b468
\ No newline at end of file
+31932a9eb8dbb33d5535715ae8bbfdc55ce66b1a1a0abd57cefe720eeb31e231
\ No newline at end of file