aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/delete.c2
-rw-r--r--src/expr.c56
-rw-r--r--src/parse.y12
-rw-r--r--src/select.c4
-rw-r--r--src/sqliteInt.h5
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