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
This commit is contained in:
parent
1fe0537e51
commit
3780be115a
21
manifest
21
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
|
||||
|
@ -1 +1 @@
|
||||
6794b2dcb48b3507caccfc7867fc185818cf8291
|
||||
f2aa7842c8b9df24294f09e2bde27b3f08c455c7
|
28
src/build.c
28
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; i<pList->nExpr; 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
|
||||
|
@ -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; i<pList->nExpr; i++){
|
||||
if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user