From: drh Date: Wed, 31 Jul 2013 19:05:22 +0000 (+0000) Subject: Resolve names in CREATE INDEX WHERE clauses and detect errors. Disallow X-Git-Tag: version-3.8.0~55^2~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3780be115a461f5da136079e5b9002dc70cbf25e;p=thirdparty%2Fsqlite.git Resolve names in CREATE INDEX WHERE clauses and detect errors. Disallow expressions that contain variables, subqueries, or functions. The expression is still not used for anything, however. still unused. FossilOrigin-Name: f2aa7842c8b9df24294f09e2bde27b3f08c455c7 --- diff --git a/manifest b/manifest index 0a7fe0faee..ac70fd7d00 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Here\sbegins\san\sexperimental\sbranch\sfor\sexploring\sthe\sidea\sof\sa\spartial\sindex.\nThis\scheck-in\sis\sable\sto\sparse\sa\sWHERE\sclause\son\sa\sCREATE\sINDEX\sstatement,\sbut\ndoes\snot\sactually\sdo\sanythingn\swith\sthat\sWHERE\sclause\syet. -D 2013-07-31T18:12:26.006 +C Resolve\snames\sin\sCREATE\sINDEX\sWHERE\sclauses\sand\sdetect\serrors.\s\sDisallow\nexpressions\sthat\scontain\svariables,\ssubqueries,\sor\sfunctions.\nThe\sexpression\sis\sstill\snot\sused\sfor\sanything,\showever.\nstill\sunused. +D 2013-07-31T19:05:22.844 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -166,7 +166,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 3f7bbfd72efb1cbf6a49515c376a031767ec930a F src/btree.h 6fa8a3ff2483d0bb64a9f0105a8cedeac9e00cca F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2 -F src/build.c c2903be4a825d6be0a518f87b60e0dcf878782d3 +F src/build.c f1ef982f38df47b11e10edaf03fbcc77b80e4d35 F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 4262c227bc91cecc61ae37ed3a40f08069cfa267 @@ -214,14 +214,14 @@ F src/pragma.c 2790c5175bc3f95d2a0cf39283d144b9b012fec7 F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f F src/printf.c 41c49dac366a3a411190001a8ab495fa8887974e F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 -F src/resolve.c 89f9003e8316ee3a172795459efc2a0274e1d5a8 +F src/resolve.c ada80e8df5d4ab0a21cf65ec5be8ba3b826e2b6f F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 91b62654caf8dfe292fb8882715e575d34ad3874 F src/shell.c 52f975eae87c8338c4dfbf4c2842d2a0971f01fd F src/sqlite.h.in d6a7523d6795317aac574fccc67d9df25253771c F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h c99f22c5bda01f07e2f9a9a8cb2c0b9adeea696c +F src/sqliteInt.h ffe632c1de338b459af86e6df712f4583c05b8af F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -589,7 +589,7 @@ F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6 F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7 F test/index4.test 2983216eb8c86ee62d9ed7cb206b5cc3331c0026 F test/index5.test fc07c14193c0430814e7a08b5da46888ee795c33 -F test/index6.test cbd74aa8604e29982438a7defae9fadaf9605336 +F test/index6.test 11171203a09b543d6181af59c298d2429ba762e2 F test/indexedby.test 0e959308707c808515c3a51363f7a9835027108c F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 @@ -1104,10 +1104,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P eb6d4278b8516e0571269049d1eaa55066f51b1a -R d0aa2f7065f4153ebb66a1af4210e515 -T *branch * partial-indices -T *sym-partial-indices * -T -sym-trunk * +P 6794b2dcb48b3507caccfc7867fc185818cf8291 +R 1d2a041bdd5863b9d0e35692b3da5ea5 U drh -Z cfed8379e8335c37848dda6e7de0acdf +Z 96979d6477d3e0c5f80978a86c33129b diff --git a/manifest.uuid b/manifest.uuid index 4d7035783c..9efb9eb1f1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6794b2dcb48b3507caccfc7867fc185818cf8291 \ No newline at end of file +f2aa7842c8b9df24294f09e2bde27b3f08c455c7 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 7ca2ef00cc..61a1ae9e3c 100644 --- a/src/build.c +++ b/src/build.c @@ -1522,26 +1522,7 @@ void sqlite3EndTable( /* Resolve names in all CHECK constraint expressions. */ if( p->pCheck ){ - SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ - NameContext sNC; /* Name context for pParse->pNewTable */ - ExprList *pList; /* List of all CHECK constraints */ - int i; /* Loop counter */ - - memset(&sNC, 0, sizeof(sNC)); - memset(&sSrc, 0, sizeof(sSrc)); - sSrc.nSrc = 1; - sSrc.a[0].zName = p->zName; - sSrc.a[0].pTab = p; - sSrc.a[0].iCursor = -1; - sNC.pParse = pParse; - sNC.pSrcList = &sSrc; - sNC.ncFlags = NC_IsCheck; - pList = p->pCheck; - for(i=0; inExpr; i++){ - if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){ - return; - } - } + sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck); } #endif /* !defined(SQLITE_OMIT_CHECK) */ @@ -2702,8 +2683,11 @@ Index *sqlite3CreateIndex( pIndex->uniqNotNull = onError==OE_Abort; pIndex->autoIndex = (u8)(pName==0); pIndex->pSchema = db->aDb[iDb].pSchema; - pIndex->pPartIdxWhere = pPIWhere; - pPIWhere = 0; + if( pPIWhere ){ + sqlite3ResolveSelfReference(pParse, pTab, NC_PartIdx, pPIWhere, 0); + pIndex->pPartIdxWhere = pPIWhere; + pPIWhere = 0; + } assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); /* Check to see if we should honor DESC requests on index columns diff --git a/src/resolve.c b/src/resolve.c index 91efcaa1a1..239e0eb2a0 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -522,6 +522,39 @@ Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){ return p; } +/* +** Report an error that an expression is not valid for a partial index WHERE +** clause. +*/ +static void notValidPartIdxWhere( + Parse *pParse, /* Leave error message here */ + NameContext *pNC, /* The name context */ + const char *zMsg /* Type of error */ +){ + if( (pNC->ncFlags & NC_PartIdx)!=0 ){ + sqlite3ErrorMsg(pParse, "%s prohibited in partial index WHERE clauses", + zMsg); + } +} + +#ifndef SQLITE_OMIT_CHECK +/* +** Report an error that an expression is not valid for a CHECK constraint. +*/ +static void notValidCheckConstraint( + Parse *pParse, /* Leave error message here */ + NameContext *pNC, /* The name context */ + const char *zMsg /* Type of error */ +){ + if( (pNC->ncFlags & NC_IsCheck)!=0 ){ + sqlite3ErrorMsg(pParse,"%s prohibited in CHECK constraints", zMsg); + } +} +#else +# define notValidCheckConstraint(P,N,M) +#endif + + /* ** This routine is callback for sqlite3WalkExpr(). ** @@ -621,6 +654,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_CONST_FUNC ); assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + notValidPartIdxWhere(pParse, pNC, "functions"); zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); @@ -686,11 +720,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_IN ); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ int nRef = pNC->nRef; -#ifndef SQLITE_OMIT_CHECK - if( (pNC->ncFlags & NC_IsCheck)!=0 ){ - sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints"); - } -#endif + notValidCheckConstraint(pParse, pNC, "subqueries"); + notValidPartIdxWhere(pParse, pNC, "subqueries"); sqlite3WalkSelect(pWalker, pExpr->x.pSelect); assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ @@ -699,14 +730,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } break; } -#ifndef SQLITE_OMIT_CHECK case TK_VARIABLE: { - if( (pNC->ncFlags & NC_IsCheck)!=0 ){ - sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints"); - } + notValidCheckConstraint(pParse, pNC, "parameters"); + notValidPartIdxWhere(pParse, pNC, "parameters"); break; } -#endif } return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue; } @@ -1331,3 +1359,45 @@ void sqlite3ResolveSelectNames( w.u.pNC = pOuterNC; sqlite3WalkSelect(&w, p); } + +/* +** Resolve names in expressions that can only reference a single table: +** +** * CHECK constraints +** * WHERE clauses on partial indices +** +** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression +** is set to -1 and the Expr.iColumn value is set to the column number. +** +** Any errors cause an error message to be set in pParse. +*/ +void sqlite3ResolveSelfReference( + Parse *pParse, /* Parsing context */ + Table *pTab, /* The table being referenced */ + int type, /* NC_IsCheck or NC_PartIdx */ + Expr *pExpr, /* Expression to resolve. May be NULL. */ + ExprList *pList /* Expression list to resolve. May be NUL. */ +){ + SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ + NameContext sNC; /* Name context for pParse->pNewTable */ + int i; /* Loop counter */ + + assert( type==NC_IsCheck || type==NC_PartIdx ); + memset(&sNC, 0, sizeof(sNC)); + memset(&sSrc, 0, sizeof(sSrc)); + sSrc.nSrc = 1; + sSrc.a[0].zName = pTab->zName; + sSrc.a[0].pTab = pTab; + sSrc.a[0].iCursor = -1; + sNC.pParse = pParse; + sNC.pSrcList = &sSrc; + sNC.ncFlags = type; + if( sqlite3ResolveExprNames(&sNC, pExpr) ) return; + if( pList ){ + for(i=0; inExpr; i++){ + if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){ + return; + } + } + } +} diff --git a/src/sqliteInt.h b/src/sqliteInt.h index dba1e55b83..3d4a57f3a4 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2019,6 +2019,7 @@ struct NameContext { #define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */ #define NC_AsMaybe 0x10 /* Resolve to AS terms of the result set only ** if no other resolution is available */ +#define NC_PartIdx 0x20 /* True if resolving a partial index WHERE */ /* ** An instance of the following structure contains all information @@ -3063,6 +3064,7 @@ void sqlite3SelectPrep(Parse*, Select*, NameContext*); int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); int sqlite3ResolveExprNames(NameContext*, Expr*); void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); +void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); void sqlite3ColumnDefault(Vdbe *, Table *, int, int); void sqlite3AlterFinishAddColumn(Parse *, Token *); diff --git a/test/index6.test b/test/index6.test index 7bd83769f3..89b9c48761 100644 --- a/test/index6.test +++ b/test/index6.test @@ -30,4 +30,31 @@ do_test index6-1.1 { } } {14 20} +do_test index6-1.2 { + catchsql { + CREATE INDEX bad1 ON t1(a,b) WHERE c IS NOT NULL; + } +} {1 {no such column: c}} +do_test index6-1.3 { + catchsql { + CREATE INDEX bad1 ON t1(a,b) WHERE EXISTS(SELECT * FROM t1); + } +} {1 {subqueries prohibited in partial index WHERE clauses}} +do_test index6-1.4 { + catchsql { + CREATE INDEX bad1 ON t1(a,b) WHERE a!=?1; + } +} {1 {parameters prohibited in partial index WHERE clauses}} +do_test index6-1.5 { + catchsql { + CREATE INDEX bad1 ON t1(a,b) WHERE a!=random(); + } +} {1 {functions prohibited in partial index WHERE clauses}} +do_test index6-1.6 { + catchsql { + CREATE INDEX bad1 ON t1(a,b) WHERE a NOT LIKE 'abc%'; + } +} {1 {functions prohibited in partial index WHERE clauses}} + + finish_test