diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/delete.c | 2 | ||||
-rw-r--r-- | src/expr.c | 56 | ||||
-rw-r--r-- | src/parse.y | 12 | ||||
-rw-r--r-- | src/select.c | 4 | ||||
-rw-r--r-- | src/sqliteInt.h | 5 |
5 files changed, 53 insertions, 26 deletions
diff --git a/src/delete.c b/src/delete.c index 011fb80de..ef6aace1c 100644 --- a/src/delete.c +++ b/src/delete.c @@ -189,7 +189,7 @@ Expr *sqlite3LimitWhere( pInClause->x.pSelect = pSelect; pInClause->flags |= EP_xIsSelect; - sqlite3ExprSetHeight(pParse, pInClause); + sqlite3ExprSetHeightAndFlags(pParse, pInClause); return pInClause; /* something went wrong. clean up anything allocated. */ diff --git a/src/expr.c b/src/expr.c index 2def950f2..496c7a317 100644 --- a/src/expr.c +++ b/src/expr.c @@ -146,10 +146,20 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ break; } if( p->flags & EP_Collate ){ - if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ + if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ - p = p->pRight; + Expr *pNext = p->pRight; + if( p->x.pList!=0 && !ExprHasProperty(p, EP_xIsSelect) ){ + int i; + for(i=0; i<p->x.pList->nExpr; i++){ + if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ + pNext = p->x.pList->a[i].pExpr; + break; + } + } + } + p = pNext; } }else{ break; @@ -355,6 +365,9 @@ static void heightOfSelect(Select *p, int *pnHeight){ ** Expr.pSelect member has a height of 1. Any other expression ** has a height equal to the maximum height of any other ** referenced Expr plus one. +** +** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags, +** if appropriate. */ static void exprSetHeight(Expr *p){ int nHeight = 0; @@ -362,8 +375,9 @@ static void exprSetHeight(Expr *p){ heightOfExpr(p->pRight, &nHeight); if( ExprHasProperty(p, EP_xIsSelect) ){ heightOfSelect(p->x.pSelect, &nHeight); - }else{ + }else if( p->x.pList ){ heightOfExprList(p->x.pList, &nHeight); + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); } p->nHeight = nHeight + 1; } @@ -372,8 +386,11 @@ static void exprSetHeight(Expr *p){ ** Set the Expr.nHeight variable using the exprSetHeight() function. If ** the height is greater than the maximum allowed expression depth, ** leave an error in pParse. +** +** Also propagate all EP_Propagate flags from the Expr.x.pList into +** Expr.flags. */ -void sqlite3ExprSetHeight(Parse *pParse, Expr *p){ +void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ exprSetHeight(p); sqlite3ExprCheckHeight(pParse, p->nHeight); } @@ -387,8 +404,17 @@ int sqlite3SelectExprHeight(Select *p){ heightOfSelect(p, &nHeight); return nHeight; } -#else - #define exprSetHeight(y) +#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */ +/* +** Propagate all EP_Propagate flags from the Expr.x.pList into +** Expr.flags. +*/ +void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ + if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){ + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); + } +} +#define exprSetHeight(y) #endif /* SQLITE_MAX_EXPR_DEPTH>0 */ /* @@ -594,7 +620,7 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ } pNew->x.pList = pList; assert( !ExprHasProperty(pNew, EP_xIsSelect) ); - sqlite3ExprSetHeight(pParse, pNew); + sqlite3ExprSetHeightAndFlags(pParse, pNew); return pNew; } @@ -1210,16 +1236,18 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ } /* -** Return TRUE if any expression in ExprList has any of the EP_* -** properties given by "m" +** Return the bitwise-OR of all Expr.flags fields in the given +** ExprList. */ -int sqlite3AnyExprListHasProperty(const ExprList *pList, u32 m){ +u32 sqlite3ExprListFlags(const ExprList *pList){ int i; - if( pList==0 ) return 0; - for(i=0; i<pList->nExpr; i++){ - if( ExprHasProperty(pList->a[i].pExpr, m) ) return 1; + u32 m = 0; + if( pList ){ + for(i=0; i<pList->nExpr; i++){ + m |= pList->a[i].pExpr->flags; + } } - return 0; + return m; } /* diff --git a/src/parse.y b/src/parse.y index 6730312d7..78e79cd36 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1078,7 +1078,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Y; - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); } @@ -1092,7 +1092,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( A.pExpr ){ A.pExpr->x.pSelect = X; ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, X); } @@ -1104,7 +1104,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( A.pExpr ){ A.pExpr->x.pSelect = Y; ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, Y); } @@ -1118,7 +1118,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( A.pExpr ){ A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } @@ -1131,7 +1131,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( p ){ p->x.pSelect = Y; ExprSetProperty(p, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeight(pParse, p); + sqlite3ExprSetHeightAndFlags(pParse, p); }else{ sqlite3SelectDelete(pParse->db, Y); } @@ -1145,7 +1145,7 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y; - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); sqlite3ExprDelete(pParse->db, Z); diff --git a/src/select.c b/src/select.c index 2c4c9e41f..91b3d4345 100644 --- a/src/select.c +++ b/src/select.c @@ -3338,8 +3338,8 @@ static int flattenSubquery( if( isAgg ) return 0; /* Restriction (1) */ if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) - || sqlite3AnyExprListHasProperty(p->pEList,EP_Subquery) - || sqlite3AnyExprListHasProperty(p->pOrderBy,EP_Subquery) + || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0 + || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0 ){ return 0; /* Restriction (2b) */ } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e07ee4a5b..3f9a3a7cc 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3159,7 +3159,7 @@ ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); void sqlite3ExprListDelete(sqlite3*, ExprList*); -int sqlite3AnyExprListHasProperty(const ExprList*,u32); +u32 sqlite3ExprListFlags(const ExprList*); int sqlite3Init(sqlite3*, char**); int sqlite3InitCallback(void*, int, char**, char**); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); @@ -3743,12 +3743,11 @@ void sqlite3MemJournalOpen(sqlite3_file *); int sqlite3MemJournalSize(void); int sqlite3IsMemJournal(sqlite3_file *); +void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p); #if SQLITE_MAX_EXPR_DEPTH>0 - void sqlite3ExprSetHeight(Parse *pParse, Expr *p); int sqlite3SelectExprHeight(Select *); int sqlite3ExprCheckHeight(Parse*, int); #else - #define sqlite3ExprSetHeight(x,y) #define sqlite3SelectExprHeight(x) 0 #define sqlite3ExprCheckHeight(x,y) #endif |