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 */
};
for(i=0; i<pIdx->nCol; i++){
sqlite3_free(pIdx->aCol[i].zExpr);
}
+ sqlite3_free(pIdx->zWhere);
sqlite3_free(pIdx);
}
}
#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,
const char *z = zIn;
while( 1 ){
+ while( cidx_isspace(*z) ) z++;
if( z[0]=='-' && z[1]=='-' ){
z += 2;
while( z[0]!='\n' ){
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;
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;
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:
p->zExpr = 0;
}
pIdx->nCol = iCol;
+ pIdx->zWhere = 0;
}
cidxFinalize(&rc, pInfo);
}
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);
'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 {
{} 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
+}
+
+
-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
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
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