diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/alter.c | 2 | ||||
-rw-r--r-- | src/attach.c | 6 | ||||
-rw-r--r-- | src/build.c | 14 | ||||
-rw-r--r-- | src/delete.c | 2 | ||||
-rw-r--r-- | src/expr.c | 238 | ||||
-rw-r--r-- | src/func.c | 5 | ||||
-rw-r--r-- | src/parse.y | 2 | ||||
-rw-r--r-- | src/pragma.c | 2 | ||||
-rw-r--r-- | src/resolve.c | 34 | ||||
-rw-r--r-- | src/select.c | 26 | ||||
-rw-r--r-- | src/sqliteInt.h | 29 | ||||
-rw-r--r-- | src/tokenize.c | 2 | ||||
-rw-r--r-- | src/trigger.c | 36 | ||||
-rw-r--r-- | src/update.c | 2 | ||||
-rw-r--r-- | src/util.c | 2 | ||||
-rw-r--r-- | src/vdbemem.c | 19 | ||||
-rw-r--r-- | src/walker.c | 2 | ||||
-rw-r--r-- | src/where.c | 12 |
18 files changed, 267 insertions, 168 deletions
diff --git a/src/alter.c b/src/alter.c index 0c3e00e51..ac185f2da 100644 --- a/src/alter.c +++ b/src/alter.c @@ -12,7 +12,7 @@ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.59 2009/05/27 10:31:29 drh Exp $ +** $Id: alter.c,v 1.60 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" diff --git a/src/attach.c b/src/attach.c index 2b5ddb589..9af765973 100644 --- a/src/attach.c +++ b/src/attach.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.91 2009/05/27 10:31:29 drh Exp $ +** $Id: attach.c,v 1.92 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -41,7 +41,7 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr) if( pExpr->op!=TK_ID ){ rc = sqlite3ResolveExprNames(pName, pExpr); if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){ - sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->zToken); + sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken); return SQLITE_ERROR; } }else{ @@ -312,7 +312,7 @@ static void codeAttach( #ifndef SQLITE_OMIT_AUTHORIZATION if( pAuthArg ){ - char *zAuthArg = pAuthArg->zToken; + char *zAuthArg = pAuthArg->u.zToken; if( zAuthArg==0 ){ goto attach_end; } diff --git a/src/build.c b/src/build.c index 66f932e6e..ce8385992 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.545 2009/05/27 10:31:29 drh Exp $ +** $Id: build.c,v 1.546 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -1181,14 +1181,12 @@ void sqlite3AddCheckConstraint( #ifndef SQLITE_OMIT_CHECK Table *pTab = pParse->pNewTable; if( pTab && !IN_DECLARE_VTAB ){ - /* The CHECK expression must be duplicated so that tokens refer - ** to malloced space and not the (ephemeral) text of the CREATE TABLE - ** statement */ - pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, - sqlite3ExprDup(db, pCheckExpr, 0)); - } + pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, pCheckExpr); + }else #endif - sqlite3ExprDelete(db, pCheckExpr); + { + sqlite3ExprDelete(db, pCheckExpr); + } } /* diff --git a/src/delete.c b/src/delete.c index e5177819c..95ef3cef7 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.202 2009/05/27 10:31:29 drh Exp $ +** $Id: delete.c,v 1.203 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" diff --git a/src/expr.c b/src/expr.c index 6fe400d1e..a94b825eb 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.437 2009/05/27 10:31:29 drh Exp $ +** $Id: expr.c,v 1.438 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -40,7 +40,8 @@ char sqlite3ExprAffinity(Expr *pExpr){ } #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ - return sqlite3AffinityType(pExpr->zToken); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + return sqlite3AffinityType(pExpr->u.zToken); } #endif if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) @@ -388,6 +389,12 @@ int sqlite3SelectExprHeight(Select *p){ ** parameter is ignored if pToken is NULL or if the token does not ** appear to be quoted. If the quotes were of the form "..." (double-quotes) ** then the EP_DblQuoted flag is set on the expression node. +** +** Special case: If op==TK_INTEGER and pToken points to a string that +** can be translated into a 32-bit integer, then the token is not +** stored in u.zToken. Instead, the integer values is written +** into u.iValue and the EP_IntValue flag is set. No extra storage +** is allocated to hold the integer text and the dequote flag is ignored. */ Expr *sqlite3ExprAlloc( sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ @@ -396,26 +403,33 @@ Expr *sqlite3ExprAlloc( int dequote /* True to dequote */ ){ Expr *pNew; - int nExtra; + int nExtra = 0; + int iValue; if( pToken ){ - nExtra = pToken->n+1; - }else{ - nExtra = 0; + if( op!=TK_INTEGER || pToken->z==0 + || sqlite3GetInt32(pToken->z, &iValue)==0 ){ + nExtra = pToken->n+1; + } } pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra); if( pNew ){ pNew->op = (u8)op; pNew->iAgg = -1; if( pToken ){ - int c; - pNew->zToken = (char*)&pNew[1]; - memcpy(pNew->zToken, pToken->z, pToken->n); - pNew->zToken[pToken->n] = 0; - if( dequote && nExtra>=3 - && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){ - sqlite3Dequote(pNew->zToken); - if( c=='"' ) pNew->flags |= EP_DblQuoted; + if( nExtra==0 ){ + pNew->flags |= EP_IntValue; + pNew->u.iValue = iValue; + }else{ + int c; + pNew->u.zToken = (char*)&pNew[1]; + memcpy(pNew->u.zToken, pToken->z, pToken->n); + pNew->u.zToken[pToken->n] = 0; + if( dequote && nExtra>=3 + && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){ + sqlite3Dequote(pNew->u.zToken); + if( c=='"' ) pNew->flags |= EP_DblQuoted; + } } } #if SQLITE_MAX_EXPR_DEPTH>0 @@ -550,7 +564,8 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ const char *z; if( pExpr==0 ) return; - z = pExpr->zToken; + assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); + z = pExpr->u.zToken; assert( z!=0 ); assert( z[0]!=0 ); if( z[1]==0 ){ @@ -584,7 +599,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ for(i=0; i<pParse->nVarExpr; i++){ Expr *pE = pParse->apVarExpr[i]; assert( pE!=0 ); - if( memcmp(pE->zToken, z, n)==0 && pE->zToken[n]==0 ){ + if( memcmp(pE->u.zToken, z, n)==0 && pE->u.zToken[n]==0 ){ pExpr->iTable = pE->iTable; break; } @@ -616,19 +631,13 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ ** Substructure is deleted. */ void sqlite3ExprClear(sqlite3 *db, Expr *p){ + assert( p!=0 ); if( !ExprHasAnyProperty(p, EP_TokenOnly) ){ - if( ExprHasProperty(p, EP_Reduced) ){ - /* Subtrees are part of the same memory allocation when EP_Reduced set */ - if( p->pLeft ) sqlite3ExprClear(db, p->pLeft); - if( p->pRight ) sqlite3ExprClear(db, p->pRight); - }else{ - /* Subtrees are separate allocations when EP_Reduced is clear */ - sqlite3ExprDelete(db, p->pLeft); - sqlite3ExprDelete(db, p->pRight); - /* Sometimes the zToken is allocated separately */ - if( p->flags2 & EP2_FreeToken ) sqlite3DbFree(db, p->zToken); + sqlite3ExprDelete(db, p->pLeft); + sqlite3ExprDelete(db, p->pRight); + if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){ + sqlite3DbFree(db, p->u.zToken); } - /* x.pSelect and x.pList are always separately allocated */ if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ @@ -643,7 +652,9 @@ void sqlite3ExprClear(sqlite3 *db, Expr *p){ void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p==0 ) return; sqlite3ExprClear(db, p); - sqlite3DbFree(db, p); + if( !ExprHasProperty(p, EP_Static) ){ + sqlite3DbFree(db, p); + } } /* @@ -658,34 +669,67 @@ static int exprStructSize(Expr *p){ } /* -** sqlite3ExprDup() has been called to create a copy of expression p with -** the EXPRDUP_XXX flags passed as the second argument. This function -** returns the space required for the copy of the Expr structure only. -** This is always one of EXPR_FULLSIZE, EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE. +** The dupedExpr*Size() routines each return the number of bytes required +** to store a copy of an expression or expression tree. They differ in +** how much of the tree is measured. +** +** dupedExprStructSize() Size of only the Expr structure +** dupedExprNodeSize() Size of Expr + space for token +** dupedExprSize() Expr + token + subtree components +** +*************************************************************************** +** +** The dupedExprStructSize() function returns two values OR-ed together: +** (1) the space required for a copy of the Expr structure only and +** (2) the EP_xxx flags that indicate what the structure size should be. +** The return values is always one of: +** +** EXPR_FULLSIZE +** EXPR_REDUCEDSIZE | EP_Reduced +** EXPR_TOKENONLYSIZE | EP_TokenOnly +** +** The size of the structure can be found by masking the return value +** of this routine with 0xfff. The flags can be found by masking the +** return value with EP_Reduced|EP_TokenOnly. +** +** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size +** (unreduced) Expr objects as they or originally constructed by the parser. +** During expression analysis, extra information is computed and moved into +** later parts of teh Expr object and that extra information might get chopped +** off if the expression is reduced. Note also that it does not work to +** make a EXPRDUP_REDUCE copy of a reduced expression. It is only legal +** to reduce a pristine expression tree from the parser. The implementation +** of dupedExprStructSize() contain multiple assert() statements that attempt +** to enforce this constraint. */ static int dupedExprStructSize(Expr *p, int flags){ int nSize; + assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ if( 0==(flags&EXPRDUP_REDUCE) ){ nSize = EXPR_FULLSIZE; - }else if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ - nSize = EXPR_REDUCEDSIZE; }else{ - nSize = EXPR_TOKENONLYSIZE; + assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(p, EP_FromJoin) ); + assert( (p->flags2 & EP2_MallocedToken)==0 ); + assert( (p->flags2 & EP2_Irreducible)==0 ); + if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ + nSize = EXPR_REDUCEDSIZE | EP_Reduced; + }else{ + nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; + } } return nSize; } /* -** sqlite3ExprDup() has been called to create a copy of expression p with -** the EXPRDUP_XXX passed as the second argument. This function returns -** the space in bytes required to store the copy of the Expr structure -** and the copies of the Expr.zToken (if applicable) -** string buffers. +** This function returns the space in bytes required to store the copy +** of the Expr structure and a copy of the Expr.u.zToken string (if that +** string is defined.) */ static int dupedExprNodeSize(Expr *p, int flags){ - int nByte = dupedExprStructSize(p, flags); - if( p->zToken ){ - nByte += sqlite3Strlen30(p->zToken)+1; + int nByte = dupedExprStructSize(p, flags) & 0xfff; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nByte += sqlite3Strlen30(p->u.zToken)+1; } return ROUND8(nByte); } @@ -696,7 +740,7 @@ static int dupedExprNodeSize(Expr *p, int flags){ ** mask containing EXPRDUP_XXX flags. ** ** The value returned includes space to create a copy of the Expr struct -** itself and the buffer referred to by Expr.zToken, if any. +** 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 @@ -717,7 +761,7 @@ static int dupedExprSize(Expr *p, int flags){ /* ** 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->zToken +** 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 any. Before returning, *pzBuffer is set to the first byte passed the ** portion of the buffer copied into by this function. @@ -727,12 +771,14 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ if( p ){ const int isReduced = (flags&EXPRDUP_REDUCE); u8 *zAlloc; + u32 staticFlag = 0; assert( pzBuffer==0 || isReduced ); /* Figure out where to write the new Expr structure. */ if( pzBuffer ){ zAlloc = *pzBuffer; + staticFlag = EP_Static; }else{ zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags)); } @@ -742,10 +788,16 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ /* Set nNewSize to the size allocated for the structure pointed to ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed - ** by the copy of the p->zToken string (if any). + ** by the copy of the p->u.zToken string (if any). */ - const int nNewSize = dupedExprStructSize(p, flags); - const int nToken = (p->zToken ? sqlite3Strlen30(p->zToken) + 1 : 0); + const unsigned nStructSize = dupedExprStructSize(p, flags); + const int nNewSize = nStructSize & 0xfff; + int nToken; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nToken = sqlite3Strlen30(p->u.zToken) + 1; + }else{ + nToken = 0; + } if( isReduced ){ assert( ExprHasProperty(p, EP_Reduced)==0 ); memcpy(zAlloc, p, nNewSize); @@ -755,17 +807,15 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize); } - /* Set the EP_Reduced and EP_TokenOnly flags appropriately. */ - pNew->flags &= ~(EP_Reduced|EP_TokenOnly); - switch( nNewSize ){ - case EXPR_REDUCEDSIZE: pNew->flags |= EP_Reduced; break; - case EXPR_TOKENONLYSIZE: pNew->flags |= EP_TokenOnly; break; - } + /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */ + pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static); + pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); + pNew->flags |= staticFlag; - /* Copy the p->zToken string, if any. */ + /* Copy the p->u.zToken string, if any. */ if( nToken ){ - char *zToken = pNew->zToken = (char*)&zAlloc[nNewSize]; - memcpy(zToken, p->zToken, nToken); + char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; + memcpy(zToken, p->u.zToken, nToken); } if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ @@ -1180,12 +1230,13 @@ int sqlite3ExprIsConstantOrFunction(Expr *p){ int sqlite3ExprIsInteger(Expr *p, int *pValue){ int rc = 0; if( p->flags & EP_IntValue ){ - *pValue = p->iTable; + *pValue = p->u.iValue; return 1; } switch( p->op ){ case TK_INTEGER: { - rc = sqlite3GetInt32(p->zToken, pValue); + rc = sqlite3GetInt32(p->u.zToken, pValue); + assert( rc==0 ); break; } case TK_UPLUS: { @@ -1203,9 +1254,11 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){ default: break; } if( rc ){ + assert( ExprHasAnyProperty(p, EP_Reduced|EP_TokenOnly) + || (p->flags2 & EP2_MallocedToken)==0 ); p->op = TK_INTEGER; p->flags |= EP_IntValue; - p->iTable = *pValue; + p->u.iValue = *pValue; } return rc; } @@ -1602,6 +1655,7 @@ void sqlite3CodeSubselect( return; } pExpr->iColumn = dest.iParm; + ExprSetIrreducible(pExpr); break; } } @@ -1662,12 +1716,12 @@ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){ const char *z; if( pExpr->flags & EP_IntValue ){ - int i = pExpr->iTable; + int i = pExpr->u.iValue; if( negFlag ) i = -i; sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); - }else if( (z = pExpr->zToken)!=0 ){ + }else if( (z = pExpr->u.zToken)!=0 ){ int i; - int n = sqlite3Strlen30(pExpr->zToken); + int n = sqlite3Strlen30(pExpr->u.zToken); assert( !sqlite3Isdigit(z[n]) ); if( sqlite3GetInt32(z, &i) ){ if( negFlag ) i = -i; @@ -2078,11 +2132,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ break; } case TK_FLOAT: { - codeReal(v, pExpr->zToken, 0, target); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + codeReal(v, pExpr->u.zToken, 0, target); break; } case TK_STRING: { - sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->zToken, 0); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); break; } case TK_NULL: { @@ -2094,9 +2150,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ int n; const char *z; char *zBlob; - assert( pExpr->zToken[0]=='x' || pExpr->zToken[0]=='X' ); - assert( pExpr->zToken[1]=='\'' ); - z = &pExpr->zToken[2]; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); + assert( pExpr->u.zToken[1]=='\'' ); + z = &pExpr->u.zToken[2]; n = sqlite3Strlen30(z) - 1; assert( z[n]=='\'' ); zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); @@ -2107,9 +2164,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_VARIABLE: { int iPrior; VdbeOp *pOp; - assert( pExpr->zToken!=0 ); - assert( pExpr->zToken[0]!=0 ); - if( pExpr->zToken[1]==0 + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( pExpr->u.zToken!=0 ); + assert( pExpr->u.zToken[0]!=0 ); + if( pExpr->u.zToken[1]==0 && (iPrior = sqlite3VdbeCurrentAddr(v)-1)>=0 && (pOp = sqlite3VdbeGetOp(v, iPrior))->opcode==OP_Variable && pOp->p1+pOp->p3==pExpr->iTable @@ -2124,8 +2182,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ pOp->p3++; }else{ sqlite3VdbeAddOp3(v, OP_Variable, pExpr->iTable, target, 1); - if( pExpr->zToken[1]!=0 ){ - sqlite3VdbeChangeP4(v, -1, pExpr->zToken, 0); + if( pExpr->u.zToken[1]!=0 ){ + sqlite3VdbeChangeP4(v, -1, pExpr->u.zToken, 0); } } break; @@ -2143,7 +2201,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ /* Expressions of the form: CAST(pLeft AS token) */ int aff, to_op; inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - aff = sqlite3AffinityType(pExpr->zToken); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + aff = sqlite3AffinityType(pExpr->u.zToken); to_op = aff - SQLITE_AFF_TEXT + OP_ToText; assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); @@ -2236,7 +2295,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ Expr *pLeft = pExpr->pLeft; assert( pLeft ); if( pLeft->op==TK_FLOAT ){ - codeReal(v, pLeft->zToken, 1, target); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + codeReal(v, pLeft->u.zToken, 1, target); }else if( pLeft->op==TK_INTEGER ){ codeInteger(v, pLeft, 1, target); }else{ @@ -2279,7 +2339,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_AGG_FUNCTION: { AggInfo *pInfo = pExpr->pAggInfo; if( pInfo==0 ){ - sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->zToken); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken); }else{ inReg = pInfo->aFunc[pExpr->iAgg].iMem; } @@ -2306,7 +2367,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ pFarg = pExpr->x.pList; } nFarg = pFarg ? pFarg->nExpr : 0; - zId = pExpr->zToken; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0); assert( pDef!=0 ); @@ -2589,8 +2651,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( pExpr->affinity==OE_Rollback || pExpr->affinity == OE_Abort || pExpr->affinity == OE_Fail ); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->affinity, 0, - pExpr->zToken, 0); + pExpr->u.zToken, 0); } else { assert( pExpr->affinity == OE_Ignore ); sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); @@ -3115,6 +3178,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ if( pA==0||pB==0 ){ return pB==pA; } + assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ return 0; } @@ -3135,9 +3200,13 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ } if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; - if( pA->op!=TK_COLUMN && pA->zToken ){ - if( pB->zToken==0 ) return 0; - if( sqlite3StrICmp(pA->zToken,pB->zToken)!=0 ){ + if( ExprHasProperty(pA, EP_IntValue) ){ + if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ + return 0; + } + }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ + if( ExprHasProperty(pB, EP_IntValue) || pB->u.zToken==0 ) return 0; + if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){ return 0; } } @@ -3204,6 +3273,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ struct SrcList_item *pItem = pSrcList->a; for(i=0; i<pSrcList->nSrc; i++, pItem++){ struct AggInfo_col *pCol; + assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); if( pExpr->iTable==pItem->iCursor ){ /* If we reach this point, it means that pExpr refers to a table ** that is in the FROM clause of the aggregate query. @@ -3252,6 +3322,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ ** Convert the pExpr to be a TK_AGG_COLUMN referring to that ** pAggInfo->aCol[] entry. */ + ExprSetIrreducible(pExpr); pExpr->pAggInfo = pAggInfo; pExpr->op = TK_AGG_COLUMN; pExpr->iAgg = k; @@ -3284,8 +3355,9 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ pItem = &pAggInfo->aFunc[i]; pItem->pExpr = pExpr; pItem->iMem = ++pParse->nMem; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); pItem->pFunc = sqlite3FindFunction(pParse->db, - pExpr->zToken, sqlite3Strlen30(pExpr->zToken), + pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken), pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); if( pExpr->flags & EP_Distinct ){ pItem->iDistinct = pParse->nTab++; @@ -3296,6 +3368,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ + assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + ExprSetIrreducible(pExpr); pExpr->iAgg = i; pExpr->pAggInfo = pAggInfo; return WRC_Prune; diff --git a/src/func.c b/src/func.c index 3792d9efb..893406ceb 100644 --- a/src/func.c +++ b/src/func.c @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.235 2009/05/27 10:31:29 drh Exp $ +** $Id: func.c,v 1.236 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> @@ -1368,7 +1368,8 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ return 0; } assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - pDef = sqlite3FindFunction(db, pExpr->zToken, sqlite3Strlen30(pExpr->zToken), + pDef = sqlite3FindFunction(db, pExpr->u.zToken, + sqlite3Strlen30(pExpr->u.zToken), 2, SQLITE_UTF8, 0); if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){ return 0; diff --git a/src/parse.y b/src/parse.y index 848ebaebc..d30f89f26 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.277 2009/05/27 10:31:29 drh Exp $ +** @(#) $Id: parse.y,v 1.278 2009/05/28 01:00:55 drh Exp $ */ // All token codes are small integers with #defines that begin with "TK_" diff --git a/src/pragma.c b/src/pragma.c index 6fca256d0..ae5ca7508 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.210 2009/05/27 10:31:29 drh Exp $ +** $Id: pragma.c,v 1.211 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" diff --git a/src/resolve.c b/src/resolve.c index b9c7face3..015fe4bf7 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -14,7 +14,7 @@ ** resolve all identifiers by associating them with a particular ** table and column. ** -** $Id: resolve.c,v 1.23 2009/05/27 10:31:29 drh Exp $ +** $Id: resolve.c,v 1.24 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> @@ -72,15 +72,15 @@ static void resolveAlias( } pDup->iTable = pEList->a[iCol].iAlias; }else{ - char *zToken = pOrig->zToken; - pOrig->zToken = 0; + char *zToken = pOrig->u.zToken; + pOrig->u.zToken = 0; pDup = sqlite3ExprDup(db, pOrig, 0); - pOrig->zToken = zToken; + pOrig->u.zToken = zToken; if( pDup==0 ) return; if( zToken ){ assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 ); - pDup->flags2 |= EP2_FreeToken; - pDup->zToken = sqlite3DbStrDup(db, zToken); + pDup->flags2 |= EP2_MallocedToken; + pDup->u.zToken = sqlite3DbStrDup(db, zToken); } } if( pExpr->flags & EP_ExpCollate ){ @@ -138,10 +138,12 @@ static int lookupName( assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ + assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; pExpr->pTab = 0; + ExprSetIrreducible(pExpr); /* Start at the inner-most context and move outward until a match is found */ while( pNC && cnt==0 ){ @@ -439,7 +441,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ /* A lone identifier is the name of a column. */ case TK_ID: { - lookupName(pParse, 0, 0, pExpr->zToken, pNC, pExpr); + lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr); return WRC_Prune; } @@ -456,13 +458,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pRight = pExpr->pRight; if( pRight->op==TK_ID ){ zDb = 0; - zTable = pExpr->pLeft->zToken; - zColumn = pRight->zToken; + zTable = pExpr->pLeft->u.zToken; + zColumn = pRight->u.zToken; }else{ assert( pRight->op==TK_DOT ); - zDb = pExpr->pLeft->zToken; - zTable = pRight->pLeft->zToken; - zColumn = pRight->pRight->zToken; + zDb = pExpr->pLeft->u.zToken; + zTable = pRight->pLeft->u.zToken; + zColumn = pRight->pRight->u.zToken; } lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); return WRC_Prune; @@ -484,7 +486,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ u8 enc = ENC(pParse->db); /* The database encoding */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - zId = pExpr->zToken; + zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ @@ -586,8 +588,8 @@ static int resolveAsName( ){ int i; /* Loop counter */ - if( pE->op==TK_ID || (pE->op==TK_STRING && pE->zToken[0]!='\'') ){ - char *zCol = pE->zToken; + if( pE->op==TK_ID || (pE->op==TK_STRING && pE->u.zToken[0]!='\'') ){ + char *zCol = pE->u.zToken; for(i=0; i<pEList->nExpr; i++){ char *zAs = pEList->a[i].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ @@ -748,7 +750,7 @@ static int resolveCompoundOrderBy( if( pE==0 ) return 1; pE->pColl = pColl; pE->flags |= EP_IntValue | flags; - pE->iTable = iCol; + pE->u.iValue = iCol; pItem->iCol = (u16)iCol; pItem->done = 1; }else{ diff --git a/src/select.c b/src/select.c index 2f91ba9c5..54a42ab29 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.519 2009/05/27 10:31:29 drh Exp $ +** $Id: select.c,v 1.520 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -232,6 +232,8 @@ static void addWhereTerm( pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0); if( pE && isOuterJoin ){ ExprSetProperty(pE, EP_FromJoin); + assert( !ExprHasAnyProperty(pE, EP_TokenOnly|EP_Reduced) ); + ExprSetIrreducible(pE); pE->iRightJoinTable = iRightJoinTable; } *ppExpr = sqlite3ExprAnd(pParse->db,*ppExpr, pE); @@ -266,6 +268,8 @@ static void addWhereTerm( static void setJoinExpr(Expr *p, int iTable){ while( p ){ ExprSetProperty(p, EP_FromJoin); + assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); + ExprSetIrreducible(p); p->iRightJoinTable = iTable; setJoinExpr(p->pLeft, iTable); p = p->pRight; @@ -1127,7 +1131,8 @@ static int selectColumnsFromExprList( /* Get an appropriate name for the column */ p = pEList->a[i].pExpr; - assert( p->pRight==0 || p->pRight->zToken==0 || p->pRight->zToken[0]!=0 ); + assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue) + || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 ); if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS <name>" phrase, use <name> as the name */ zName = sqlite3DbStrDup(db, zName); @@ -1143,7 +1148,8 @@ static int selectColumnsFromExprList( zName = sqlite3MPrintf(db, "%s", iCol>=0 ? pTab->aCol[iCol].zName : "rowid"); }else if( pColExpr->op==TK_ID ){ - zName = sqlite3MPrintf(db, "%s", pColExpr->zToken); + assert( !ExprHasProperty(pColExpr, EP_IntValue) ); + zName = sqlite3MPrintf(db, "%s", pColExpr->u.zToken); }else{ /* Use the original text of the column expression as its name */ zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan); @@ -2048,7 +2054,7 @@ static int multiSelectOrderBy( Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); if( pNew==0 ) return SQLITE_NOMEM; pNew->flags |= EP_IntValue; - pNew->iTable = i; + pNew->u.iValue = i; pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); pOrderBy->a[nOrderBy++].iCol = (u16)i; } @@ -2896,9 +2902,10 @@ static u8 minMaxQuery(Select *p){ pEList = pExpr->x.pList; if( pEList==0 || pEList->nExpr!=1 ) return 0; if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL; - if( sqlite3StrICmp(pExpr->zToken,"min")==0 ){ + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){ return WHERE_ORDERBY_MIN; - }else if( sqlite3StrICmp(pExpr->zToken,"max")==0 ){ + }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){ return WHERE_ORDERBY_MAX; } return WHERE_ORDERBY_NORMAL; @@ -3119,7 +3126,8 @@ static int selectExpander(Walker *pWalker, Select *p){ char *zTName; /* text of name of TABLE */ if( pE->op==TK_DOT ){ assert( pE->pLeft!=0 ); - zTName = pE->pLeft->zToken; + assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); + zTName = pE->pLeft->u.zToken; }else{ zTName = 0; } @@ -4143,8 +4151,8 @@ select_end: ** or from temporary "printf" statements inserted for debugging. */ void sqlite3PrintExpr(Expr *p){ - if( p->zToken ){ - sqlite3DebugPrintf("(%s", p->zToken); + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + sqlite3DebugPrintf("(%s", p->u.zToken); }else{ sqlite3DebugPrintf("(%d", p->op); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3c0a525dd..97de27667 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.876 2009/05/27 10:31:29 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.877 2009/05/28 01:00:55 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1464,7 +1464,7 @@ struct AggInfo { ** help reduce memory requirements, sometimes an Expr object will be ** truncated. And to reduce the number of memory allocations, sometimes ** two or more Expr objects will be stored in a single memory allocation, -** together with Expr.token strings. +** together with Expr.zToken strings. ** ** If the EP_Reduced and EP_TokenOnly flags are set when ** an Expr object is truncated. When EP_Reduced is set, then all @@ -1477,7 +1477,10 @@ struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ u16 flags; /* Various flags. EP_* See below */ - char *zToken; /* Token value. Zero terminated and dequoted */ + union { + char *zToken; /* Token value. Zero terminated and dequoted */ + int iValue; /* Integer value if EP_IntValue */ + } u; /* 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 @@ -1498,8 +1501,7 @@ struct Expr { *********************************************************************/ int iTable; /* TK_COLUMN: cursor number of table holding column - ** TK_REGISTER: register number - ** EP_IntValue: integer value */ + ** TK_REGISTER: register number */ i16 iColumn; /* TK_COLUMN: column index. -1 for rowid */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ @@ -1525,7 +1527,7 @@ struct Expr { #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ #define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */ #define EP_FixedDest 0x0400 /* Result needed in a specific register */ -#define EP_IntValue 0x0800 /* Integer value contained in iTable */ +#define EP_IntValue 0x0800 /* Integer value contained in u.iValue */ #define EP_xIsSelect 0x1000 /* x.pSelect is valid (otherwise x.pList is) */ #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ @@ -1535,7 +1537,20 @@ struct Expr { /* ** The following are the meanings of bits in the Expr.flags2 field. */ -#define EP2_FreeToken 0x0001 /* Need to call sqlite3DbFree() on Expr.zToken */ +#define EP2_MallocedToken 0x0001 /* Need to sqlite3DbFree() Expr.zToken */ +#define EP2_Irreducible 0x0002 /* Cannot EXPRDUP_REDUCE this Expr */ + +/* +** The pseudo-routine sqlite3ExprSetIrreducible sets the EP2_Irreducible +** flag on an expression structure. This flag is used for VV&A only. The +** routine is implemented as a macro that only works when in debugging mode, +** so as not to burden production code. +*/ +#ifdef SQLITE_DEBUG +# define ExprSetIrreducible(X) (X)->flags2 |= EP2_Irreducible +#else +# define ExprSetIrreducible(X) +#endif /* ** These macros can be used to test, set, or clear bits in the diff --git a/src/tokenize.c b/src/tokenize.c index 3e6c98c97..8bfda9bfd 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.157 2009/05/27 10:31:29 drh Exp $ +** $Id: tokenize.c,v 1.158 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> diff --git a/src/trigger.c b/src/trigger.c index 718e46e11..ab94f246a 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -10,7 +10,7 @@ ************************************************************************* ** ** -** $Id: trigger.c,v 1.140 2009/05/27 10:31:29 drh Exp $ +** $Id: trigger.c,v 1.141 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -375,15 +375,15 @@ TriggerStep *sqlite3TriggerInsertStep( pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); if( pTriggerStep ){ - pTriggerStep->pSelect = pSelect; + pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); pTriggerStep->pIdList = pColumn; - pTriggerStep->pExprList = pEList; + pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); pTriggerStep->orconf = orconf; }else{ sqlite3IdListDelete(db, pColumn); - sqlite3ExprListDelete(db, pEList); - sqlite3SelectDelete(db, pSelect); } + sqlite3ExprListDelete(db, pEList); + sqlite3SelectDelete(db, pSelect); return pTriggerStep; } @@ -403,14 +403,13 @@ TriggerStep *sqlite3TriggerUpdateStep( TriggerStep *pTriggerStep; pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName); - if( pTriggerStep==0 ){ - sqlite3ExprListDelete(db, pEList); - sqlite3ExprDelete(db, pWhere); - return 0; - } - pTriggerStep->pExprList = pEList; - pTriggerStep->pWhere = pWhere; - pTriggerStep->orconf = orconf; + if( pTriggerStep ){ + pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); + pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); + pTriggerStep->orconf = orconf; + } + sqlite3ExprListDelete(db, pEList); + sqlite3ExprDelete(db, pWhere); return pTriggerStep; } @@ -427,13 +426,11 @@ TriggerStep *sqlite3TriggerDeleteStep( TriggerStep *pTriggerStep; pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName); - if( pTriggerStep==0 ){ - sqlite3ExprDelete(db, pWhere); - return 0; + if( pTriggerStep ){ + pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); + pTriggerStep->orconf = OE_Default; } - pTriggerStep->pWhere = pWhere; - pTriggerStep->orconf = OE_Default; - + sqlite3ExprDelete(db, pWhere); return pTriggerStep; } @@ -640,7 +637,6 @@ static SrcList *targetSrcList( Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ - Token sDb; /* Dummy database name token */ int iDb; /* Index of the database to use */ SrcList *pSrc; /* SrcList to be returned */ diff --git a/src/update.c b/src/update.c index e72a6354a..6eb92fb61 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.201 2009/05/27 10:31:29 drh Exp $ +** $Id: update.c,v 1.202 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" diff --git a/src/util.c b/src/util.c index 76a8848db..00d13dd0c 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.255 2009/05/27 10:31:29 drh Exp $ +** $Id: util.c,v 1.256 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> diff --git a/src/vdbemem.c b/src/vdbemem.c index 004ea367f..f5120c86b 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -15,7 +15,7 @@ ** only within the VDBE. Interface routines refer to a Mem using the ** name sqlite_value ** -** $Id: vdbemem.c,v 1.145 2009/05/27 10:31:29 drh Exp $ +** $Id: vdbemem.c,v 1.146 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -974,10 +974,15 @@ int sqlite3ValueFromExpr( op = pExpr->op; if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ - zVal = sqlite3DbStrDup(db, pExpr->zToken); pVal = sqlite3ValueNew(db); - if( !zVal || !pVal ) goto no_mem; - sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + if( pVal==0 ) goto no_mem; + if( ExprHasProperty(pExpr, EP_IntValue) ){ + sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue); + }else{ + zVal = sqlite3DbStrDup(db, pExpr->u.zToken); + if( zVal==0 ) goto no_mem; + sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + } if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); }else{ @@ -996,11 +1001,11 @@ int sqlite3ValueFromExpr( #ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ int nVal; - assert( pExpr->zToken[0]=='x' || pExpr->zToken[0]=='X' ); - assert( pExpr->zToken[1]=='\'' ); + assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); + assert( pExpr->u.zToken[1]=='\'' ); pVal = sqlite3ValueNew(db); if( !pVal ) goto no_mem; - zVal = &pExpr->zToken[2]; + zVal = &pExpr->u.zToken[2]; nVal = sqlite3Strlen30(zVal)-1; assert( zVal[nVal]=='\'' ); sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, diff --git a/src/walker.c b/src/walker.c index 7be9e252f..f565bc55f 100644 --- a/src/walker.c +++ b/src/walker.c @@ -12,7 +12,7 @@ ** This file contains routines used for walking the parser tree for ** an SQL statement. ** -** $Id: walker.c,v 1.5 2009/05/27 10:31:29 drh Exp $ +** $Id: walker.c,v 1.6 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> diff --git a/src/where.c b/src/where.c index 7396bf198..48651ceb9 100644 --- a/src/where.c +++ b/src/where.c @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.398 2009/05/27 10:31:29 drh Exp $ +** $Id: where.c,v 1.399 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -658,7 +658,7 @@ static int isLikeOrGlob( (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){ return 0; } - z = pRight->zToken; + z = pRight->u.zToken; cnt = 0; if( z ){ while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ @@ -691,7 +691,7 @@ static int isMatchOfColumn( if( pExpr->op!=TK_FUNCTION ){ return 0; } - if( sqlite3StrICmp(pExpr->zToken,"match")!=0 ){ + if( sqlite3StrICmp(pExpr->u.zToken,"match")!=0 ){ return 0; } pList = pExpr->x.pList; @@ -1161,12 +1161,12 @@ static void exprAnalyze( pLeft = pExpr->x.pList->a[1].pExpr; pRight = pExpr->x.pList->a[0].pExpr; - pStr1 = sqlite3Expr(db, TK_STRING, pRight->zToken); - if( pStr1 ) pStr1->zToken[nPattern] = 0; + pStr1 = sqlite3Expr(db, TK_STRING, pRight->u.zToken); + if( pStr1 ) pStr1->u.zToken[nPattern] = 0; pStr2 = sqlite3ExprDup(db, pStr1, 0); if( !db->mallocFailed ){ u8 c, *pC; - pC = (u8*)&pStr2->zToken[nPattern-1]; + pC = (u8*)&pStr2->u.zToken[nPattern-1]; c = *pC; if( noCase ){ if( c=='@' ) isComplete = 0; |