diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/alter.c | 11 | ||||
-rw-r--r-- | src/attach.c | 35 | ||||
-rw-r--r-- | src/build.c | 51 | ||||
-rw-r--r-- | src/delete.c | 23 | ||||
-rw-r--r-- | src/expr.c | 432 | ||||
-rw-r--r-- | src/func.c | 6 | ||||
-rw-r--r-- | src/parse.y | 469 | ||||
-rw-r--r-- | src/pragma.c | 8 | ||||
-rw-r--r-- | src/resolve.c | 94 | ||||
-rw-r--r-- | src/select.c | 140 | ||||
-rw-r--r-- | src/sqliteInt.h | 84 | ||||
-rw-r--r-- | src/tokenize.c | 8 | ||||
-rw-r--r-- | src/trigger.c | 114 | ||||
-rw-r--r-- | src/update.c | 8 | ||||
-rw-r--r-- | src/util.c | 3 | ||||
-rw-r--r-- | src/vdbemem.c | 15 | ||||
-rw-r--r-- | src/walker.c | 5 | ||||
-rw-r--r-- | src/where.c | 34 |
18 files changed, 772 insertions, 768 deletions
diff --git a/src/alter.c b/src/alter.c index 807bb8daa..0c3e00e51 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.58 2009/05/12 17:46:54 drh Exp $ +** $Id: alter.c,v 1.59 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" @@ -66,7 +66,7 @@ static void renameTableFunc( } /* Store the token that zCsr points to in tname. */ - tname.z = zCsr; + tname.z = (char*)zCsr; tname.n = len; /* Advance zCsr to the next token. Store that token type in 'token', @@ -79,7 +79,7 @@ static void renameTableFunc( assert( len>0 ); } while( token!=TK_LP && token!=TK_USING ); - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql, + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } @@ -125,7 +125,7 @@ static void renameTriggerFunc( } /* Store the token that zCsr points to in tname. */ - tname.z = zCsr; + tname.z = (char*)zCsr; tname.n = len; /* Advance zCsr to the next token. Store that token type in 'token', @@ -155,7 +155,7 @@ static void renameTriggerFunc( /* Variable tname now contains the token that is the old table-name ** in the CREATE TRIGGER statement. */ - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql, + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } @@ -636,6 +636,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ pCol->zColl = 0; pCol->zType = 0; pCol->pDflt = 0; + pCol->zDflt = 0; } pNew->pSchema = db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; diff --git a/src/attach.c b/src/attach.c index c635645d6..2b5ddb589 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.90 2009/05/01 06:19:21 danielk1977 Exp $ +** $Id: attach.c,v 1.91 2009/05/27 10:31:29 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: \"%T\"", &pExpr->span); + sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->zToken); return SQLITE_ERROR; } }else{ @@ -298,21 +298,6 @@ static void codeAttach( sqlite3* db = pParse->db; int regArgs; -#ifndef SQLITE_OMIT_AUTHORIZATION - assert( db->mallocFailed || pAuthArg ); - if( pAuthArg ){ - char *zAuthArg = sqlite3NameFromToken(db, &pAuthArg->span); - if( !zAuthArg ){ - goto attach_end; - } - rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); - sqlite3DbFree(db, zAuthArg); - if(rc!=SQLITE_OK ){ - goto attach_end; - } - } -#endif /* SQLITE_OMIT_AUTHORIZATION */ - memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; @@ -325,6 +310,20 @@ static void codeAttach( goto attach_end; } +#ifndef SQLITE_OMIT_AUTHORIZATION + if( pAuthArg ){ + char *zAuthArg = pAuthArg->zToken; + if( zAuthArg==0 ){ + goto attach_end; + } + rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); + if(rc!=SQLITE_OK ){ + goto attach_end; + } + } +#endif /* SQLITE_OMIT_AUTHORIZATION */ + + v = sqlite3GetVdbe(pParse); regArgs = sqlite3GetTempRange(pParse, 4); sqlite3ExprCode(pParse, pFilename, regArgs); @@ -487,7 +486,7 @@ int sqlite3FixExpr( Expr *pExpr /* The expression to be fixed to one database */ ){ while( pExpr ){ - if( ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanToken) ) break; + if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; }else{ diff --git a/src/build.c b/src/build.c index 9851153eb..66f932e6e 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.544 2009/05/13 22:58:29 drh Exp $ +** $Id: build.c,v 1.545 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" @@ -470,6 +470,7 @@ static void sqliteResetColumnNames(Table *pTable){ for(i=0; i<pTable->nCol; i++, pCol++){ sqlite3DbFree(db, pCol->zName); sqlite3ExprDelete(db, pCol->pDflt); + sqlite3DbFree(db, pCol->zDflt); sqlite3DbFree(db, pCol->zType); sqlite3DbFree(db, pCol->zColl); } @@ -568,7 +569,7 @@ char *sqlite3NameFromToken(sqlite3 *db, Token *pName){ char *zName; if( pName ){ zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n); - if( pName->quoted ) sqlite3Dequote(zName); + sqlite3Dequote(zName); }else{ zName = 0; } @@ -1002,14 +1003,12 @@ void sqlite3AddNotNull(Parse *pParse, int onError){ ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ -char sqlite3AffinityType(const Token *pType){ +char sqlite3AffinityType(const char *zIn){ u32 h = 0; char aff = SQLITE_AFF_NUMERIC; - const unsigned char *zIn = pType->z; - const unsigned char *zEnd = &pType->z[pType->n]; - while( zIn!=zEnd ){ - h = (h<<8) + sqlite3UpperToLower[*zIn]; + if( zIn ) while( zIn[0] ){ + h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff]; zIn++; if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ aff = SQLITE_AFF_TEXT; @@ -1058,7 +1057,7 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){ pCol = &p->aCol[p->nCol-1]; assert( pCol->zType==0 ); pCol->zType = sqlite3NameFromToken(pParse->db, pType); - pCol->affinity = sqlite3AffinityType(pType); + pCol->affinity = sqlite3AffinityType(pCol->zType); } /* @@ -1071,14 +1070,14 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){ ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. */ -void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){ +void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){ Table *p; Column *pCol; sqlite3 *db = pParse->db; p = pParse->pNewTable; if( p!=0 ){ pCol = &(p->aCol[p->nCol-1]); - if( !sqlite3ExprIsConstantOrFunction(pExpr) ){ + if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zName); }else{ @@ -1087,10 +1086,13 @@ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){ ** is required by pragma table_info. */ sqlite3ExprDelete(db, pCol->pDflt); - pCol->pDflt = sqlite3ExprDup(db, pExpr, EXPRDUP_REDUCE|EXPRDUP_SPAN); + pCol->pDflt = sqlite3ExprDup(db, pSpan->pExpr, EXPRDUP_REDUCE); + sqlite3DbFree(db, pCol->zDflt); + pCol->zDflt = sqlite3DbStrNDup(db, (char*)pSpan->zStart, + pSpan->zEnd - pSpan->zStart); } } - sqlite3ExprDelete(db, pExpr); + sqlite3ExprDelete(db, pSpan->pExpr); } /* @@ -1399,14 +1401,8 @@ static char *createTableStmt(sqlite3 *db, Table *p){ zType = azType[pCol->affinity - SQLITE_AFF_TEXT]; len = sqlite3Strlen30(zType); -#ifndef NDEBUG - if( pCol->affinity!=SQLITE_AFF_NONE ){ - Token typeToken; - typeToken.z = (u8*)zType; - typeToken.n = len; - assert( pCol->affinity==sqlite3AffinityType(&typeToken) ); - } -#endif + assert( pCol->affinity==SQLITE_AFF_NONE + || pCol->affinity==sqlite3AffinityType(zType) ); memcpy(&zStmt[k], zType, len); k += len; assert( k<=n ); @@ -1652,7 +1648,7 @@ void sqlite3CreateView( ){ Table *p; int n; - const unsigned char *z; + const char *z; Token sEnd; DbFixer sFix; Token *pName; @@ -1704,7 +1700,7 @@ void sqlite3CreateView( } sEnd.n = 0; n = (int)(sEnd.z - pBegin->z); - z = (const unsigned char*)pBegin->z; + z = pBegin->z; while( ALWAYS(n>0) && sqlite3Isspace(z[n-1]) ){ n--; } sEnd.z = &z[n-1]; sEnd.n = 1; @@ -2508,11 +2504,11 @@ void sqlite3CreateIndex( ** So create a fake list to simulate this. */ if( pList==0 ){ - nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName; + nullId.z = pTab->aCol[pTab->nCol-1].zName; nullId.n = sqlite3Strlen30((char*)nullId.z); - nullId.quoted = 0; - pList = sqlite3ExprListAppend(pParse, 0, 0, &nullId); + pList = sqlite3ExprListAppend(pParse, 0, 0); if( pList==0 ) goto exit_create_index; + sqlite3ExprListSetName(pParse, pList, &nullId, 0); pList->a[0].sortOrder = (u8)sortOrder; } @@ -3081,7 +3077,7 @@ SrcList *sqlite3SrcListEnlarge( /* ** Append a new table name to the given SrcList. Create a new SrcList if -** need be. A new entry is created in the SrcList even if pToken is NULL. +** need be. A new entry is created in the SrcList even if pTable is NULL. ** ** A SrcList is returned, or NULL if there is an OOM error. The returned ** SrcList might be the same as the SrcList that was input or it might be @@ -3109,6 +3105,9 @@ SrcList *sqlite3SrcListEnlarge( ** then so is B. In other words, we never have a case where: ** ** sqlite3SrcListAppend(D,A,0,C); +** +** Both pTable and pDatabase are assumed to be quoted. They are dequoted +** before being added to the SrcList. */ SrcList *sqlite3SrcListAppend( sqlite3 *db, /* Connection to notify of malloc failures */ diff --git a/src/delete.c b/src/delete.c index cf0a36ef0..e5177819c 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.201 2009/05/01 21:13:37 drh Exp $ +** $Id: delete.c,v 1.202 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" @@ -82,13 +82,18 @@ void sqlite3MaterializeView( pDup = sqlite3SelectDup(db, pView->pSelect, 0); if( pWhere ){ SrcList *pFrom; - Token viewName; pWhere = sqlite3ExprDup(db, pWhere, 0); - viewName.z = (u8*)pView->zName; - viewName.n = (unsigned int)sqlite3Strlen30((const char*)viewName.z); - viewName.quoted = 0; - pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0); + pFrom = sqlite3SrcListAppend(db, 0, 0, 0); + if( pFrom ){ + assert( pFrom->nSrc==1 ); + pFrom->a[0].zAlias = sqlite3DbStrDup(db, pView->zName); + pFrom->a[0].pSelect = pDup; + assert( pFrom->a[0].pOn==0 ); + assert( pFrom->a[0].pUsing==0 ); + }else{ + sqlite3SelectDelete(db, pDup); + } pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); } sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); @@ -148,9 +153,9 @@ Expr *sqlite3LimitWhere( ** ); */ - pSelectRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0); + pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); if( pSelectRowid == 0 ) goto limit_where_cleanup_2; - pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0); + pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); if( pEList == 0 ) goto limit_where_cleanup_2; /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree @@ -167,7 +172,7 @@ Expr *sqlite3LimitWhere( if( pSelect == 0 ) return 0; /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ - pWhereRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0); + pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); if( pWhereRowid == 0 ) goto limit_where_cleanup_1; pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0); if( pInClause == 0 ) goto limit_where_cleanup_1; diff --git a/src/expr.c b/src/expr.c index fdbffc584..6fe400d1e 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.436 2009/05/25 11:46:29 drh Exp $ +** $Id: expr.c,v 1.437 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" @@ -40,7 +40,7 @@ char sqlite3ExprAffinity(Expr *pExpr){ } #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ - return sqlite3AffinityType(&pExpr->token); + return sqlite3AffinityType(pExpr->zToken); } #endif if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) @@ -376,70 +376,109 @@ int sqlite3SelectExprHeight(Select *p){ #endif /* SQLITE_MAX_EXPR_DEPTH>0 */ /* +** This routine is the core allocator for Expr nodes. +** ** Construct a new expression node and return a pointer to it. Memory -** for this node is obtained from sqlite3_malloc(). The calling function +** for this node and for the pToken argument is a single allocation +** obtained from sqlite3DbMalloc(). The calling function ** is responsible for making sure the node eventually gets freed. +** +** 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. */ -Expr *sqlite3Expr( +Expr *sqlite3ExprAlloc( sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ int op, /* Expression opcode */ - Expr *pLeft, /* Left operand */ - Expr *pRight, /* Right operand */ - const Token *pToken /* Argument token */ + const Token *pToken, /* Token argument. Might be NULL */ + int dequote /* True to dequote */ ){ Expr *pNew; - pNew = sqlite3DbMallocZero(db, sizeof(Expr)); - if( pNew==0 ){ - /* When malloc fails, delete pLeft and pRight. Expressions passed to - ** this function must always be allocated with sqlite3Expr() for this - ** reason. - */ - sqlite3ExprDelete(db, pLeft); - sqlite3ExprDelete(db, pRight); - return 0; - } - pNew->op = (u8)op; - pNew->pLeft = pLeft; - pNew->pRight = pRight; - pNew->iAgg = -1; - pNew->span.z = (u8*)""; + int nExtra; + if( pToken ){ - int c; - assert( pToken->dyn==0 ); - pNew->span = *pToken; - if( pToken->n>=2 - && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){ - sqlite3TokenCopy(db, &pNew->token, pToken); - if( pNew->token.z ){ - pNew->token.n = sqlite3Dequote((char*)pNew->token.z); - assert( pNew->token.n==(unsigned)sqlite3Strlen30((char*)pNew->token.z)); + nExtra = pToken->n+1; + }else{ + nExtra = 0; + } + 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( c=='"' ) pNew->flags |= EP_DblQuoted; - }else{ - pNew->token = *pToken; } - pNew->token.quoted = 0; - }else if( pLeft ){ +#if SQLITE_MAX_EXPR_DEPTH>0 + pNew->nHeight = 1; +#endif + } + return pNew; +} + +/* +** Allocate a new expression node from a zero-terminated token that has +** already been dequoted. +*/ +Expr *sqlite3Expr( + sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ + int op, /* Expression opcode */ + const char *zToken /* Token argument. Might be NULL */ +){ + Token x; + x.z = zToken; + x.n = zToken ? sqlite3Strlen30(zToken) : 0; + return sqlite3ExprAlloc(db, op, &x, 0); +} + +/* +** Attach subtrees pLeft and pRight to the Expr node pRoot. +** +** If pRoot==NULL that means that a memory allocation error has occurred. +** In that case, delete the subtrees pLeft and pRight. +*/ +void sqlite3ExprAttachSubtrees( + sqlite3 *db, + Expr *pRoot, + Expr *pLeft, + Expr *pRight +){ + if( pRoot==0 ){ + assert( db->mallocFailed ); + sqlite3ExprDelete(db, pLeft); + sqlite3ExprDelete(db, pRight); + }else{ if( pRight ){ - if( pRight->span.dyn==0 && pLeft->span.dyn==0 ){ - sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span); - } + pRoot->pRight = pRight; if( pRight->flags & EP_ExpCollate ){ - pNew->flags |= EP_ExpCollate; - pNew->pColl = pRight->pColl; + pRoot->flags |= EP_ExpCollate; + pRoot->pColl = pRight->pColl; } } - if( pLeft->flags & EP_ExpCollate ){ - pNew->flags |= EP_ExpCollate; - pNew->pColl = pLeft->pColl; + if( pLeft ){ + pRoot->pLeft = pLeft; + if( pLeft->flags & EP_ExpCollate ){ + pRoot->flags |= EP_ExpCollate; + pRoot->pColl = pLeft->pColl; + } } + exprSetHeight(pRoot); } - - exprSetHeight(pNew); - return pNew; } /* +** Allocate a Expr node which joins up to two subtrees. +** +** The ** Works like sqlite3Expr() except that it takes an extra Parse* ** argument and notifies the associated connection object if malloc fails. */ @@ -450,34 +489,8 @@ Expr *sqlite3PExpr( Expr *pRight, /* Right operand */ const Token *pToken /* Argument token */ ){ - Expr *p = sqlite3Expr(pParse->db, op, pLeft, pRight, pToken); - if( p ){ - sqlite3ExprCheckHeight(pParse, p->nHeight); - } - return p; -} - -/* -** When doing a nested parse, you can include terms in an expression -** that look like this: #1 #2 ... These terms refer to registers -** in the virtual machine. #N is the N-th register. -** -** This routine is called by the parser to deal with on of those terms. -** It immediately generates code to store the value in a memory location. -** The returns an expression that will code to extract the value from -** that memory location as needed. -*/ -Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){ - Expr *p; - if( pParse->nested==0 ){ - sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken); - return sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); - } - p = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, pToken); - if( p==0 ){ - return 0; /* Malloc failed */ - } - p->iTable = atoi((char*)&pToken->z[1]); + Expr *p = sqlite3ExprAlloc(pParse->db, op, pToken, 1); + sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); return p; } @@ -491,24 +504,9 @@ Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){ }else if( pRight==0 ){ return pLeft; }else{ - return sqlite3Expr(db, TK_AND, pLeft, pRight, 0); - } -} - -/* -** Set the Expr.span field of the given expression to span all -** text between the two given tokens. Both tokens must be pointing -** at the same string. -*/ -void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ - assert( pRight!=0 ); - assert( pLeft!=0 ); - if( pExpr ){ - pExpr->span.z = pLeft->z; - /* The following assert() may fail when this is called - ** via sqlite3PExpr()/sqlite3Expr() from addWhereTerm(). */ - /* assert(pRight->z >= pLeft->z); */ - pExpr->span.n = pRight->n + (unsigned)(pRight->z - pLeft->z); + Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0); + sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight); + return pNew; } } @@ -520,17 +518,13 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ Expr *pNew; sqlite3 *db = pParse->db; assert( pToken ); - pNew = sqlite3DbMallocZero(db, sizeof(Expr) ); + pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1); if( pNew==0 ){ sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ return 0; } - pNew->op = TK_FUNCTION; pNew->x.pList = pList; assert( !ExprHasProperty(pNew, EP_xIsSelect) ); - assert( pToken->dyn==0 ); - pNew->span = *pToken; - sqlite3TokenCopy(db, &pNew->token, pToken); sqlite3ExprSetHeight(pParse, pNew); return pNew; } @@ -552,22 +546,22 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ ** assigned. */ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ - Token *pToken; sqlite3 *db = pParse->db; + const char *z; if( pExpr==0 ) return; - pToken = &pExpr->token; - assert( pToken->n>=1 ); - assert( pToken->z!=0 ); - assert( pToken->z[0]!=0 ); - if( pToken->n==1 ){ + z = pExpr->zToken; + assert( z!=0 ); + assert( z[0]!=0 ); + if( z[1]==0 ){ /* Wildcard of the form "?". Assign the next variable number */ + assert( z[0]=='?' ); pExpr->iTable = ++pParse->nVar; - }else if( pToken->z[0]=='?' ){ + }else if( z[0]=='?' ){ /* Wildcard of the form "?nnn". Convert "nnn" to an integer and ** use it as the variable number */ int i; - pExpr->iTable = i = atoi((char*)&pToken->z[1]); + pExpr->iTable = i = atoi((char*)&z[1]); testcase( i==0 ); testcase( i==1 ); testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); @@ -586,11 +580,11 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ */ int i; u32 n; - n = pToken->n; + n = sqlite3Strlen30(z); for(i=0; i<pParse->nVarExpr; i++){ Expr *pE = pParse->apVarExpr[i]; assert( pE!=0 ); - if( pE->token.n==n && memcmp(pE->token.z, pToken->z, n)==0 ){ + if( memcmp(pE->zToken, z, n)==0 && pE->zToken[n]==0 ){ pExpr->iTable = pE->iTable; break; } @@ -622,9 +616,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ ** Substructure is deleted. */ void sqlite3ExprClear(sqlite3 *db, Expr *p){ - if( p->token.dyn ) sqlite3DbFree(db, (char*)p->token.z); - if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanToken) ){ - if( p->span.dyn ) sqlite3DbFree(db, (char*)p->span.z); + 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); @@ -633,6 +625,8 @@ void sqlite3ExprClear(sqlite3 *db, Expr *p){ /* 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 */ if( ExprHasProperty(p, EP_xIsSelect) ){ @@ -659,7 +653,6 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){ */ static int exprStructSize(Expr *p){ if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE; - if( ExprHasProperty(p, EP_SpanToken) ) return EXPR_SPANTOKENSIZE; if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE; return EXPR_FULLSIZE; } @@ -676,8 +669,6 @@ static int dupedExprStructSize(Expr *p, int flags){ nSize = EXPR_FULLSIZE; }else if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ nSize = EXPR_REDUCEDSIZE; - }else if( flags&EXPRDUP_SPAN ){ - nSize = EXPR_SPANTOKENSIZE; }else{ nSize = EXPR_TOKENONLYSIZE; } @@ -688,15 +679,13 @@ static int dupedExprStructSize(Expr *p, int flags){ ** 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.token.z and Expr.span.z (if applicable) +** and the copies of the Expr.zToken (if applicable) ** string buffers. */ static int dupedExprNodeSize(Expr *p, int flags){ - int nByte = dupedExprStructSize(p, flags) + (p->token.z ? p->token.n + 1 : 0); - if( (flags&EXPRDUP_SPAN)!=0 - && (p->token.z!=p->span.z || p->token.n!=p->span.n) - ){ - nByte += p->span.n; + int nByte = dupedExprStructSize(p, flags); + if( p->zToken ){ + nByte += sqlite3Strlen30(p->zToken)+1; } return ROUND8(nByte); } @@ -707,9 +696,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.token, if any. If the -** EXPRDUP_SPAN flag is set, then space to create a copy of the buffer -** refered to by Expr.span is also included. +** itself and the buffer referred to by Expr.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 @@ -721,8 +708,7 @@ static int dupedExprSize(Expr *p, int flags){ if( p ){ nByte = dupedExprNodeSize(p, flags); if( flags&EXPRDUP_REDUCE ){ - int f = flags&(~EXPRDUP_SPAN); - nByte += dupedExprSize(p->pLeft, f) + dupedExprSize(p->pRight, f); + nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags); } } return nByte; @@ -731,7 +717,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->token and p->span +** to store the copy of expression p, the copies of p->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. @@ -739,7 +725,6 @@ static int dupedExprSize(Expr *p, int flags){ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ Expr *pNew = 0; /* Value to return */ if( p ){ - const int isRequireSpan = (flags&EXPRDUP_SPAN); const int isReduced = (flags&EXPRDUP_REDUCE); u8 *zAlloc; @@ -757,10 +742,10 @@ 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->token.z string (if any). + ** by the copy of the p->zToken string (if any). */ const int nNewSize = dupedExprStructSize(p, flags); - const int nToken = (p->token.z ? p->token.n + 1 : 0); + const int nToken = (p->zToken ? sqlite3Strlen30(p->zToken) + 1 : 0); if( isReduced ){ assert( ExprHasProperty(p, EP_Reduced)==0 ); memcpy(zAlloc, p, nNewSize); @@ -771,40 +756,19 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ } /* Set the EP_Reduced and EP_TokenOnly flags appropriately. */ - pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_SpanToken); + pNew->flags &= ~(EP_Reduced|EP_TokenOnly); switch( nNewSize ){ case EXPR_REDUCEDSIZE: pNew->flags |= EP_Reduced; break; case EXPR_TOKENONLYSIZE: pNew->flags |= EP_TokenOnly; break; - case EXPR_SPANTOKENSIZE: pNew->flags |= EP_SpanToken; break; } - /* Copy the p->token string, if any. */ + /* Copy the p->zToken string, if any. */ if( nToken ){ - unsigned char *zToken = &zAlloc[nNewSize]; - memcpy(zToken, p->token.z, nToken-1); - zToken[nToken-1] = '\0'; - pNew->token.dyn = 0; - pNew->token.z = zToken; + char *zToken = pNew->zToken = (char*)&zAlloc[nNewSize]; + memcpy(zToken, p->zToken, nToken); } if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ - /* Fill in the pNew->span token, if required. */ - if( isRequireSpan ){ - if( p->token.z!=p->span.z || p->token.n!=p->span.n ){ - pNew->span.z = &zAlloc[nNewSize+nToken]; - memcpy((char *)pNew->span.z, p->span.z, p->span.n); - pNew->span.dyn = 0; - }else{ - pNew->span.z = pNew->token.z; - pNew->span.n = pNew->token.n; - } - }else{ - pNew->span.z = 0; - pNew->span.n = 0; - } - } - - if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_SpanToken)) ){ /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ if( ExprHasProperty(p, EP_xIsSelect) ){ pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced); @@ -814,7 +778,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ } /* Fill in pNew->pLeft and pNew->pRight. */ - if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly|EP_SpanToken) ){ + if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){ zAlloc += dupedExprNodeSize(p, flags); if( ExprHasProperty(pNew, EP_Reduced) ){ pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc); @@ -823,10 +787,14 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ if( pzBuffer ){ *pzBuffer = zAlloc; } - }else if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanToken) ){ - pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); - pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); + }else{ + pNew->flags2 = 0; + if( !ExprHasAnyProperty(p, EP_TokenOnly) ){ + pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); + pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); + } } + } } return pNew; @@ -844,12 +812,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ ** ** Any tables that the SrcList might point to are not duplicated. ** -** The flags parameter contains a combination of the EXPRDUP_XXX flags. If -** the EXPRDUP_SPAN flag is set in the argument parameter, then the -** Expr.span field of the input expression is copied. If EXPRDUP_SPAN is -** clear, then the Expr.span field of the returned expression structure -** is zeroed. -** +** The flags parameter contains a combination of the EXPRDUP_XXX flags. ** If the EXPRDUP_REDUCE flag is set, then the structure returned is a ** truncated version of the usual Expr structure that will be stored as ** part of the in-memory representation of the database schema. @@ -857,17 +820,6 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){ return exprDup(db, p, flags, 0); } -void sqlite3TokenCopy(sqlite3 *db, Token *pTo, const Token *pFrom){ - if( pTo->dyn ) sqlite3DbFree(db, (char*)pTo->z); - if( pFrom->z ){ - pTo->n = pFrom->n; - pTo->z = (u8*)sqlite3DbStrNDup(db, (char*)pFrom->z, pFrom->n); - pTo->dyn = 1; - pTo->quoted = pFrom->quoted; - }else{ - pTo->z = 0; - } -} ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ ExprList *pNew; struct ExprList_item *pItem, *pOldItem; @@ -888,6 +840,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ Expr *pOldExpr = pOldItem->pExpr; pItem->pExpr = pNewExpr = sqlite3ExprDup(db, pOldExpr, flags); pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan); pItem->sortOrder = pOldItem->sortOrder; pItem->done = 0; pItem->iCol = pOldItem->iCol; @@ -962,10 +915,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ if( p==0 ) return 0; pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); if( pNew==0 ) return 0; - /* Always make a copy of the span for top-level expressions in the - ** expression list. The logic in SELECT processing that determines - ** the names of columns in the result set needs this information */ - pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags|EXPRDUP_SPAN); + pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); @@ -995,12 +945,15 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ /* ** Add a new element to the end of an expression list. If pList is ** initially NULL, then create a new expression list. +** +** If a memory allocation error occurs, the entire list is freed and +** NULL is returned. If non-NULL is returned, then it is guaranteed +** that the new entry was successfully appended. */ ExprList *sqlite3ExprListAppend( Parse *pParse, /* Parsing context */ ExprList *pList, /* List to which to append. Might be NULL */ - Expr *pExpr, /* Expression to be appended */ - Token *pName /* AS keyword for the expression */ + Expr *pExpr /* Expression to be appended. Might be NULL */ ){ sqlite3 *db = pParse->db; if( pList==0 ){ @@ -1021,12 +974,10 @@ ExprList *sqlite3ExprListAppend( pList->nAlloc = sqlite3DbMallocSize(db, a)/sizeof(a[0]); } assert( pList->a!=0 ); - if( pExpr || pName ){ + if( 1 ){ struct ExprList_item *pItem = &pList->a[pList->nExpr++]; memset(pItem, 0, sizeof(*pItem)); - pItem->zName = sqlite3NameFromToken(db, pName); pItem->pExpr = pExpr; - pItem->iAlias = 0; } return pList; @@ -1038,6 +989,56 @@ no_mem: } /* +** Set the ExprList.a[].zName element of the most recently added item +** on the expression list. +** +** pList might be NULL following an OOM error. But pName should never be +** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag +** is set. +*/ +void sqlite3ExprListSetName( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to add the span. */ + Token *pName, /* Name to be added */ + int dequote /* True to cause the name to be dequoted */ +){ + assert( pList!=0 || pParse->db->mallocFailed!=0 ); + if( pList ){ + struct ExprList_item *pItem; + assert( pList->nExpr>0 ); + pItem = &pList->a[pList->nExpr-1]; + assert( pItem->zName==0 ); + pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); + if( dequote && pItem->zName ) sqlite3Dequote(pItem->zName); + } +} + +/* +** Set the ExprList.a[].zSpan element of the most recently added item +** on the expression list. +** +** pList might be NULL following an OOM error. But pSpan should never be +** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag +** is set. +*/ +void sqlite3ExprListSetSpan( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to add the span. */ + ExprSpan *pSpan /* The span to be added */ +){ + sqlite3 *db = pParse->db; + assert( pList!=0 || db->mallocFailed!=0 ); + if( pList ){ + struct ExprList_item *pItem = &pList->a[pList->nExpr-1]; + assert( pList->nExpr>0 ); + assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr ); + sqlite3DbFree(db, pItem->zSpan); + pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart, + pSpan->zEnd - pSpan->zStart); + } +} + +/* ** If the expression list pEList contains more than iLimit elements, ** leave an error message in pParse. */ @@ -1066,6 +1067,7 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){ sqlite3ExprDelete(db, pItem->pExpr); sqlite3DbFree(db, pItem->zName); + sqlite3DbFree(db, pItem->zSpan); } sqlite3DbFree(db, pList->a); sqlite3DbFree(db, pList); @@ -1183,7 +1185,7 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){ } switch( p->op ){ case TK_INTEGER: { - rc = sqlite3GetInt32((char*)p->token.z, pValue); + rc = sqlite3GetInt32(p->zToken, pValue); break; } case TK_UPLUS: { @@ -1578,7 +1580,7 @@ void sqlite3CodeSubselect( ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ - static const Token one = { (u8*)"1", 0, 0, 1 }; + static const Token one = { "1", 1 }; Select *pSel; SelectDest dest; @@ -1632,10 +1634,8 @@ static char *dup8bytes(Vdbe *v, const char *in){ ** z[n] character is guaranteed to be something that does not look ** like the continuation of the number. */ -static void codeReal(Vdbe *v, const char *z, int n, int negateFlag, int iMem){ +static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed ); - assert( !z || !sqlite3Isdigit(z[n]) ); - UNUSED_PARAMETER(n); if( z ){ double value; char *zV; @@ -1665,9 +1665,9 @@ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){ int i = pExpr->iTable; if( negFlag ) i = -i; sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); - }else if( (z = (char*)pExpr->token.z)!=0 ){ + }else if( (z = pExpr->zToken)!=0 ){ int i; - int n = pExpr->token.n; + int n = sqlite3Strlen30(pExpr->zToken); assert( !sqlite3Isdigit(z[n]) ); if( sqlite3GetInt32(z, &i) ){ if( negFlag ) i = -i; @@ -1680,7 +1680,7 @@ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){ zV = dup8bytes(v, (char*)&value); sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); }else{ - codeReal(v, z, n, negFlag, iMem); + codeReal(v, z, negFlag, iMem); } } } @@ -2078,12 +2078,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ break; } case TK_FLOAT: { - codeReal(v, (char*)pExpr->token.z, pExpr->token.n, 0, target); + codeReal(v, pExpr->zToken, 0, target); break; } case TK_STRING: { - sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, - (char*)pExpr->token.z, pExpr->token.n); + sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->zToken, 0); break; } case TK_NULL: { @@ -2095,12 +2094,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ int n; const char *z; char *zBlob; - assert( pExpr->token.n>=3 ); - assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' ); - assert( pExpr->token.z[1]=='\'' ); - assert( pExpr->token.z[pExpr->token.n-1]=='\'' ); - n = pExpr->token.n - 3; - z = (char*)pExpr->token.z + 2; + assert( pExpr->zToken[0]=='x' || pExpr->zToken[0]=='X' ); + assert( pExpr->zToken[1]=='\'' ); + z = &pExpr->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; @@ -2109,7 +2107,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_VARIABLE: { int iPrior; VdbeOp *pOp; - if( pExpr->token.n<=1 + assert( pExpr->zToken!=0 ); + assert( pExpr->zToken[0]!=0 ); + if( pExpr->zToken[1]==0 && (iPrior = sqlite3VdbeCurrentAddr(v)-1)>=0 && (pOp = sqlite3VdbeGetOp(v, iPrior))->opcode==OP_Variable && pOp->p1+pOp->p3==pExpr->iTable @@ -2124,8 +2124,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ pOp->p3++; }else{ sqlite3VdbeAddOp3(v, OP_Variable, pExpr->iTable, target, 1); - if( pExpr->token.n>1 ){ - sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n); + if( pExpr->zToken[1]!=0 ){ + sqlite3VdbeChangeP4(v, -1, pExpr->zToken, 0); } } break; @@ -2143,7 +2143,7 @@ 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->token); + aff = sqlite3AffinityType(pExpr->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 +2236,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ Expr *pLeft = pExpr->pLeft; assert( pLeft ); if( pLeft->op==TK_FLOAT ){ - codeReal(v, (char*)pLeft->token.z, pLeft->token.n, 1, target); + codeReal(v, pLeft->zToken, 1, target); }else if( pLeft->op==TK_INTEGER ){ codeInteger(v, pLeft, 1, target); }else{ @@ -2279,8 +2279,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_AGG_FUNCTION: { AggInfo *pInfo = pExpr->pAggInfo; if( pInfo==0 ){ - sqlite3ErrorMsg(pParse, "misuse of aggregate: %T", - &pExpr->span); + sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->zToken); }else{ inReg = pInfo->aFunc[pExpr->iAgg].iMem; } @@ -2301,14 +2300,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); testcase( op==TK_CONST_FUNC ); testcase( op==TK_FUNCTION ); - if( ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanToken) ){ + if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; }else{ pFarg = pExpr->x.pList; } nFarg = pFarg ? pFarg->nExpr : 0; - zId = (char*)pExpr->token.z; - nId = pExpr->token.n; + zId = pExpr->zToken; + nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0); assert( pDef!=0 ); if( pFarg ){ @@ -2591,7 +2590,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ pExpr->affinity == OE_Abort || pExpr->affinity == OE_Fail ); sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->affinity, 0, - (char*)pExpr->token.z, pExpr->token.n); + pExpr->zToken, 0); } else { assert( pExpr->affinity == OE_Ignore ); sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); @@ -3136,10 +3135,9 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ } if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; - if( pA->op!=TK_COLUMN && pA->token.z ){ - if( pB->token.z==0 ) return 0; - if( pB->token.n!=pA->token.n ) return 0; - if( sqlite3StrNICmp((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){ + if( pA->op!=TK_COLUMN && pA->zToken ){ + if( pB->zToken==0 ) return 0; + if( sqlite3StrICmp(pA->zToken,pB->zToken)!=0 ){ return 0; } } @@ -3287,7 +3285,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ pItem->pExpr = pExpr; pItem->iMem = ++pParse->nMem; pItem->pFunc = sqlite3FindFunction(pParse->db, - (char*)pExpr->token.z, pExpr->token.n, + pExpr->zToken, sqlite3Strlen30(pExpr->zToken), pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); if( pExpr->flags & EP_Distinct ){ pItem->iDistinct = pParse->nTab++; diff --git a/src/func.c b/src/func.c index b7df8178f..3792d9efb 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.234 2009/04/20 12:07:37 drh Exp $ +** $Id: func.c,v 1.235 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> @@ -1368,8 +1368,8 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ return 0; } assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2, - SQLITE_UTF8, 0); + pDef = sqlite3FindFunction(db, pExpr->zToken, sqlite3Strlen30(pExpr->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 43124abb4..848ebaebc 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.276 2009/05/11 18:22:31 drh Exp $ +** @(#) $Id: parse.y,v 1.277 2009/05/27 10:31:29 drh Exp $ */ // All token codes are small integers with #defines that begin with "TK_" @@ -166,8 +166,6 @@ columnlist ::= column. column(A) ::= columnid(X) type carglist. { A.z = X.z; A.n = (int)(pParse->sLastToken.z-X.z) + pParse->sLastToken.n; - A.quoted = 0; - A.dyn = 0; } columnid(A) ::= nm(X). { sqlite3AddColumn(pParse,&X); @@ -264,32 +262,35 @@ carglist ::= carglist carg. carglist ::= . carg ::= CONSTRAINT nm ccons. carg ::= ccons. -ccons ::= DEFAULT term(X). {sqlite3AddDefaultValue(pParse,X);} -ccons ::= DEFAULT LP expr(X) RP. {sqlite3AddDefaultValue(pParse,X);} -ccons ::= DEFAULT PLUS term(X). {sqlite3AddDefaultValue(pParse,X);} +ccons ::= DEFAULT term(X). {sqlite3AddDefaultValue(pParse,&X);} +ccons ::= DEFAULT LP expr(X) RP. {sqlite3AddDefaultValue(pParse,&X);} +ccons ::= DEFAULT PLUS term(X). {sqlite3AddDefaultValue(pParse,&X);} ccons ::= DEFAULT MINUS(A) term(X). { - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, X, 0, 0); - sqlite3ExprSpan(p,&A,&X->span); - sqlite3AddDefaultValue(pParse,p); + ExprSpan v; + v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, X.pExpr, 0, 0); + v.zStart = A.z; + v.zEnd = X.zEnd; + sqlite3AddDefaultValue(pParse,&v); } ccons ::= DEFAULT id(X). { - Expr *p = sqlite3PExpr(pParse, TK_STRING, 0, 0, &X); - sqlite3AddDefaultValue(pParse,p); + ExprSpan v; + spanExpr(&v, pParse, TK_STRING, &X); + sqlite3AddDefaultValue(pParse,&v); } // In addition to the type name, we also care about the primary key and // UNIQUE constraints. // ccons ::= NULL onconf. -ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);} +ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);} ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I). - {sqlite3AddPrimaryKey(pParse,0,R,I,Z);} -ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);} -ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X);} + {sqlite3AddPrimaryKey(pParse,0,R,I,Z);} +ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);} +ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X.pExpr);} ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). - {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} -ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);} -ccons ::= COLLATE ids(C). {sqlite3AddCollateType(pParse, &C);} + {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} +ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);} +ccons ::= COLLATE ids(C). {sqlite3AddCollateType(pParse, &C);} // The optional AUTOINCREMENT keyword %type autoinc {int} @@ -332,10 +333,11 @@ conslist ::= conslist tcons. conslist ::= tcons. tcons ::= CONSTRAINT nm. tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R). - {sqlite3AddPrimaryKey(pParse,X,R,I,0);} + {sqlite3AddPrimaryKey(pParse,X,R,I,0);} tcons ::= UNIQUE LP idxlist(X) RP onconf(R). {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);} -tcons ::= CHECK LP expr(E) RP onconf. {sqlite3AddCheckConstraint(pParse,E);} +tcons ::= CHECK LP expr(E) RP onconf. + {sqlite3AddCheckConstraint(pParse,E.pExpr);} tcons ::= FOREIGN KEY LP idxlist(FA) RP REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). { sqlite3CreateForeignKey(pParse, FA, &T, TA, R); @@ -433,17 +435,19 @@ distinct(A) ::= . {A = 0;} sclp(A) ::= selcollist(X) COMMA. {A = X;} sclp(A) ::= . {A = 0;} selcollist(A) ::= sclp(P) expr(X) as(Y). { - A = sqlite3ExprListAppend(pParse,P,X,Y.n?&Y:0); + A = sqlite3ExprListAppend(pParse, P, X.pExpr); + if( Y.n>0 ) sqlite3ExprListSetName(pParse, A, &Y, 1); + sqlite3ExprListSetSpan(pParse,A,&X); } selcollist(A) ::= sclp(P) STAR. { - Expr *p = sqlite3PExpr(pParse, TK_ALL, 0, 0, 0); - A = sqlite3ExprListAppend(pParse, P, p, 0); + Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0); + A = sqlite3ExprListAppend(pParse, P, p); } selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). { Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &Y); Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); - A = sqlite3ExprListAppend(pParse,P, pDot, 0); + A = sqlite3ExprListAppend(pParse,P, pDot); } // An option "AS <id>" phrase that can follow one of the expressions that @@ -530,7 +534,7 @@ joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN. %type on_opt {Expr*} %destructor on_opt {sqlite3ExprDelete(pParse->db, $$);} -on_opt(N) ::= ON expr(E). {N = E;} +on_opt(N) ::= ON expr(E). {N = E.pExpr;} on_opt(N) ::= . {N = 0;} // Note that this block abuses the Token type just a little. If there is @@ -564,14 +568,14 @@ using_opt(U) ::= . {U = 0;} orderby_opt(A) ::= . {A = 0;} orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z). { - A = sqlite3ExprListAppend(pParse,X,Y,0); + A = sqlite3ExprListAppend(pParse,X,Y); if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z; } sortlist(A) ::= sortitem(Y) sortorder(Z). { - A = sqlite3ExprListAppend(pParse,0,Y,0); + A = sqlite3ExprListAppend(pParse,0,Y); if( A && A->a ) A->a[0].sortOrder = (u8)Z; } -sortitem(A) ::= expr(X). {A = X;} +sortitem(A) ::= expr(X). {A = X.pExpr;} %type sortorder {int} @@ -587,7 +591,7 @@ groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;} %type having_opt {Expr*} %destructor having_opt {sqlite3ExprDelete(pParse->db, $$);} having_opt(A) ::= . {A = 0;} -having_opt(A) ::= HAVING expr(X). {A = X;} +having_opt(A) ::= HAVING expr(X). {A = X.pExpr;} %type limit_opt {struct LimitVal} @@ -602,12 +606,12 @@ having_opt(A) ::= HAVING expr(X). {A = X;} // sqlite3ExprDelete(pParse->db, $$.pLimit); // sqlite3ExprDelete(pParse->db, $$.pOffset); //} -limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;} -limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X; A.pOffset = 0;} +limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;} +limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X.pExpr; A.pOffset = 0;} limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). - {A.pLimit = X; A.pOffset = Y;} + {A.pLimit = X.pExpr; A.pOffset = Y.pExpr;} limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). - {A.pOffset = X; A.pLimit = Y;} + {A.pOffset = X.pExpr; A.pLimit = Y.pExpr;} /////////////////////////// The DELETE statement ///////////////////////////// // @@ -630,7 +634,7 @@ cmd ::= DELETE FROM fullname(X) indexed_opt(I) where_opt(W). { %destructor where_opt {sqlite3ExprDelete(pParse->db, $$);} where_opt(A) ::= . {A = 0;} -where_opt(A) ::= WHERE expr(X). {A = X;} +where_opt(A) ::= WHERE expr(X). {A = X.pExpr;} ////////////////////////// The UPDATE command //////////////////////////////// // @@ -653,10 +657,14 @@ cmd ::= UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(W). %type setlist {ExprList*} %destructor setlist {sqlite3ExprListDelete(pParse->db, $$);} -setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). - {A = sqlite3ExprListAppend(pParse,Z,Y,&X);} -setlist(A) ::= nm(X) EQ expr(Y). - {A = sqlite3ExprListAppend(pParse,0,Y,&X);} +setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). { + A = sqlite3ExprListAppend(pParse, Z, Y.pExpr); + sqlite3ExprListSetName(pParse, A, &X, 1); +} +setlist(A) ::= nm(X) EQ expr(Y). { + A = sqlite3ExprListAppend(pParse, 0, Y.pExpr); + sqlite3ExprListSetName(pParse, A, &X, 1); +} ////////////////////////// The INSERT command ///////////////////////////////// // @@ -677,9 +685,9 @@ insert_cmd(A) ::= REPLACE. {A = OE_Replace;} %destructor itemlist {sqlite3ExprListDelete(pParse->db, $$);} itemlist(A) ::= itemlist(X) COMMA expr(Y). - {A = sqlite3ExprListAppend(pParse,X,Y,0);} + {A = sqlite3ExprListAppend(pParse,X,Y.pExpr);} itemlist(A) ::= expr(X). - {A = sqlite3ExprListAppend(pParse,0,X,0);} + {A = sqlite3ExprListAppend(pParse,0,X.pExpr);} %type inscollist_opt {IdList*} %destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);} @@ -696,240 +704,319 @@ inscollist(A) ::= nm(Y). /////////////////////////// Expression Processing ///////////////////////////// // -%type expr {Expr*} -%destructor expr {sqlite3ExprDelete(pParse->db, $$);} -%type term {Expr*} -%destructor term {sqlite3ExprDelete(pParse->db, $$);} +%type expr {ExprSpan} +%destructor expr {sqlite3ExprDelete(pParse->db, $$.pExpr);} +%type term {ExprSpan} +%destructor term {sqlite3ExprDelete(pParse->db, $$.pExpr);} + +%include { + /* This is a utility routine used to set the ExprSpan.zStart and + ** ExprSpan.zEnd values of pOut so that the span covers the complete + ** range of text beginning with pStart and going to the end of pEnd. + */ + static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){ + pOut->zStart = pStart->z; + pOut->zEnd = &pEnd->z[pEnd->n]; + } + + /* Construct a new Expr object from a single identifier. Use the + ** new Expr to populate pOut. Set the span of pOut to be the identifier + ** that created the expression. + */ + static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token *pValue){ + pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, pValue); + pOut->zStart = pValue->z; + pOut->zEnd = &pValue->z[pValue->n]; + } +} expr(A) ::= term(X). {A = X;} -expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); } -term(A) ::= NULL(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} -expr(A) ::= id(X). {A = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);} -expr(A) ::= JOIN_KW(X). {A = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);} +expr(A) ::= LP(B) expr(X) RP(E). {A.pExpr = X.pExpr; spanSet(&A,&B,&E);} +term(A) ::= NULL(X). {spanExpr(&A, pParse, @X, &X);} +expr(A) ::= id(X). {spanExpr(&A, pParse, TK_ID, &X);} +expr(A) ::= JOIN_KW(X). {spanExpr(&A, pParse, TK_ID, &X);} expr(A) ::= nm(X) DOT nm(Y). { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y); - A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); + A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); + spanSet(&A,&X,&Y); } expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y); Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Z); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); - A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); + A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); + spanSet(&A,&X,&Z); +} +term(A) ::= INTEGER|FLOAT|BLOB(X). {spanExpr(&A, pParse, @X, &X);} +term(A) ::= STRING(X). {spanExpr(&A, pParse, @X, &X);} +expr(A) ::= REGISTER(X). { + /* When doing a nested parse, one can include terms in an expression + ** that look like this: #1 #2 ... These terms refer to registers + ** in the virtual machine. #N is the N-th register. */ + if( pParse->nested==0 ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &X); + A.pExpr = 0; + }else{ + A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &X); + if( A.pExpr ) sqlite3GetInt32(&X.z[1], &A.pExpr->iTable); + } + spanSet(&A, &X, &X); } -term(A) ::= INTEGER|FLOAT|BLOB(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} -term(A) ::= STRING(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} -expr(A) ::= REGISTER(X). {A = sqlite3RegisterExpr(pParse, &X);} expr(A) ::= VARIABLE(X). { - Token *pToken = &X; - Expr *pExpr = A = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken); - sqlite3ExprAssignVarNumber(pParse, pExpr); + spanExpr(&A, pParse, TK_VARIABLE, &X); + sqlite3ExprAssignVarNumber(pParse, A.pExpr); + spanSet(&A, &X, &X); } expr(A) ::= expr(E) COLLATE ids(C). { - A = sqlite3ExprSetColl(pParse, E, &C); + A.pExpr = sqlite3ExprSetColl(pParse, E.pExpr, &C); + A.zStart = E.zStart; + A.zEnd = &C.z[C.n]; } %ifndef SQLITE_OMIT_CAST expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). { - A = sqlite3PExpr(pParse, TK_CAST, E, 0, &T); - sqlite3ExprSpan(A,&X,&Y); + A.pExpr = sqlite3PExpr(pParse, TK_CAST, E.pExpr, 0, &T); + spanSet(&A,&X,&Y); } %endif SQLITE_OMIT_CAST expr(A) ::= ID(X) LP distinct(D) exprlist(Y) RP(E). { if( Y && Y->nExpr>SQLITE_MAX_FUNCTION_ARG ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X); } - A = sqlite3ExprFunction(pParse, Y, &X); - sqlite3ExprSpan(A,&X,&E); - if( D && A ){ - A->flags |= EP_Distinct; + A.pExpr = sqlite3ExprFunction(pParse, Y, &X); + spanSet(&A,&X,&E); + if( D && A.pExpr ){ + A.pExpr->flags |= EP_Distinct; } } expr(A) ::= ID(X) LP STAR RP(E). { - A = sqlite3ExprFunction(pParse, 0, &X); - sqlite3ExprSpan(A,&X,&E); + A.pExpr = sqlite3ExprFunction(pParse, 0, &X); + spanSet(&A,&X,&E); } term(A) ::= CTIME_KW(OP). { /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are ** treated as functions that return constants */ - A = sqlite3ExprFunction(pParse, 0,&OP); - if( A ){ - A->op = TK_CONST_FUNC; - A->span = OP; + A.pExpr = sqlite3ExprFunction(pParse, 0,&OP); + if( A.pExpr ){ + A.pExpr->op = TK_CONST_FUNC; + } + spanSet(&A, &OP, &OP); +} + +%include { + /* This routine constructs a binary expression node out of two ExprSpan + ** objects and uses the result to populate a new ExprSpan object. + */ + static void spanBinaryExpr( + ExprSpan *pOut, /* Write the result here */ + Parse *pParse, /* The parsing context. Errors accumulate here */ + int op, /* The binary operation */ + ExprSpan *pLeft, /* The left operand */ + ExprSpan *pRight /* The right operand */ + ){ + pOut->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0); + pOut->zStart = pLeft->zStart; + pOut->zEnd = pRight->zEnd; } } -expr(A) ::= expr(X) AND(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} -expr(A) ::= expr(X) OR(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} + +expr(A) ::= expr(X) AND(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} +expr(A) ::= expr(X) OR(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y). - {A = sqlite3PExpr(pParse,@OP,X,Y,0);} -expr(A) ::= expr(X) EQ|NE(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} + {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} +expr(A) ::= expr(X) EQ|NE(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y). - {A = sqlite3PExpr(pParse,@OP,X,Y,0);} -expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y).{A = sqlite3PExpr(pParse,@OP,X,Y,0);} + {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} +expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y). + {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y). - {A = sqlite3PExpr(pParse,@OP,X,Y,0);} -expr(A) ::= expr(X) CONCAT(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} + {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} +expr(A) ::= expr(X) CONCAT(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} %type likeop {struct LikeOp} likeop(A) ::= LIKE_KW(X). {A.eOperator = X; A.not = 0;} likeop(A) ::= NOT LIKE_KW(X). {A.eOperator = X; A.not = 1;} likeop(A) ::= MATCH(X). {A.eOperator = X; A.not = 0;} likeop(A) ::= NOT MATCH(X). {A.eOperator = X; A.not = 1;} -%type escape {Expr*} -%destructor escape {sqlite3ExprDelete(pParse->db, $$);} +%type escape {ExprSpan} +%destructor escape {sqlite3ExprDelete(pParse->db, $$.pExpr);} escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;} -escape(X) ::= . [ESCAPE] {X = 0;} +escape(X) ::= . [ESCAPE] {memset(&X,0,sizeof(X));} expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, Y, 0); - pList = sqlite3ExprListAppend(pParse,pList, X, 0); - if( E ){ - pList = sqlite3ExprListAppend(pParse,pList, E, 0); + pList = sqlite3ExprListAppend(pParse,0, Y.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, X.pExpr); + if( E.pExpr ){ + pList = sqlite3ExprListAppend(pParse,pList, E.pExpr); } - A = sqlite3ExprFunction(pParse, pList, &OP.eOperator); - if( OP.not ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); - sqlite3ExprSpan(A, &X->span, &Y->span); - if( A ) A->flags |= EP_InfixFunc; + A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator); + if( OP.not ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0); + A.zStart = X.zStart; + A.zEnd = Y.zEnd; + if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc; } -expr(A) ::= expr(X) ISNULL|NOTNULL(E). { - A = sqlite3PExpr(pParse, @E, X, 0, 0); - sqlite3ExprSpan(A,&X->span,&E); -} -expr(A) ::= expr(X) IS NULL(E). { - A = sqlite3PExpr(pParse, TK_ISNULL, X, 0, 0); - sqlite3ExprSpan(A,&X->span,&E); -} -expr(A) ::= expr(X) NOT NULL(E). { - A = sqlite3PExpr(pParse, TK_NOTNULL, X, 0, 0); - sqlite3ExprSpan(A,&X->span,&E); -} -expr(A) ::= expr(X) IS NOT NULL(E). { - A = sqlite3PExpr(pParse, TK_NOTNULL, X, 0, 0); - sqlite3ExprSpan(A,&X->span,&E); -} -expr(A) ::= NOT(B) expr(X). { - A = sqlite3PExpr(pParse, @B, X, 0, 0); - sqlite3ExprSpan(A,&B,&X->span); -} -expr(A) ::= BITNOT(B) expr(X). { - A = sqlite3PExpr(pParse, @B, X, 0, 0); - sqlite3ExprSpan(A,&B,&X->span); -} -expr(A) ::= MINUS(B) expr(X). [UMINUS] { - A = sqlite3PExpr(pParse, TK_UMINUS, X, 0, 0); - sqlite3ExprSpan(A,&B,&X->span); -} -expr(A) ::= PLUS(B) expr(X). [UPLUS] { - A = sqlite3PExpr(pParse, TK_UPLUS, X, 0, 0); - sqlite3ExprSpan(A,&B,&X->span); +%include { + /* Construct an expression node for a unary postfix operator + */ + static void spanUnaryPostfix( + ExprSpan *pOut, /* Write the new expression node here */ + Parse *pParse, /* Parsing context to record errors */ + int op, /* The operator */ + ExprSpan *pOperand, /* The operand */ + Token *pPostOp /* The operand token for setting the span */ + ){ + pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); + pOut->zStart = pOperand->zStart; + pOut->zEnd = &pPostOp->z[pPostOp->n]; + } +} + +expr(A) ::= expr(X) ISNULL|NOTNULL(E). {spanUnaryPostfix(&A,pParse,@E,&X,&E);} +expr(A) ::= expr(X) IS NULL(E). {spanUnaryPostfix(&A,pParse,TK_ISNULL,&X,&E);} +expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);} +expr(A) ::= expr(X) IS NOT NULL(E). + {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);} + +%include { + /* Construct an expression node for a unary prefix operator + */ + static void spanUnaryPrefix( + ExprSpan *pOut, /* Write the new expression node here */ + Parse *pParse, /* Parsing context to record errors */ + int op, /* The operator */ + ExprSpan *pOperand, /* The operand */ + Token *pPreOp /* The operand token for setting the span */ + ){ + pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); + pOut->zStart = pPreOp->z; + pOut->zEnd = pOperand->zEnd; + } } + + + +expr(A) ::= NOT(B) expr(X). {spanUnaryPrefix(&A,pParse,@B,&X,&B);} +expr(A) ::= BITNOT(B) expr(X). {spanUnaryPrefix(&A,pParse,@B,&X,&B);} +expr(A) ::= MINUS(B) expr(X). [UMINUS] + {spanUnaryPrefix(&A,pParse,TK_UMINUS,&X,&B);} +expr(A) ::= PLUS(B) expr(X). [UPLUS] + {spanUnaryPrefix(&A,pParse,TK_UPLUS,&X,&B);} + %type between_op {int} between_op(A) ::= BETWEEN. {A = 0;} between_op(A) ::= NOT BETWEEN. {A = 1;} expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { - ExprList *pList = sqlite3ExprListAppend(pParse,0, X, 0); - pList = sqlite3ExprListAppend(pParse,pList, Y, 0); - A = sqlite3PExpr(pParse, TK_BETWEEN, W, 0, 0); - if( A ){ - A->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, X.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, Y.pExpr); + A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, W.pExpr, 0, 0); + if( A.pExpr ){ + A.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); - sqlite3ExprSpan(A,&W->span,&Y->span); + if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0); + A.zStart = W.zStart; + A.zEnd = Y.zEnd; } %ifndef SQLITE_OMIT_SUBQUERY %type in_op {int} in_op(A) ::= IN. {A = 0;} in_op(A) ::= NOT IN. {A = 1;} expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] { - A = sqlite3PExpr(pParse, TK_IN, X, 0, 0); - if( A ){ - A->x.pList = Y; - sqlite3ExprSetHeight(pParse, A); + A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); + if( A.pExpr ){ + A.pExpr->x.pList = Y; + sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); } - if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); - sqlite3ExprSpan(A,&X->span,&E); + if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0); + A.zStart = X.zStart; + A.zEnd = &E.z[E.n]; } expr(A) ::= LP(B) select(X) RP(E). { - A = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); - if( A ){ - A->x.pSelect = X; - ExprSetProperty(A, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, A); + A.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); + if( A.pExpr ){ + A.pExpr->x.pSelect = X; + ExprSetProperty(A.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, X); } - sqlite3ExprSpan(A,&B,&E); + A.zStart = B.z; + A.zEnd = &E.z[E.n]; } expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] { - A = sqlite3PExpr(pParse, TK_IN, X, 0, 0); - if( A ){ - A->x.pSelect = Y; - ExprSetProperty(A, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, A); + A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); + if( A.pExpr ){ + A.pExpr->x.pSelect = Y; + ExprSetProperty(A.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, Y); } - if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); - sqlite3ExprSpan(A,&X->span,&E); + if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0); + A.zStart = X.zStart; + A.zEnd = &E.z[E.n]; } expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z); - A = sqlite3PExpr(pParse, TK_IN, X, 0, 0); - if( A ){ - A->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - ExprSetProperty(A, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, A); + A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); + if( A.pExpr ){ + A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); + ExprSetProperty(A.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } - if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); - sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y); + if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0); + A.zStart = X.zStart; + A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n]; } expr(A) ::= EXISTS(B) LP select(Y) RP(E). { - Expr *p = A = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); + Expr *p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ p->x.pSelect = Y; - ExprSetProperty(A, EP_xIsSelect); - sqlite3ExprSpan(p,&B,&E); - sqlite3ExprSetHeight(pParse, A); + ExprSetProperty(p, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, p); }else{ sqlite3SelectDelete(pParse->db, Y); } + A.zStart = B.z; + A.zEnd = &E.z[E.n]; } %endif SQLITE_OMIT_SUBQUERY /* CASE expressions */ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { - A = sqlite3PExpr(pParse, TK_CASE, X, Z, 0); - if( A ){ - A->x.pList = Y; - sqlite3ExprSetHeight(pParse, A); + A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, Z, 0); + if( A.pExpr ){ + A.pExpr->x.pList = Y; + sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); } - sqlite3ExprSpan(A, &C, &E); + A.zStart = C.z; + A.zEnd = &E.z[E.n]; } %type case_exprlist {ExprList*} %destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);} case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). { - A = sqlite3ExprListAppend(pParse,X, Y, 0); - A = sqlite3ExprListAppend(pParse,A, Z, 0); + A = sqlite3ExprListAppend(pParse,X, Y.pExpr); + A = sqlite3ExprListAppend(pParse,A, Z.pExpr); } case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). { - A = sqlite3ExprListAppend(pParse,0, Y, 0); - A = sqlite3ExprListAppend(pParse,A, Z, 0); + A = sqlite3ExprListAppend(pParse,0, Y.pExpr); + A = sqlite3ExprListAppend(pParse,A, Z.pExpr); } %type case_else {Expr*} %destructor case_else {sqlite3ExprDelete(pParse->db, $$);} -case_else(A) ::= ELSE expr(X). {A = X;} +case_else(A) ::= ELSE expr(X). {A = X.pExpr;} case_else(A) ::= . {A = 0;} %type case_operand {Expr*} %destructor case_operand {sqlite3ExprDelete(pParse->db, $$);} -case_operand(A) ::= expr(X). {A = X;} +case_operand(A) ::= expr(X). {A = X.pExpr;} case_operand(A) ::= . {A = 0;} %type exprlist {ExprList*} @@ -940,9 +1027,9 @@ case_operand(A) ::= . {A = 0;} exprlist(A) ::= nexprlist(X). {A = X;} exprlist(A) ::= . {A = 0;} nexprlist(A) ::= nexprlist(X) COMMA expr(Y). - {A = sqlite3ExprListAppend(pParse,X,Y,0);} + {A = sqlite3ExprListAppend(pParse,X,Y.pExpr);} nexprlist(A) ::= expr(Y). - {A = sqlite3ExprListAppend(pParse,0,Y,0);} + {A = sqlite3ExprListAppend(pParse,0,Y.pExpr);} ///////////////////////////// The CREATE INDEX command /////////////////////// @@ -968,10 +1055,11 @@ idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). { Expr *p = 0; if( C.n>0 ){ - p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); + p = sqlite3Expr(pParse->db, TK_COLUMN, 0); sqlite3ExprSetColl(pParse, p, &C); } - A = sqlite3ExprListAppend(pParse,X, p, &Y); + A = sqlite3ExprListAppend(pParse,X, p); + sqlite3ExprListSetName(pParse,A,&Y,1); sqlite3ExprListCheckLength(pParse, A, "index"); if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z; } @@ -981,13 +1069,14 @@ idxlist(A) ::= nm(Y) collate(C) sortorder(Z). { p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); sqlite3ExprSetColl(pParse, p, &C); } - A = sqlite3ExprListAppend(pParse,0, p, &Y); + A = sqlite3ExprListAppend(pParse,0, p); + sqlite3ExprListSetName(pParse, A, &Y, 1); sqlite3ExprListCheckLength(pParse, A, "index"); if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z; } %type collate {Token} -collate(C) ::= . {C.z = 0; C.n = 0;} +collate(C) ::= . {C.z = 0; C.n = 0;} collate(C) ::= COLLATE ids(X). {C = X;} @@ -1065,25 +1154,17 @@ foreach_clause ::= FOR EACH ROW. %type when_clause {Expr*} %destructor when_clause {sqlite3ExprDelete(pParse->db, $$);} when_clause(A) ::= . { A = 0; } -when_clause(A) ::= WHEN expr(X). { A = X; } +when_clause(A) ::= WHEN expr(X). { A = X.pExpr; } %type trigger_cmd_list {TriggerStep*} %destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);} trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. { -/* - if( Y ){ - Y->pLast->pNext = X; - }else{ - Y = X; - } -*/ assert( Y!=0 ); Y->pLast->pNext = X; Y->pLast = X; A = Y; } trigger_cmd_list(A) ::= trigger_cmd(X) SEMI. { - /* if( X ) */ assert( X!=0 ); X->pLast = X; A = X; @@ -1112,18 +1193,20 @@ trigger_cmd(A) ::= select(X). {A = sqlite3TriggerSelectStep(pParse->db, X); } // The special RAISE expression that may occur in trigger programs expr(A) ::= RAISE(X) LP IGNORE RP(Y). { - A = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); - if( A ){ - A->affinity = OE_Ignore; - sqlite3ExprSpan(A, &X, &Y); + A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); + if( A.pExpr ){ + A.pExpr->affinity = OE_Ignore; } + A.zStart = X.z; + A.zEnd = &Y.z[Y.n]; } expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). { - A = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &Z); - if( A ) { - A->affinity = (char)T; - sqlite3ExprSpan(A, &X, &Y); + A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &Z); + if( A.pExpr ) { + A.pExpr->affinity = (char)T; } + A.zStart = X.z; + A.zEnd = &Y.z[Y.n]; } %endif !SQLITE_OMIT_TRIGGER @@ -1143,16 +1226,16 @@ cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). { //////////////////////// ATTACH DATABASE file AS name ///////////////////////// %ifndef SQLITE_OMIT_ATTACH cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). { - sqlite3Attach(pParse, F, D, K); + sqlite3Attach(pParse, F.pExpr, D.pExpr, K); } cmd ::= DETACH database_kw_opt expr(D). { - sqlite3Detach(pParse, D); + sqlite3Detach(pParse, D.pExpr); } %type key_opt {Expr*} %destructor key_opt {sqlite3ExprDelete(pParse->db, $$);} key_opt(A) ::= . { A = 0; } -key_opt(A) ::= KEY expr(X). { A = X; } +key_opt(A) ::= KEY expr(X). { A = X.pExpr; } database_kw_opt ::= DATABASE. database_kw_opt ::= . diff --git a/src/pragma.c b/src/pragma.c index f3761b1d0..6fca256d0 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.209 2009/04/07 22:05:43 drh Exp $ +** $Id: pragma.c,v 1.210 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" @@ -840,10 +840,8 @@ void sqlite3Pragma( sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pCol->zType ? pCol->zType : "", 0); sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); - if( pCol->pDflt ){ - const Token *p = &pCol->pDflt->span; - assert( p->z ); - sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)p->z, p->n); + if( pCol->zDflt ){ + sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, 5); } diff --git a/src/resolve.c b/src/resolve.c index 4d34317e0..b9c7face3 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.22 2009/05/05 15:46:43 drh Exp $ +** $Id: resolve.c,v 1.23 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> @@ -63,16 +63,25 @@ static void resolveAlias( assert( pOrig!=0 ); assert( pOrig->flags & EP_Resolved ); db = pParse->db; - pDup = sqlite3ExprDup(db, pOrig, 0); - if( pDup==0 ) return; - sqlite3TokenCopy(db, &pDup->token, &pOrig->token); - if( pDup->op!=TK_COLUMN && zType[0]!='G' ){ + if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ + pDup = sqlite3ExprDup(db, pOrig, 0); pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); if( pDup==0 ) return; 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; + pDup = sqlite3ExprDup(db, pOrig, 0); + pOrig->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); + } } if( pExpr->flags & EP_ExpCollate ){ pDup->pColl = pExpr->pColl; @@ -100,10 +109,10 @@ static void resolveAlias( ** pExpr->pLeft Any expression this points to is deleted ** pExpr->pRight Any expression this points to is deleted. ** -** The pDbToken is the name of the database (the "X"). This value may be +** The zDb variable is the name of the database (the "X"). This value may be ** NULL meaning that name is of the form Y.Z or Z. Any available database -** can be used. The pTableToken is the name of the table (the "Y"). This -** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it +** can be used. The zTable variable is the name of the table (the "Y"). This +** value can be NULL if zDb is also NULL. If zTable is NULL it ** means that the form of the name is Z and that columns from any table ** can be used. ** @@ -112,15 +121,12 @@ static void resolveAlias( */ static int lookupName( Parse *pParse, /* The parsing context */ - Token *pDbToken, /* Name of the database containing table, or NULL */ - Token *pTableToken, /* Name of table containing column, or NULL */ - Token *pColumnToken, /* Name of the column. */ + const char *zDb, /* Name of the database containing table, or NULL */ + const char *zTab, /* Name of table containing column, or NULL */ + const char *zCol, /* Name of the column. */ NameContext *pNC, /* The name context used to resolve the name */ Expr *pExpr /* Make this EXPR node point to the selected column */ ){ - char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */ - char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */ - char *zCol = 0; /* Name of the column. The "Z" */ int i, j; /* Loop counters */ int cnt = 0; /* Number of matching column names */ int cntTab = 0; /* Number of matching table names */ @@ -130,16 +136,8 @@ static int lookupName( NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ - assert( pNC ); /* the name context cannot be NULL. */ - assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ - - /* Dequote and zero-terminate the names */ - zDb = sqlite3NameFromToken(db, pDbToken); - zTab = sqlite3NameFromToken(db, pTableToken); - zCol = sqlite3NameFromToken(db, pColumnToken); - if( db->mallocFailed ){ - goto lookupname_end; - } + assert( pNC ); /* the name context cannot be NULL. */ + assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ /* Initialize the node to no-match */ pExpr->iTable = -1; @@ -293,14 +291,13 @@ static int lookupName( pOrig = pEList->a[j].pExpr; if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); - sqlite3DbFree(db, zCol); return 2; } resolveAlias(pParse, pEList, j, pExpr, ""); cnt = 1; pMatch = 0; assert( zTab==0 && zDb==0 ); - goto lookupname_end_2; + goto lookupname_end; } } } @@ -324,7 +321,6 @@ static int lookupName( ** fields are not changed in any context. */ if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){ - sqlite3DbFree(db, zCol); pExpr->op = TK_STRING; pExpr->pTab = 0; return 0; @@ -363,18 +359,14 @@ static int lookupName( pMatch->colUsed |= ((Bitmask)1)<<n; } -lookupname_end: /* Clean up and return */ - sqlite3DbFree(db, zDb); - sqlite3DbFree(db, zTab); sqlite3ExprDelete(db, pExpr->pLeft); pExpr->pLeft = 0; sqlite3ExprDelete(db, pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; -lookupname_end_2: - sqlite3DbFree(db, zCol); +lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); @@ -447,7 +439,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->token, pNC, pExpr); + lookupName(pParse, 0, 0, pExpr->zToken, pNC, pExpr); return WRC_Prune; } @@ -455,24 +447,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ ** Or a database, table and column: ID.ID.ID */ case TK_DOT: { - Token *pColumn; - Token *pTable; - Token *pDb; + const char *zColumn; + const char *zTable; + const char *zDb; Expr *pRight; /* if( pSrcList==0 ) break; */ pRight = pExpr->pRight; if( pRight->op==TK_ID ){ - pDb = 0; - pTable = &pExpr->pLeft->token; - pColumn = &pRight->token; + zDb = 0; + zTable = pExpr->pLeft->zToken; + zColumn = pRight->zToken; }else{ assert( pRight->op==TK_DOT ); - pDb = &pExpr->pLeft->token; - pTable = &pRight->pLeft->token; - pColumn = &pRight->pRight->token; + zDb = pExpr->pLeft->zToken; + zTable = pRight->pLeft->zToken; + zColumn = pRight->pRight->zToken; } - lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr); + lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); return WRC_Prune; } @@ -492,8 +484,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ u8 enc = ENC(pParse->db); /* The database encoding */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - zId = (char*)pExpr->token.z; - nId = pExpr->token.n; + zId = pExpr->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); @@ -594,20 +586,14 @@ static int resolveAsName( ){ int i; /* Loop counter */ - if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){ - sqlite3 *db = pParse->db; - char *zCol = sqlite3NameFromToken(db, &pE->token); - if( zCol==0 ){ - return -1; - } + if( pE->op==TK_ID || (pE->op==TK_STRING && pE->zToken[0]!='\'') ){ + char *zCol = pE->zToken; for(i=0; i<pEList->nExpr; i++){ char *zAs = pEList->a[i].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ - sqlite3DbFree(db, zCol); return i+1; } } - sqlite3DbFree(db, zCol); } return 0; } @@ -758,7 +744,7 @@ static int resolveCompoundOrderBy( CollSeq *pColl = pE->pColl; int flags = pE->flags & EP_ExpCollate; sqlite3ExprDelete(db, pE); - pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0, 0, 0); + pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0); if( pE==0 ) return 1; pE->pColl = pColl; pE->flags |= EP_IntValue | flags; diff --git a/src/select.c b/src/select.c index c7c9e9de2..2f91ba9c5 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.518 2009/05/19 19:04:58 drh Exp $ +** $Id: select.c,v 1.519 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" @@ -71,7 +71,7 @@ Select *sqlite3SelectNew( memset(pNew, 0, sizeof(*pNew)); } if( pEList==0 ){ - pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0,0,0), 0); + pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0)); } pNew->pEList = pEList; pNew->pSrc = pSrc; @@ -192,22 +192,10 @@ static int columnIndex(Table *pTab, const char *zCol){ } /* -** Set the value of a token to a '\000'-terminated string. -*/ -static void setToken(Token *p, const char *z){ - p->z = (u8*)z; - p->n = z ? sqlite3Strlen30(z) : 0; - p->dyn = 0; - p->quoted = 0; -} - -/* ** Create an expression node for an identifier with the name of zName */ Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){ - Token dummy; - setToken(&dummy, zName); - return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy); + return sqlite3Expr(pParse->db, TK_ID, zName); } /* @@ -1072,7 +1060,7 @@ static void generateColumnNames( } if( !shortNames && !fullNames ){ sqlite3VdbeSetColName(v, i, COLNAME_NAME, - sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC); + sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC); }else if( fullNames ){ char *zName = 0; zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol); @@ -1082,7 +1070,7 @@ static void generateColumnNames( } }else{ sqlite3VdbeSetColName(v, i, COLNAME_NAME, - sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC); + sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC); } } generateColumnTypes(pParse, pTabList, pEList); @@ -1139,7 +1127,7 @@ static int selectColumnsFromExprList( /* Get an appropriate name for the column */ p = pEList->a[i].pExpr; - assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); + assert( p->pRight==0 || p->pRight->zToken==0 || p->pRight->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); @@ -1154,10 +1142,11 @@ static int selectColumnsFromExprList( 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); }else{ /* Use the original text of the column expression as its name */ - Token *pToken = (pColExpr->span.z?&pColExpr->span:&pColExpr->token); - zName = sqlite3MPrintf(db, "%T", pToken); + zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan); } } if( db->mallocFailed ){ @@ -2056,11 +2045,11 @@ static int multiSelectOrderBy( if( pItem->iCol==i ) break; } if( j==nOrderBy ){ - Expr *pNew = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0); + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); if( pNew==0 ) return SQLITE_NOMEM; pNew->flags |= EP_IntValue; pNew->iTable = i; - pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0); + pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); pOrderBy->a[nOrderBy++].iCol = (u16)i; } } @@ -2345,13 +2334,13 @@ static void substSelect(sqlite3*, Select *, int, ExprList *); ** changes to pExpr so that it refers directly to the source table ** of the subquery rather the result set of the subquery. */ -static void substExpr( +static Expr *substExpr( sqlite3 *db, /* Report malloc errors to this connection */ Expr *pExpr, /* Expr in which substitution occurs */ int iTable, /* Table to be substituted */ ExprList *pEList /* Substitute expressions */ ){ - if( pExpr==0 ) return; + if( pExpr==0 ) return 0; if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; @@ -2359,38 +2348,20 @@ static void substExpr( Expr *pNew; assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); assert( pExpr->pLeft==0 && pExpr->pRight==0 ); - pNew = pEList->a[pExpr->iColumn].pExpr; - assert( pNew!=0 ); - pExpr->op = pNew->op; - assert( pExpr->pLeft==0 ); - pExpr->pLeft = sqlite3ExprDup(db, pNew->pLeft, 0); - assert( pExpr->pRight==0 ); - pExpr->pRight = sqlite3ExprDup(db, pNew->pRight, 0); - pExpr->iTable = pNew->iTable; - pExpr->pTab = pNew->pTab; - pExpr->iColumn = pNew->iColumn; - pExpr->iAgg = pNew->iAgg; - sqlite3TokenCopy(db, &pExpr->token, &pNew->token); - sqlite3TokenCopy(db, &pExpr->span, &pNew->span); - assert( pExpr->x.pList==0 && pExpr->x.pSelect==0 ); - if( ExprHasProperty(pNew, EP_xIsSelect) ){ - pExpr->x.pSelect = sqlite3SelectDup(db, pNew->x.pSelect, 0); - }else{ - pExpr->x.pList = sqlite3ExprListDup(db, pNew->x.pList, 0); - } - pExpr->flags = pNew->flags; - pExpr->pAggInfo = pNew->pAggInfo; - pNew->pAggInfo = 0; + pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); + sqlite3ExprDelete(db, pExpr); + pExpr = pNew; } }else{ - substExpr(db, pExpr->pLeft, iTable, pEList); - substExpr(db, pExpr->pRight, iTable, pEList); + pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); + pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ substSelect(db, pExpr->x.pSelect, iTable, pEList); }else{ substExprList(db, pExpr->x.pList, iTable, pEList); } } + return pExpr; } static void substExprList( sqlite3 *db, /* Report malloc errors here */ @@ -2401,7 +2372,7 @@ static void substExprList( int i; if( pList==0 ) return; for(i=0; i<pList->nExpr; i++){ - substExpr(db, pList->a[i].pExpr, iTable, pEList); + pList->a[i].pExpr = substExpr(db, pList->a[i].pExpr, iTable, pEList); } } static void substSelect( @@ -2417,8 +2388,8 @@ static void substSelect( substExprList(db, p->pEList, iTable, pEList); substExprList(db, p->pGroupBy, iTable, pEList); substExprList(db, p->pOrderBy, iTable, pEList); - substExpr(db, p->pHaving, iTable, pEList); - substExpr(db, p->pWhere, iTable, pEList); + p->pHaving = substExpr(db, p->pHaving, iTable, pEList); + p->pWhere = substExpr(db, p->pWhere, iTable, pEList); substSelect(db, p->pPrior, iTable, pEList); pSrc = p->pSrc; assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */ @@ -2840,17 +2811,16 @@ static int flattenSubquery( pList = pParent->pEList; for(i=0; i<pList->nExpr; i++){ if( pList->a[i].zName==0 ){ - Expr *pExpr = pList->a[i].pExpr; - if( ALWAYS(pExpr->span.z!=0) ){ - pList->a[i].zName = - sqlite3DbStrNDup(db, (char*)pExpr->span.z, pExpr->span.n); + const char *zSpan = pList->a[i].zSpan; + if( zSpan ){ + pList->a[i].zName = sqlite3DbStrDup(db, zSpan); } } } substExprList(db, pParent->pEList, iParent, pSub->pEList); if( isAgg ){ substExprList(db, pParent->pGroupBy, iParent, pSub->pEList); - substExpr(db, pParent->pHaving, iParent, pSub->pEList); + pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); } if( pSub->pOrderBy ){ assert( pParent->pOrderBy==0 ); @@ -2868,13 +2838,13 @@ static int flattenSubquery( assert( pParent->pHaving==0 ); pParent->pHaving = pParent->pWhere; pParent->pWhere = pWhere; - substExpr(db, pParent->pHaving, iParent, pSub->pEList); + pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, sqlite3ExprDup(db, pSub->pHaving, 0)); assert( pParent->pGroupBy==0 ); pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); }else{ - substExpr(db, pParent->pWhere, iParent, pSub->pEList); + pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList); pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); } @@ -2926,10 +2896,9 @@ 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( pExpr->token.n!=3 ) return WHERE_ORDERBY_NORMAL; - if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){ + if( sqlite3StrICmp(pExpr->zToken,"min")==0 ){ return WHERE_ORDERBY_MIN; - }else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){ + }else if( sqlite3StrICmp(pExpr->zToken,"max")==0 ){ return WHERE_ORDERBY_MAX; } return WHERE_ORDERBY_NORMAL; @@ -3135,12 +3104,14 @@ static int selectExpander(Walker *pWalker, Select *p){ if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){ /* This particular expression does not need to be expanded. */ - pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0); + pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); if( pNew ){ pNew->a[pNew->nExpr-1].zName = a[k].zName; + pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan; + a[k].zName = 0; + a[k].zSpan = 0; } a[k].pExpr = 0; - a[k].zName = 0; }else{ /* This expression is a "*" or a "TABLE.*" and needs to be ** expanded. */ @@ -3148,7 +3119,7 @@ static int selectExpander(Walker *pWalker, Select *p){ char *zTName; /* text of name of TABLE */ if( pE->op==TK_DOT ){ assert( pE->pLeft!=0 ); - zTName = sqlite3NameFromToken(db, &pE->pLeft->token); + zTName = pE->pLeft->zToken; }else{ zTName = 0; } @@ -3166,6 +3137,9 @@ static int selectExpander(Walker *pWalker, Select *p){ for(j=0; j<pTab->nCol; j++){ Expr *pExpr, *pRight; char *zName = pTab->aCol[j].zName; + char *zColname; /* The computed column name */ + char *zToFree; /* Malloced string that needs to be freed */ + Token sColname; /* Computed column name as a token */ /* If a column is marked as 'hidden' (currently only possible ** for virtual tables), do not include it in the expanded @@ -3190,30 +3164,25 @@ static int selectExpander(Walker *pWalker, Select *p){ continue; } } - pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0); - if( pRight==0 ) break; - setToken(&pRight->token, zName); + pRight = sqlite3Expr(db, TK_ID, zName); + zColname = zName; + zToFree = 0; if( longNames || pTabList->nSrc>1 ){ - Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0); + Expr *pLeft; + pLeft = sqlite3Expr(db, TK_ID, zTabName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); - if( pExpr==0 ) break; - setToken(&pLeft->token, zTabName); - setToken(&pExpr->span, - sqlite3MPrintf(db, "%s.%s", zTabName, zName)); - pExpr->span.dyn = 1; - pExpr->token.z = 0; - pExpr->token.n = 0; - pExpr->token.dyn = 0; + if( longNames ){ + zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); + zToFree = zColname; + } }else{ pExpr = pRight; - pExpr->span = pExpr->token; - pExpr->span.dyn = 0; - } - if( longNames ){ - pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span); - }else{ - pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token); } + pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); + sColname.z = zColname; + sColname.n = sqlite3Strlen30(zColname); + sqlite3ExprListSetName(pParse, pNew, &sColname, 0); + sqlite3DbFree(db, zToFree); } } if( !tableSeen ){ @@ -3223,7 +3192,6 @@ static int selectExpander(Walker *pWalker, Select *p){ sqlite3ErrorMsg(pParse, "no tables specified"); } } - sqlite3DbFree(db, zTName); } } sqlite3ExprListDelete(db, pEList); @@ -4175,8 +4143,8 @@ select_end: ** or from temporary "printf" statements inserted for debugging. */ void sqlite3PrintExpr(Expr *p){ - if( p->token.z && p->token.n>0 ){ - sqlite3DebugPrintf("(%.*s", p->token.n, p->token.z); + if( p->zToken ){ + sqlite3DebugPrintf("(%s", p->zToken); }else{ sqlite3DebugPrintf("(%d", p->op); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index da3f09286..3c0a525dd 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.875 2009/05/20 02:40:46 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.876 2009/05/27 10:31:29 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -579,6 +579,7 @@ typedef struct Db Db; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; +typedef struct ExprSpan ExprSpan; typedef struct FKey FKey; typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; @@ -1015,6 +1016,7 @@ struct Module { struct Column { char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ + char *zDflt; /* Original text of the default value */ char *zType; /* Data type for this column */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* True if there is a NOT NULL constraint */ @@ -1360,10 +1362,8 @@ struct Index { ** and Token.n when Token.z==0. */ struct Token { - const unsigned char *z; /* Text of the token. Not NULL-terminated! */ - unsigned dyn : 1; /* True for malloced memory, false for static */ - unsigned quoted : 1; /* True if token still has its quotes */ - unsigned n : 30; /* Number of characters in this token */ + const char *z; /* Text of the token. Not NULL-terminated! */ + unsigned int n; /* Number of characters in this token */ }; /* @@ -1464,9 +1464,9 @@ 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 and/or Expr.span strings. +** together with Expr.token strings. ** -** If the EP_Reduced, EP_SpanToken, and EP_TokenOnly flags are set when +** 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 @@ -1476,22 +1476,14 @@ struct AggInfo { struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ - VVA_ONLY(u8 vvaFlags;) /* Flags used for VV&A only. EVVA_* below. */ u16 flags; /* Various flags. EP_* See below */ - Token token; /* An operand token */ + char *zToken; /* Token value. Zero terminated and dequoted */ /* 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. *********************************************************************/ - Token span; /* Complete text of the expression */ - - /* If the EP_SpanToken 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 { @@ -1505,11 +1497,14 @@ struct Expr { ** access them will result in a segfault or malfunction. *********************************************************************/ - int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the - ** iColumn-th field of the iTable-th table. */ + int iTable; /* TK_COLUMN: cursor number of table holding column + ** TK_REGISTER: register number + ** EP_IntValue: integer value */ + 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 */ - int iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ - int iRightJoinTable; /* If EP_FromJoin, the right table of the join */ Table *pTab; /* Table for TK_COLUMN expressions. */ #if SQLITE_MAX_EXPR_DEPTH>0 int nHeight; /* Height of the tree headed by this node */ @@ -1535,16 +1530,12 @@ struct Expr { #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ #define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */ -#define EP_SpanToken 0x8000 /* Expr size is EXPR_SPANTOKENSIZE bytes */ +#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */ /* -** The following are the meanings of bits in the Expr.vvaFlags field. -** This information is only used when SQLite is compiled with -** SQLITE_DEBUG defined. +** The following are the meanings of bits in the Expr.flags2 field. */ -#ifndef NDEBUG -#define EVVA_ReadOnlyToken 0x01 /* Expr.token.z is read-only */ -#endif +#define EP2_FreeToken 0x0001 /* Need to call sqlite3DbFree() on Expr.zToken */ /* ** These macros can be used to test, set, or clear bits in the @@ -1562,15 +1553,13 @@ struct Expr { */ #define EXPR_FULLSIZE sizeof(Expr) /* Full size */ #define EXPR_REDUCEDSIZE offsetof(Expr,iTable) /* Common features */ -#define EXPR_SPANTOKENSIZE offsetof(Expr,pLeft) /* Fewer features */ -#define EXPR_TOKENONLYSIZE offsetof(Expr,span) /* Smallest possible */ +#define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */ /* ** Flags passed to the sqlite3ExprDup() function. See the header comment ** above sqlite3ExprDup() for details. */ #define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */ -#define EXPRDUP_SPAN 0x0002 /* Make a copy of Expr.span */ /* ** A list of expressions. Each expression may optionally have a @@ -1587,6 +1576,7 @@ struct ExprList { struct ExprList_item { Expr *pExpr; /* The list of expressions */ char *zName; /* Token associated with this expression */ + char *zSpan; /* Original text of the expression */ u8 sortOrder; /* 1 for DESC or 0 for ASC */ u8 done; /* A flag to indicate when processing is finished */ u16 iCol; /* For ORDER BY, column number in result set */ @@ -1595,6 +1585,17 @@ struct ExprList { }; /* +** An instance of this structure is used by the parser to record both +** the parse tree for an expression and the span of input text for an +** expression. +*/ +struct ExprSpan { + Expr *pExpr; /* The expression parse tree */ + const char *zStart; /* First character of input text */ + const char *zEnd; /* One character past the end of input text */ +}; + +/* ** An instance of this structure can hold a simple list of identifiers, ** such as the list "a,b,c" in the following statements: ** @@ -2044,7 +2045,6 @@ struct Trigger { Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */ IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger, the <column-list> is stored here */ - Token nameToken; /* Token containing zName. Use during parsing only */ Schema *pSchema; /* Schema containing the trigger */ Schema *pTabSchema; /* Schema containing the table */ TriggerStep *step_list; /* Link list of trigger program steps */ @@ -2078,7 +2078,7 @@ struct Trigger { * orconf -> stores the ON CONFLICT algorithm * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then * this stores a pointer to the SELECT statement. Otherwise NULL. - * target -> A token holding the name of the table to insert into. + * target -> A token holding the quoted name of the table to insert into. * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then * this stores values to be inserted. Otherwise NULL. * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ... @@ -2086,12 +2086,12 @@ struct Trigger { * inserted into. * * (op == TK_DELETE) - * target -> A token holding the name of the table to delete from. + * target -> A token holding the quoted name of the table to delete from. * pWhere -> The WHERE clause of the DELETE statement if one is specified. * Otherwise NULL. * * (op == TK_UPDATE) - * target -> A token holding the name of the table to update rows of. + * target -> A token holding the quoted name of the table to update rows of. * pWhere -> The WHERE clause of the UPDATE statement if one is specified. * Otherwise NULL. * pExprList -> A list of the columns to update and the expressions to update @@ -2106,7 +2106,7 @@ struct TriggerStep { Select *pSelect; /* Valid for SELECT and sometimes INSERT steps (when pExprList == 0) */ - Token target; /* Valid for DELETE, UPDATE, INSERT steps */ + Token target; /* Target table for DELETE, UPDATE, INSERT. Quoted */ Expr *pWhere; /* Valid for DELETE, UPDATE steps */ ExprList *pExprList; /* Valid for UPDATE statements and sometimes INSERT steps (when pSelect == 0) */ @@ -2384,16 +2384,19 @@ int sqlite3GetTempReg(Parse*); void sqlite3ReleaseTempReg(Parse*,int); int sqlite3GetTempRange(Parse*,int); void sqlite3ReleaseTempRange(Parse*,int,int); -Expr *sqlite3Expr(sqlite3*, int, Expr*, Expr*, const Token*); +Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); +Expr *sqlite3Expr(sqlite3*,int,const char*); +void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*); Expr *sqlite3RegisterExpr(Parse*,Token*); Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); -void sqlite3ExprSpan(Expr*,Token*,Token*); Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); void sqlite3ExprAssignVarNumber(Parse*, Expr*); void sqlite3ExprClear(sqlite3*, Expr*); void sqlite3ExprDelete(sqlite3*, Expr*); -ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*,Token*); +ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); +void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); +void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); void sqlite3ExprListDelete(sqlite3*, ExprList*); int sqlite3Init(sqlite3*, char**); int sqlite3InitCallback(void*, int, char**, char**); @@ -2409,7 +2412,7 @@ void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); void sqlite3AddColumnType(Parse*,Token*); -void sqlite3AddDefaultValue(Parse*,Expr*); +void sqlite3AddDefaultValue(Parse*,ExprSpan*); void sqlite3AddCollateType(Parse*, Token*); void sqlite3EndTable(Parse*,Token*,Token*,Select*); @@ -2523,7 +2526,6 @@ void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int,int,int); int sqlite3OpenTableAndIndices(Parse*, Table*, int, int); void sqlite3BeginWriteOperation(Parse*, int, int); Expr *sqlite3ExprDup(sqlite3*,Expr*,int); -void sqlite3TokenCopy(sqlite3*,Token*,const Token*); ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); IdList *sqlite3IdListDup(sqlite3*,IdList*); @@ -2694,7 +2696,7 @@ void sqlite3ColumnDefault(Vdbe *, Table *, int); void sqlite3AlterFinishAddColumn(Parse *, Token *); void sqlite3AlterBeginAddColumn(Parse *, SrcList *); CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char*); -char sqlite3AffinityType(const Token*); +char sqlite3AffinityType(const char*); void sqlite3Analyze(Parse*, Token*, Token*); int sqlite3InvokeBusyHandler(BusyHandler*); int sqlite3FindDb(sqlite3*, Token*); diff --git a/src/tokenize.c b/src/tokenize.c index a933de1b9..3e6c98c97 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.156 2009/05/01 21:13:37 drh Exp $ +** $Id: tokenize.c,v 1.157 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> @@ -404,7 +404,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ db->mallocFailed = 1; return SQLITE_NOMEM; } - assert( pParse->sLastToken.dyn==0 ); assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); @@ -413,12 +412,9 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ assert( pParse->apVarExpr==0 ); enableLookaside = db->lookaside.bEnabled; if( db->lookaside.pStart ) db->lookaside.bEnabled = 1; - pParse->sLastToken.quoted = 1; while( !db->mallocFailed && zSql[i]!=0 ){ assert( i>=0 ); - pParse->sLastToken.z = (u8*)&zSql[i]; - assert( pParse->sLastToken.dyn==0 ); - assert( pParse->sLastToken.quoted ); + pParse->sLastToken.z = &zSql[i]; pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); i += pParse->sLastToken.n; if( i>mxSqlLen ){ diff --git a/src/trigger.c b/src/trigger.c index 131b67599..718e46e11 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -10,7 +10,7 @@ ************************************************************************* ** ** -** $Id: trigger.c,v 1.139 2009/05/09 00:18:38 drh Exp $ +** $Id: trigger.c,v 1.140 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" @@ -23,7 +23,6 @@ void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){ TriggerStep * pTmp = pTriggerStep; pTriggerStep = pTriggerStep->pNext; - if( pTmp->target.dyn ) sqlite3DbFree(db, (char*)pTmp->target.z); sqlite3ExprDelete(db, pTmp->pWhere); sqlite3ExprListDelete(db, pTmp->pExprList); sqlite3SelectDelete(db, pTmp->pSelect); @@ -218,7 +217,6 @@ void sqlite3BeginTrigger( pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); pTrigger->pColumns = sqlite3IdListDup(db, pColumns); - sqlite3TokenCopy(db, &pTrigger->nameToken, pName); assert( pParse->pNewTrigger==0 ); pParse->pNewTrigger = pTrigger; @@ -248,6 +246,7 @@ void sqlite3FinishTrigger( sqlite3 *db = pParse->db; /* The database */ DbFixer sFix; int iDb; /* Database containing the trigger */ + Token nameToken; /* Trigger name for error reporting */ pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; @@ -259,7 +258,9 @@ void sqlite3FinishTrigger( pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } - if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) + nameToken.z = pTrig->name; + nameToken.n = sqlite3Strlen30(nameToken.z); + if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken) && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ goto triggerfinish_cleanup; } @@ -310,43 +311,6 @@ triggerfinish_cleanup: } /* -** Make a copy of all components of the given trigger step. This has -** the effect of copying all Expr.token.z values into memory obtained -** from sqlite3_malloc(). As initially created, the Expr.token.z values -** all point to the input string that was fed to the parser. But that -** string is ephemeral - it will go away as soon as the sqlite3_exec() -** call that started the parser exits. This routine makes a persistent -** copy of all the Expr.token.z strings so that the TriggerStep structure -** will be valid even after the sqlite3_exec() call returns. -*/ -static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){ - if( p->target.z ){ - p->target.z = (u8*)sqlite3DbStrNDup(db, (char*)p->target.z, p->target.n); - p->target.dyn = 1; - } - if( p->pSelect ){ - Select *pNew = sqlite3SelectDup(db, p->pSelect, 1); - sqlite3SelectDelete(db, p->pSelect); - p->pSelect = pNew; - } - if( p->pWhere ){ - Expr *pNew = sqlite3ExprDup(db, p->pWhere, EXPRDUP_REDUCE); - sqlite3ExprDelete(db, p->pWhere); - p->pWhere = pNew; - } - if( p->pExprList ){ - ExprList *pNew = sqlite3ExprListDup(db, p->pExprList, 1); - sqlite3ExprListDelete(db, p->pExprList); - p->pExprList = pNew; - } - if( p->pIdList ){ - IdList *pNew = sqlite3IdListDup(db, p->pIdList); - sqlite3IdListDelete(db, p->pIdList); - p->pIdList = pNew; - } -} - -/* ** Turn a SELECT statement (that the pSelect parameter points to) into ** a trigger step. Return a pointer to a TriggerStep structure. ** @@ -359,12 +323,33 @@ TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ sqlite3SelectDelete(db, pSelect); return 0; } - pTriggerStep->op = TK_SELECT; pTriggerStep->pSelect = pSelect; pTriggerStep->orconf = OE_Default; - sqlitePersistTriggerStep(db, pTriggerStep); + return pTriggerStep; +} + +/* +** Allocate space to hold a new trigger step. The allocated space +** holds both the TriggerStep object and the TriggerStep.target.z string. +** +** If an OOM error occurs, NULL is returned and db->mallocFailed is set. +*/ +static TriggerStep *triggerStepAllocate( + sqlite3 *db, /* Database connection */ + int op, /* Trigger opcode */ + Token *pName /* The target name */ +){ + TriggerStep *pTriggerStep; + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n); + if( pTriggerStep ){ + char *z = (char*)&pTriggerStep[1]; + memcpy(z, pName->z, pName->n); + pTriggerStep->target.z = z; + pTriggerStep->target.n = pName->n; + pTriggerStep->op = op; + } return pTriggerStep; } @@ -388,15 +373,12 @@ TriggerStep *sqlite3TriggerInsertStep( assert(pEList == 0 || pSelect == 0); assert(pEList != 0 || pSelect != 0 || db->mallocFailed); - pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); + pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); if( pTriggerStep ){ - pTriggerStep->op = TK_INSERT; pTriggerStep->pSelect = pSelect; - pTriggerStep->target = *pTableName; pTriggerStep->pIdList = pColumn; pTriggerStep->pExprList = pEList; pTriggerStep->orconf = orconf; - sqlitePersistTriggerStep(db, pTriggerStep); }else{ sqlite3IdListDelete(db, pColumn); sqlite3ExprListDelete(db, pEList); @@ -418,20 +400,17 @@ TriggerStep *sqlite3TriggerUpdateStep( Expr *pWhere, /* The WHERE clause */ int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ ){ - TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); + TriggerStep *pTriggerStep; + + pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName); if( pTriggerStep==0 ){ sqlite3ExprListDelete(db, pEList); sqlite3ExprDelete(db, pWhere); return 0; } - - pTriggerStep->op = TK_UPDATE; - pTriggerStep->target = *pTableName; pTriggerStep->pExprList = pEList; pTriggerStep->pWhere = pWhere; pTriggerStep->orconf = orconf; - sqlitePersistTriggerStep(db, pTriggerStep); - return pTriggerStep; } @@ -445,17 +424,15 @@ TriggerStep *sqlite3TriggerDeleteStep( Token *pTableName, /* The table from which rows are deleted */ Expr *pWhere /* The WHERE clause */ ){ - TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); + TriggerStep *pTriggerStep; + + pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName); if( pTriggerStep==0 ){ sqlite3ExprDelete(db, pWhere); return 0; } - - pTriggerStep->op = TK_DELETE; - pTriggerStep->target = *pTableName; pTriggerStep->pWhere = pWhere; pTriggerStep->orconf = OE_Default; - sqlitePersistTriggerStep(db, pTriggerStep); return pTriggerStep; } @@ -470,8 +447,6 @@ void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ sqlite3DbFree(db, pTrigger->table); sqlite3ExprDelete(db, pTrigger->pWhen); sqlite3IdListDelete(db, pTrigger->pColumns); - assert( pTrigger->nameToken.dyn ); - sqlite3DbFree(db, (char*)pTrigger->nameToken.z); sqlite3DbFree(db, pTrigger); } @@ -669,15 +644,16 @@ static SrcList *targetSrcList( int iDb; /* Index of the database to use */ SrcList *pSrc; /* SrcList to be returned */ - iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); - if( iDb==0 || iDb>=2 ){ - assert( iDb<pParse->db->nDb ); - sDb.z = (u8*)pParse->db->aDb[iDb].zName; - sDb.n = sqlite3Strlen30((char*)sDb.z); - sDb.quoted = 0; - pSrc = sqlite3SrcListAppend(pParse->db, 0, &sDb, &pStep->target); - } else { - pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); + pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); + if( pSrc ){ + assert( pSrc->nSrc>0 ); + assert( pSrc->a!=0 ); + iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); + if( iDb==0 || iDb>=2 ){ + sqlite3 *db = pParse->db; + assert( iDb<pParse->db->nDb ); + pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); + } } return pSrc; } diff --git a/src/update.c b/src/update.c index daab3adf0..e72a6354a 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.200 2009/05/05 15:46:10 drh Exp $ +** $Id: update.c,v 1.201 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" @@ -630,10 +630,10 @@ static void updateVirtualTable( ** all updated rows. */ pEList = sqlite3ExprListAppend(pParse, 0, - sqlite3CreateIdExpr(pParse, "_rowid_"), 0); + sqlite3CreateIdExpr(pParse, "_rowid_")); if( pRowid ){ pEList = sqlite3ExprListAppend(pParse, pEList, - sqlite3ExprDup(db, pRowid, 0), 0); + sqlite3ExprDup(db, pRowid, 0)); } assert( pTab->iPKey<0 ); for(i=0; i<pTab->nCol; i++){ @@ -642,7 +642,7 @@ static void updateVirtualTable( }else{ pExpr = sqlite3CreateIdExpr(pParse, pTab->aCol[i].zName); } - pEList = sqlite3ExprListAppend(pParse, pEList, pExpr, 0); + pEList = sqlite3ExprListAppend(pParse, pEList, pExpr); } pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); diff --git a/src/util.c b/src/util.c index 4ce0eaa48..76a8848db 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.254 2009/05/06 19:03:14 drh Exp $ +** $Id: util.c,v 1.255 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> @@ -108,6 +108,7 @@ int sqlite3IsNaN(double x){ */ int sqlite3Strlen30(const char *z){ const char *z2 = z; + if( z==0 ) return 0; while( *z2 ){ z2++; } return 0x3fffffff & (int)(z2 - z); } diff --git a/src/vdbemem.c b/src/vdbemem.c index e946067a4..004ea367f 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.144 2009/05/05 12:54:50 drh Exp $ +** $Id: vdbemem.c,v 1.145 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -974,7 +974,7 @@ int sqlite3ValueFromExpr( op = pExpr->op; if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ - zVal = sqlite3DbStrNDup(db, (char*)pExpr->token.z, pExpr->token.n); + zVal = sqlite3DbStrDup(db, pExpr->zToken); pVal = sqlite3ValueNew(db); if( !zVal || !pVal ) goto no_mem; sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); @@ -996,14 +996,13 @@ int sqlite3ValueFromExpr( #ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ int nVal; - assert( pExpr->token.n>=3 ); - assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' ); - assert( pExpr->token.z[1]=='\'' ); - assert( pExpr->token.z[pExpr->token.n-1]=='\'' ); + assert( pExpr->zToken[0]=='x' || pExpr->zToken[0]=='X' ); + assert( pExpr->zToken[1]=='\'' ); pVal = sqlite3ValueNew(db); if( !pVal ) goto no_mem; - nVal = pExpr->token.n - 3; - zVal = (char*)pExpr->token.z + 2; + zVal = &pExpr->zToken[2]; + nVal = sqlite3Strlen30(zVal)-1; + assert( zVal[nVal]=='\'' ); sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, 0, SQLITE_DYNAMIC); } diff --git a/src/walker.c b/src/walker.c index 19fb4e035..7be9e252f 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.4 2009/04/08 13:51:52 drh Exp $ +** $Id: walker.c,v 1.5 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> @@ -42,11 +42,10 @@ int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ int rc; if( pExpr==0 ) return WRC_Continue; testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); - testcase( ExprHasProperty(pExpr, EP_SpanToken) ); testcase( ExprHasProperty(pExpr, EP_Reduced) ); rc = pWalker->xExprCallback(pWalker, pExpr); if( rc==WRC_Continue - && !ExprHasAnyProperty(pExpr,EP_TokenOnly|EP_SpanToken) ){ + && !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){ if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ diff --git a/src/where.c b/src/where.c index 6bbc4af39..7396bf198 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.397 2009/05/22 15:43:27 danielk1977 Exp $ +** $Id: where.c,v 1.398 2009/05/27 10:31:29 drh Exp $ */ #include "sqliteInt.h" @@ -628,7 +628,6 @@ static int isLikeOrGlob( Expr *pRight, *pLeft; /* Right and left size of LIKE operator */ ExprList *pList; /* List of operands to the LIKE operator */ int c; /* One character in z[] */ - int n; /* Length of string z[] */ int cnt; /* Number of non-wildcard prefix characters */ char wc[3]; /* Wildcard characters */ CollSeq *pColl; /* Collating sequence for LHS */ @@ -659,15 +658,14 @@ static int isLikeOrGlob( (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){ return 0; } - z = (const char*)pRight->token.z; + z = pRight->zToken; cnt = 0; if( z ){ - n = pRight->token.n; - while( cnt<n && (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ + while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; } } - if( cnt==0 || 255==(u8)z[cnt-1] ){ + if( cnt==0 || c==0 || 255==(u8)z[cnt-1] ){ return 0; } *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0; @@ -693,8 +691,7 @@ static int isMatchOfColumn( if( pExpr->op!=TK_FUNCTION ){ return 0; } - if( pExpr->token.n!=5 || - sqlite3StrNICmp((const char*)pExpr->token.z,"match",5)!=0 ){ + if( sqlite3StrICmp(pExpr->zToken,"match")!=0 ){ return 0; } pList = pExpr->x.pList; @@ -963,12 +960,12 @@ static void exprAnalyzeOrTerm( assert( pOrTerm->leftCursor==iCursor ); assert( pOrTerm->u.leftColumn==iColumn ); pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); - pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0); + pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup); pLeft = pOrTerm->pExpr->pLeft; } assert( pLeft!=0 ); pDup = sqlite3ExprDup(db, pLeft, 0); - pNew = sqlite3Expr(db, TK_IN, pDup, 0, 0); + pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0, 0); if( pNew ){ int idxNew; transferJoinMarkings(pNew, pExpr); @@ -1121,7 +1118,8 @@ static void exprAnalyze( for(i=0; i<2; i++){ Expr *pNewExpr; int idxNew; - pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft, 0), + pNewExpr = sqlite3PExpr(pParse, ops[i], + sqlite3ExprDup(db, pExpr->pLeft, 0), sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); @@ -1163,16 +1161,12 @@ static void exprAnalyze( pLeft = pExpr->x.pList->a[1].pExpr; pRight = pExpr->x.pList->a[0].pExpr; - pStr1 = sqlite3PExpr(pParse, TK_STRING, 0, 0, 0); - if( pStr1 ){ - sqlite3TokenCopy(db, &pStr1->token, &pRight->token); - pStr1->token.n = nPattern; - } + pStr1 = sqlite3Expr(db, TK_STRING, pRight->zToken); + if( pStr1 ) pStr1->zToken[nPattern] = 0; pStr2 = sqlite3ExprDup(db, pStr1, 0); if( !db->mallocFailed ){ u8 c, *pC; - /* assert( pStr2->token.dyn ); */ - pC = (u8*)&pStr2->token.z[nPattern-1]; + pC = (u8*)&pStr2->zToken[nPattern-1]; c = *pC; if( noCase ){ if( c=='@' ) isComplete = 0; @@ -1216,7 +1210,8 @@ static void exprAnalyze( prereqColumn = exprTableUsage(pMaskSet, pLeft); if( (prereqExpr & prereqColumn)==0 ){ Expr *pNewExpr; - pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight, 0), 0); + pNewExpr = sqlite3PExpr(pParse, TK_MATCH, + 0, sqlite3ExprDup(db, pRight, 0), 0); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); pNewTerm = &pWC->a[idxNew]; @@ -2296,7 +2291,6 @@ static int codeEqualityTerm( eType = sqlite3FindInIndex(pParse, pX, 0); iTab = pX->iTable; sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); - VdbeComment((v, "%.*s", pX->span.n, pX->span.z)); assert( pLevel->plan.wsFlags & WHERE_IN_ABLE ); if( pLevel->u.in.nIn==0 ){ pLevel->addrNxt = sqlite3VdbeMakeLabel(v); |