Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -1144,25 +1144,20 @@ static int dupedExprStructSize(Expr *p, int flags){ int nSize; assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ assert( EXPR_FULLSIZE<=0xfff ); assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); - if( 0==flags || p->op==TK_SELECT_COLUMN -#ifndef SQLITE_OMIT_WINDOWFUNC - || p->pWin -#endif - ){ + if( 0==flags || p->op==TK_SELECT_COLUMN ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasProperty(p, EP_FromJoin) ); assert( !ExprHasProperty(p, EP_MemToken) ); assert( !ExprHasProperty(p, EP_NoReduce) ); - if( p->pLeft || p->x.pList ){ + if( p->eV || p->eX ){ nSize = EXPR_REDUCEDSIZE | EP_Reduced; }else{ - assert( p->pRight==0 ); nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; } } return nSize; } @@ -1187,30 +1182,31 @@ ** ** The value returned includes space to create a copy of the Expr struct ** itself and the buffer referred to by Expr.u.zToken, if any. ** ** If the EXPRDUP_REDUCE flag is set, then the return value includes -** space to duplicate all Expr nodes in the tree formed by Expr.pLeft +** space to duplicate all Expr nodes in the tree formed by Expr.v.pLeft ** and Expr.pRight variables (but not for any structures pointed to or ** descended from the Expr.x.pList or Expr.x.pSelect variables). */ static int dupedExprSize(Expr *p, int flags){ int nByte = 0; if( p ){ nByte = dupedExprNodeSize(p, flags); if( flags&EXPRDUP_REDUCE ){ - nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags); + if( p->eV==EV_Left ) nByte += dupedExprSize(p->v.pLeft, flags); + if( p->eV==EX_Right ) nByte += dupedExprSize(p->x.pRight, flags); } } return nByte; } /* ** This function is similar to sqlite3ExprDup(), except that if pzBuffer ** is not NULL then *pzBuffer is assumed to point to a buffer large enough ** to store the copy of expression p, the copies of p->u.zToken -** (if applicable), and the copies of the p->pLeft and p->pRight expressions, +** (if applicable), and the copies of the p->v.pLeft and p->pRight expressions, ** if any. Before returning, *pzBuffer is set to the first byte past the ** portion of the buffer copied into by this function. */ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ Expr *pNew; /* Value to return */ @@ -1266,20 +1262,27 @@ if( nToken ){ char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; memcpy(zToken, p->u.zToken, nToken); } +#if 0 if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){ /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ if( ExprHasProperty(p, EP_xIsSelect) ){ pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); }else{ pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); } } +#endif + if( p->eX==EX_Select ){ + pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); + }else if( p->eX==EX_List ){ + pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); + } - /* Fill in pNew->pLeft and pNew->pRight. */ + /* Fill in pNew->v.pLeft and pNew->x.pRight. */ if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ zAlloc += dupedExprNodeSize(p, dupFlags); if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ pNew->pLeft = p->pLeft ? exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2424,10 +2424,12 @@ ** allocated, regardless of whether or not EP_Reduced is set. */ struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ + u8 eV; /* Which element of v-union is used */ + u8 eX; /* Which element of x-union is used */ u32 flags; /* Various flags. EP_* See below */ union { char *zToken; /* Token value. Zero terminated and dequoted */ int iValue; /* Non-negative integer value if EP_IntValue */ } u; @@ -2435,15 +2437,21 @@ /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ - Expr *pLeft; /* Left subnode */ - Expr *pRight; /* Right subnode */ - union { - ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */ - Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */ + union { /* Usage determined by Expr.eV */ + Expr *pLeft; /* Left subnode */ + Expr *pVector; /* TK_SELECT_COLUMN: The SELECT */ + Window *pWin; /* TK_FUNCTION: Window definition */ + } v; + union { /* Usage determined by Expr.eX */ + Expr *pRight; /* Right subnode */ + ExprList *pList; /* IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */ + Select *pSelect; /* IN, EXISTS, SELECT */ + Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL + ** for a column of an index on an expression */ } x; /* If the EP_Reduced flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. @@ -2464,17 +2472,26 @@ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 op2; /* TK_REGISTER: original value of Expr.op ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ - Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL - ** for a column of an index on an expression */ -#ifndef SQLITE_OMIT_WINDOWFUNC - Window *pWin; /* Window definition for window functions */ -#endif }; +/* +** Allowed values for the Expr.eV and Expr.eX fields: +*/ +#define EV_None 0 /* Expr.v is not used */ +#define EV_Left 1 /* Expr.v.pLeft */ +#define EV_Vector 2 /* Expr.v.pVector */ +#dfeine EV_Win 3 /* Expr.v.pWin */ + +#define EX_None 0 /* Expr.x is not used */ +#define EX_Right 1 /* Expr.x.pRight */ +#define EX_List 2 /* Expr.x.pList */ +#define EX_Select 3 /* Expr.x.pSelect */ +#define EX_Tab 4 /* Expr.x.pTab */ + /* ** The following are the meanings of bits in the Expr.flags field. */ #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ #define EP_Agg 0x000002 /* Contains one or more aggregate functions */