aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2009-05-27 10:31:29 +0000
committerdrh <drh@noemail.net>2009-05-27 10:31:29 +0000
commitb7916a78ff7708161b6e2de54af5aea85a07c543 (patch)
tree0699a42ca40c038b563d4fadd6bfeb2080942de0 /src/expr.c
parent38a2c01b09b494030bd3f62743119331522d1e04 (diff)
downloadsqlite-b7916a78ff7708161b6e2de54af5aea85a07c543.tar.gz
sqlite-b7916a78ff7708161b6e2de54af5aea85a07c543.zip
Simplifications to the Expr object: Remove Expr.span completely and convert
Expr.token into a char* Expr.zToken. Also simplify the Token object by removing the Token.dyn and Token.quoted fields. (CVS 6681) FossilOrigin-Name: 7cb1c3ba0759539cb035978fdaff6316775986f3
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c432
1 files changed, 215 insertions, 217 deletions
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++;