Index: src/alter.c ================================================================== --- src/alter.c +++ src/alter.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** 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" /* ** The code in this file only exists if we are not omitting the Index: src/attach.c ================================================================== --- src/attach.c +++ src/attach.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** 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" #ifndef SQLITE_OMIT_ATTACH /* @@ -39,11 +39,11 @@ int rc = SQLITE_OK; if( 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{ pExpr->op = TK_STRING; } @@ -310,11 +310,11 @@ goto attach_end; } #ifndef SQLITE_OMIT_AUTHORIZATION if( pAuthArg ){ - char *zAuthArg = pAuthArg->zToken; + char *zAuthArg = pAuthArg->u.zToken; if( zAuthArg==0 ){ goto attach_end; } rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); if(rc!=SQLITE_OK ){ Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -20,11 +20,11 @@ ** creating ID lists ** BEGIN TRANSACTION ** 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" /* ** This routine is called when a new SQL statement is beginning to @@ -1179,18 +1179,16 @@ ){ sqlite3 *db = pParse->db; #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); + } } /* ** Set the collation function of the most recently parsed table column ** to the CollSeq given. Index: src/delete.c ================================================================== --- src/delete.c +++ src/delete.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** 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" /* ** Look up every table that is named in pSrc. If any table is not found, Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** 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" /* ** Return the 'affinity' of the expression pExpr if any. @@ -38,11 +38,12 @@ assert( pExpr->flags&EP_xIsSelect ); return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].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) && pExpr->pTab!=0 ){ @@ -386,38 +387,51 @@ ** If dequote is true, then the token (if it exists) is dequoted. ** If dequote is false, no dequoting is performance. The deQuote ** 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) */ int op, /* Expression opcode */ const Token *pToken, /* Token argument. Might be NULL */ 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 pNew->nHeight = 1; #endif @@ -548,11 +562,12 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ sqlite3 *db = pParse->db; 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 ){ /* Wildcard of the form "?". Assign the next variable number */ assert( z[0]=='?' ); @@ -582,11 +597,11 @@ u32 n; n = sqlite3Strlen30(z); for(i=0; inVarExpr; 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; } } if( i>=pParse->nVarExpr ){ @@ -614,23 +629,17 @@ /* ** Clear an expression structure without deleting the structure itself. ** 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); - } - /* x.pSelect and x.pList are always separately allocated */ + sqlite3ExprDelete(db, p->pLeft); + sqlite3ExprDelete(db, p->pRight); + if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){ + sqlite3DbFree(db, p->u.zToken); + } if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ sqlite3ExprListDelete(db, p->x.pList); } @@ -641,11 +650,13 @@ ** Recursively delete an expression tree. */ void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p==0 ) return; sqlite3ExprClear(db, p); - sqlite3DbFree(db, p); + if( !ExprHasProperty(p, EP_Static) ){ + sqlite3DbFree(db, p); + } } /* ** Return the number of bytes allocated for the expression structure ** passed as the first argument. This is always one of EXPR_FULLSIZE, @@ -656,38 +667,71 @@ if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE; return EXPR_FULLSIZE; } /* -** 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); } /* @@ -694,11 +738,11 @@ ** Return the number of bytes required to create a duplicate of the ** expression passed as the first argument. The second argument is a ** 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 ** and Expr.pRight variables (but not for any structures pointed to or ** descended from the Expr.x.pList or Expr.x.pSelect variables). @@ -715,59 +759,65 @@ } /* ** 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. */ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ Expr *pNew = 0; /* Value to return */ 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)); } pNew = (Expr *)zAlloc; if( pNew ){ /* 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); }else{ int nSize = exprStructSize(p); memcpy(zAlloc, p, nSize); 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; - } - - /* Copy the p->zToken string, if any. */ + /* 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->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) ){ /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ if( ExprHasProperty(p, EP_xIsSelect) ){ @@ -1178,16 +1228,17 @@ ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. */ 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: { rc = sqlite3ExprIsInteger(p->pLeft, pValue); break; @@ -1201,13 +1252,15 @@ break; } 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; } /* @@ -1600,10 +1653,11 @@ pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one); if( sqlite3Select(pParse, pSel, &dest) ){ return; } pExpr->iColumn = dest.iParm; + ExprSetIrreducible(pExpr); break; } } if( testAddr ){ @@ -1660,16 +1714,16 @@ ** like the continuation of the number. */ 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; sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); }else if( sqlite3FitsIn64Bits(z, negFlag) ){ @@ -2076,15 +2130,17 @@ case TK_INTEGER: { codeInteger(v, pExpr, 0, 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: { sqlite3VdbeAddOp2(v, OP_Null, 0, target); break; @@ -2092,13 +2148,14 @@ #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { 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); sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); break; @@ -2105,13 +2162,14 @@ } #endif 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 && pOp->p2+pOp->p3==target && pOp->p4.z==0 @@ -2122,12 +2180,12 @@ ** instruction. */ 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; } case TK_REGISTER: { @@ -2141,11 +2199,12 @@ #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* 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 ); assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); @@ -2234,11 +2293,12 @@ } case TK_UMINUS: { 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{ regFree1 = r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); @@ -2277,11 +2337,12 @@ break; } 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; } break; } @@ -2304,11 +2365,12 @@ pFarg = 0; }else{ 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 ); if( pFarg ){ r1 = sqlite3GetTempRange(pParse, nFarg); @@ -2587,12 +2649,13 @@ } if( pExpr->affinity!=OE_Ignore ){ 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); sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->trigStack->ignoreJump); VdbeComment((v, "raise(IGNORE)")); @@ -3113,10 +3176,12 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ int i; 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; } if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0; if( pA->op!=pB->op ) return 0; @@ -3133,13 +3198,17 @@ }else if( pA->x.pList || pB->x.pList ){ return 0; } 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; } } return 1; } @@ -3202,10 +3271,11 @@ ** clause of the aggregate query */ if( pSrcList ){ struct SrcList_item *pItem = pSrcList->a; for(i=0; inSrc; 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. ** ** Make an entry for the column in pAggInfo->aCol[] if there @@ -3250,10 +3320,11 @@ /* There is now an entry for pExpr in pAggInfo->aCol[] (either ** because it was there before or because we just created it). ** 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; break; } /* endif pExpr->iTable==pItem->iCursor */ @@ -3282,12 +3353,13 @@ if( i>=0 ){ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); 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++; }else{ pItem->iDistinct = -1; @@ -3294,10 +3366,12 @@ } } } /* 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; } } Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -14,11 +14,11 @@ ** ** There is only one exported symbol in this file - the function ** 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 #include #include "vdbeInt.h" @@ -1366,11 +1366,12 @@ || pExpr->x.pList->nExpr!=2 ){ 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; } Index: src/parse.y ================================================================== --- src/parse.y +++ src/parse.y @@ -12,11 +12,11 @@ ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** 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_" %token_prefix TK_ Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** 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" /* Ignore this whole file if pragmas are disabled */ Index: src/resolve.c ================================================================== --- src/resolve.c +++ src/resolve.c @@ -12,11 +12,11 @@ ** ** This file contains routines used for walking the parser tree and ** 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 #include @@ -70,19 +70,19 @@ if( pEList->a[iCol].iAlias==0 ){ pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); } 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 ){ pDup->pColl = pExpr->pColl; pDup->flags |= EP_ExpCollate; @@ -136,14 +136,16 @@ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ 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 ){ ExprList *pEList; SrcList *pSrcList = pNC->pSrcList; @@ -437,11 +439,11 @@ #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */ /* 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; } /* A table name and column name: ID.ID ** Or a database, table and column: ID.ID.ID @@ -454,17 +456,17 @@ /* if( pSrcList==0 ) break; */ 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; } @@ -482,11 +484,11 @@ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ 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 ){ pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); if( pDef==0 ){ @@ -584,12 +586,12 @@ ExprList *pEList, /* List of expressions to scan */ Expr *pE /* Expression we are trying to match */ ){ 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; inExpr; i++){ char *zAs = pEList->a[i].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ return i+1; } @@ -746,11 +748,11 @@ sqlite3ExprDelete(db, pE); pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0); 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{ moreToDo = 1; } Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** 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" /* @@ -230,10 +230,12 @@ pE1c = sqlite3PExpr(pParse, TK_DOT, pE1b, pE1a, 0); pE2c = sqlite3PExpr(pParse, TK_DOT, pE2b, pE2a, 0); 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); } @@ -264,10 +266,12 @@ ** the output, which is incorrect. */ 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; } } @@ -1125,11 +1129,12 @@ if( aCol==0 ) return SQLITE_NOMEM; for(i=0, pCol=aCol; ia[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 " phrase, use as the name */ zName = sqlite3DbStrDup(db, zName); }else{ Expr *pColExpr = p; /* The expression that is the result column name */ @@ -1141,11 +1146,12 @@ pTab = pColExpr->pTab; if( iCol<0 ) iCol = pTab->iPKey; 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); } } @@ -2046,11 +2052,11 @@ } if( j==nOrderBy ){ 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; } } } @@ -2894,13 +2900,14 @@ if( pExpr->op!=TK_AGG_FUNCTION ) return 0; if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0; 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; } @@ -3117,11 +3124,12 @@ ** expanded. */ int tableSeen = 0; /* Set to 1 when TABLE matches */ 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; } for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; @@ -4141,12 +4149,12 @@ ** These routine are not called anywhere from within the normal ** code base. Then are intended to be called from within the debugger ** 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); } if( p->pLeft ){ sqlite3DebugPrintf(" "); Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** 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_ /* @@ -1462,11 +1462,11 @@ ** ** Expr objects can use a lot of memory space in database schema. To ** 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 ** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees ** are contained within the same memory allocation. Note, however, that @@ -1475,11 +1475,14 @@ */ 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 ** access them will result in a segfault or malfunction. *********************************************************************/ @@ -1496,12 +1499,11 @@ ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ 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 */ u16 flags2; /* Second set of flags. EP2_... */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ @@ -1523,21 +1525,34 @@ #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ #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 */ #define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */ #define EP_Static 0x8000 /* Held in memory not obtained from malloc() */ /* ** 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 ** Expr.flags field. */ Index: src/tokenize.c ================================================================== --- src/tokenize.c +++ src/tokenize.c @@ -13,11 +13,11 @@ ** ** This file contains C code that splits an SQL input string up into ** 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 /* Index: src/trigger.c ================================================================== --- src/trigger.c +++ src/trigger.c @@ -8,11 +8,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** -** $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" #ifndef SQLITE_OMIT_TRIGGER /* @@ -373,19 +373,19 @@ assert(pEList == 0 || pSelect == 0); assert(pEList != 0 || pSelect != 0 || db->mallocFailed); 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; } /* @@ -401,18 +401,17 @@ int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ ){ 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; } /* ** Construct a trigger step that implements a DELETE statement and return @@ -425,17 +424,15 @@ Expr *pWhere /* The WHERE clause */ ){ 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; } /* ** Recursively delete a Trigger structure @@ -638,11 +635,10 @@ */ 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 */ pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); if( pSrc ){ Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** 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" #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declaration */ Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -12,11 +12,11 @@ ** Utility functions used throughout sqlite. ** ** 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 #ifdef SQLITE_HAVE_ISNAN # include Index: src/vdbemem.c ================================================================== --- src/vdbemem.c +++ src/vdbemem.c @@ -13,11 +13,11 @@ ** This file contains code use to manipulate "Mem" structure. A "Mem" ** stores a single value in the VDBE. Mem is an opaque structure visible ** 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" /* @@ -972,14 +972,19 @@ return SQLITE_OK; } 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{ sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); } @@ -994,15 +999,15 @@ } } #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, 0, SQLITE_DYNAMIC); } Index: src/walker.c ================================================================== --- src/walker.c +++ src/walker.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** 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 #include Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -14,11 +14,11 @@ ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** 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" /* ** Trace output macros @@ -656,11 +656,11 @@ } if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) && (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] ){ cnt++; } @@ -689,11 +689,11 @@ ExprList *pList; 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; if( pList->nExpr!=2 ){ return 0; @@ -1159,16 +1159,16 @@ Expr *pNewExpr1, *pNewExpr2; int idxNew1, idxNew2; 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; c = sqlite3UpperToLower[c]; } Index: test/attach.test ================================================================== --- test/attach.test +++ test/attach.test @@ -10,11 +10,11 @@ #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: attach.test,v 1.50 2009/05/27 10:31:30 drh Exp $ +# $Id: attach.test,v 1.51 2009/05/28 01:00:56 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl Index: test/select1.test ================================================================== --- test/select1.test +++ test/select1.test @@ -9,11 +9,11 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # -# $Id: select1.test,v 1.69 2009/05/27 10:31:30 drh Exp $ +# $Id: select1.test,v 1.70 2009/05/28 01:00:56 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Try to select on a non-existant table. Index: test/tkt3508.test ================================================================== --- test/tkt3508.test +++ test/tkt3508.test @@ -8,11 +8,11 @@ # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. # -# $Id: tkt3508.test,v 1.4 2009/05/27 10:31:30 drh Exp $ +# $Id: tkt3508.test,v 1.5 2009/05/28 01:00:56 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tkt3508-1.1 {