mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-08 03:22:21 +03:00
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
This commit is contained in:
446
src/expr.c
446
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*)"";
|
||||
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));
|
||||
}
|
||||
if( c=='"' ) pNew->flags |= EP_DblQuoted;
|
||||
}else{
|
||||
pNew->token = *pToken;
|
||||
}
|
||||
pNew->token.quoted = 0;
|
||||
}else if( pLeft ){
|
||||
if( pRight ){
|
||||
if( pRight->span.dyn==0 && pLeft->span.dyn==0 ){
|
||||
sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span);
|
||||
}
|
||||
if( pRight->flags & EP_ExpCollate ){
|
||||
pNew->flags |= EP_ExpCollate;
|
||||
pNew->pColl = pRight->pColl;
|
||||
}
|
||||
}
|
||||
if( pLeft->flags & EP_ExpCollate ){
|
||||
pNew->flags |= EP_ExpCollate;
|
||||
pNew->pColl = pLeft->pColl;
|
||||
}
|
||||
}
|
||||
int nExtra;
|
||||
|
||||
exprSetHeight(pNew);
|
||||
if( pToken ){
|
||||
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 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 ){
|
||||
pRoot->pRight = pRight;
|
||||
if( pRight->flags & EP_ExpCollate ){
|
||||
pRoot->flags |= EP_ExpCollate;
|
||||
pRoot->pColl = pRight->pColl;
|
||||
}
|
||||
}
|
||||
if( pLeft ){
|
||||
pRoot->pLeft = pLeft;
|
||||
if( pLeft->flags & EP_ExpCollate ){
|
||||
pRoot->flags |= EP_ExpCollate;
|
||||
pRoot->pColl = pLeft->pColl;
|
||||
}
|
||||
}
|
||||
exprSetHeight(pRoot);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** 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;
|
||||
|
||||
@@ -1037,6 +988,56 @@ no_mem:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** 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++;
|
||||
|
||||
Reference in New Issue
Block a user