From: dan Date: Tue, 7 Nov 2017 19:02:00 +0000 (+0000) Subject: Fix handling of partial indexes in checkindex.c (sqlite3_checker). X-Git-Tag: version-3.22.0~205 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0e90ad6a374f2747d54c8addad5a4a66b5401ed8;p=thirdparty%2Fsqlite.git Fix handling of partial indexes in checkindex.c (sqlite3_checker). FossilOrigin-Name: 31932a9eb8dbb33d5535715ae8bbfdc55ce66b1a1a0abd57cefe720eeb31e231 --- diff --git a/ext/repair/checkindex.c b/ext/repair/checkindex.c index 46ecc12fc4..58706c1aab 100644 --- a/ext/repair/checkindex.c +++ b/ext/repair/checkindex.c @@ -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; inCol; 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); diff --git a/ext/repair/test/checkindex01.test b/ext/repair/test/checkindex01.test index d4abdcea7e..25930397d3 100644 --- a/ext/repair/test/checkindex01.test +++ b/ext/repair/test/checkindex01.test @@ -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 +} + + diff --git a/manifest b/manifest index e2118d2f81..004ac6c071 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index f26af75224..ab0b7bdaaf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -292a04086a902634fc514b379a2b245eb2681c1b84d9bb950b6ecb9aab28b468 \ No newline at end of file +31932a9eb8dbb33d5535715ae8bbfdc55ce66b1a1a0abd57cefe720eeb31e231 \ No newline at end of file