📄 expr.c
字号:
/*** 2001 September 15**** The author disclaims copyright to this source code. In place of** a legal notice, here is a blessing:**** May you do good and not evil.** May you find forgiveness for yourself and forgive others.** May you share freely, never taking more than you give.***************************************************************************** This file contains routines used for analyzing expressions and** for generating VDBE code that evaluates expressions in SQLite.**** $Id: expr.c,v 1.98 2003/07/30 12:34:12 drh Exp $*/#include "sqliteInt.h"#include <ctype.h>/*** Construct a new expression node and return a pointer to it. Memory** for this node is obtained from sqliteMalloc(). The calling function** is responsible for making sure the node eventually gets freed.*/Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){ Expr *pNew; pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ sqliteExprDelete(pLeft); sqliteExprDelete(pRight); return 0; } pNew->op = op; pNew->pLeft = pLeft; pNew->pRight = pRight; if( pToken ){ assert( pToken->dyn==0 ); pNew->token = *pToken; pNew->span = *pToken; }else{ pNew->token.dyn = 0; pNew->token.z = 0; pNew->token.n = 0; if( pLeft && pRight ){ sqliteExprSpan(pNew, &pLeft->span, &pRight->span); }else{ pNew->span = pNew->token; } } return pNew;}/*** Set the Expr.span field of the given expression to span all** text between the two given tokens.*/void sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ if( pExpr && pRight && pRight->z && pLeft && pLeft->z ){ if( pLeft->dyn==0 && pRight->dyn==0 ){ pExpr->span.z = pLeft->z; pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z); }else{ pExpr->span.z = 0; pExpr->span.n = 0; pExpr->span.dyn = 0; } }}/*** Construct a new expression node for a function with multiple** arguments.*/Expr *sqliteExprFunction(ExprList *pList, Token *pToken){ Expr *pNew; pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ sqliteExprListDelete(pList); return 0; } pNew->op = TK_FUNCTION; pNew->pList = pList; pNew->token.dyn = 0; if( pToken ){ assert( pToken->dyn==0 ); pNew->token = *pToken; }else{ pNew->token.z = 0; pNew->token.n = 0; } pNew->span = pNew->token; return pNew;}/*** Recursively delete an expression tree.*/void sqliteExprDelete(Expr *p){ if( p==0 ) return; if( p->span.dyn && p->span.z ) sqliteFree((char*)p->span.z); if( p->token.dyn && p->token.z ) sqliteFree((char*)p->token.z); if( p->pLeft ) sqliteExprDelete(p->pLeft); if( p->pRight ) sqliteExprDelete(p->pRight); if( p->pList ) sqliteExprListDelete(p->pList); if( p->pSelect ) sqliteSelectDelete(p->pSelect); sqliteFree(p);}/*** The following group of routines make deep copies of expressions,** expression lists, ID lists, and select statements. The copies can** be deleted (by being passed to their respective ...Delete() routines)** without effecting the originals.**** The expression list, ID, and source lists return by sqliteExprListDup(),** sqliteIdListDup(), and sqliteSrcListDup() can not be further expanded ** by subsequent calls to sqlite*ListAppend() routines.**** Any tables that the SrcList might point to are not duplicated.*/Expr *sqliteExprDup(Expr *p){ Expr *pNew; if( p==0 ) return 0; pNew = sqliteMallocRaw( sizeof(*p) ); if( pNew==0 ) return 0; memcpy(pNew, p, sizeof(*pNew)); if( p->token.z!=0 ){ pNew->token.z = sqliteStrDup(p->token.z); pNew->token.dyn = 1; }else{ pNew->token.z = 0; pNew->token.n = 0; pNew->token.dyn = 0; } pNew->span.z = 0; pNew->span.n = 0; pNew->span.dyn = 0; pNew->pLeft = sqliteExprDup(p->pLeft); pNew->pRight = sqliteExprDup(p->pRight); pNew->pList = sqliteExprListDup(p->pList); pNew->pSelect = sqliteSelectDup(p->pSelect); return pNew;}void sqliteTokenCopy(Token *pTo, Token *pFrom){ if( pTo->dyn ) sqliteFree((char*)pTo->z); if( pFrom->z ){ pTo->n = pFrom->n; pTo->z = sqliteStrNDup(pFrom->z, pFrom->n); pTo->dyn = 1; }else{ pTo->n = 0; pTo->z = 0; pTo->dyn = 0; }}ExprList *sqliteExprListDup(ExprList *p){ ExprList *pNew; int i; if( p==0 ) return 0; pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nExpr = pNew->nAlloc = p->nExpr; pNew->a = sqliteMalloc( p->nExpr*sizeof(p->a[0]) ); if( pNew->a==0 ) return 0; for(i=0; i<p->nExpr; i++){ Expr *pNewExpr, *pOldExpr; pNew->a[i].pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr); if( pOldExpr->span.z!=0 && pNewExpr ){ /* 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 */ sqliteTokenCopy(&pNewExpr->span, &pOldExpr->span); } assert( pNewExpr==0 || pNewExpr->span.z!=0 || pOldExpr->span.z==0 || sqlite_malloc_failed ); pNew->a[i].zName = sqliteStrDup(p->a[i].zName); pNew->a[i].sortOrder = p->a[i].sortOrder; pNew->a[i].isAgg = p->a[i].isAgg; pNew->a[i].done = 0; } return pNew;}SrcList *sqliteSrcListDup(SrcList *p){ SrcList *pNew; int i; int nByte; if( p==0 ) return 0; nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); pNew = sqliteMalloc( nByte ); if( pNew==0 ) return 0; pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; i<p->nSrc; i++){ pNew->a[i].zDatabase = sqliteStrDup(p->a[i].zDatabase); pNew->a[i].zName = sqliteStrDup(p->a[i].zName); pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias); pNew->a[i].jointype = p->a[i].jointype; pNew->a[i].iCursor = p->a[i].iCursor; pNew->a[i].pTab = 0; pNew->a[i].pSelect = sqliteSelectDup(p->a[i].pSelect); pNew->a[i].pOn = sqliteExprDup(p->a[i].pOn); pNew->a[i].pUsing = sqliteIdListDup(p->a[i].pUsing); } return pNew;}IdList *sqliteIdListDup(IdList *p){ IdList *pNew; int i; if( p==0 ) return 0; pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nId = pNew->nAlloc = p->nId; pNew->a = sqliteMalloc( p->nId*sizeof(p->a[0]) ); if( pNew->a==0 ) return 0; for(i=0; i<p->nId; i++){ pNew->a[i].zName = sqliteStrDup(p->a[i].zName); pNew->a[i].idx = p->a[i].idx; } return pNew;}Select *sqliteSelectDup(Select *p){ Select *pNew; if( p==0 ) return 0; pNew = sqliteMalloc( sizeof(*p) ); if( pNew==0 ) return 0; pNew->isDistinct = p->isDistinct; pNew->pEList = sqliteExprListDup(p->pEList); pNew->pSrc = sqliteSrcListDup(p->pSrc); pNew->pWhere = sqliteExprDup(p->pWhere); pNew->pGroupBy = sqliteExprListDup(p->pGroupBy); pNew->pHaving = sqliteExprDup(p->pHaving); pNew->pOrderBy = sqliteExprListDup(p->pOrderBy); pNew->op = p->op; pNew->pPrior = sqliteSelectDup(p->pPrior); pNew->nLimit = p->nLimit; pNew->nOffset = p->nOffset; pNew->zSelect = 0; pNew->iLimit = -1; pNew->iOffset = -1; return pNew;}/*** Add a new element to the end of an expression list. If pList is** initially NULL, then create a new expression list.*/ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){ int i; if( pList==0 ){ pList = sqliteMalloc( sizeof(ExprList) ); if( pList==0 ){ sqliteExprDelete(pExpr); return 0; } pList->nAlloc = 0; } if( pList->nAlloc<=pList->nExpr ){ struct ExprList_item *a; pList->nAlloc = pList->nAlloc*2 + 4; a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0])); if( a==0 ){ sqliteExprDelete(pExpr); return pList; } pList->a = a; } if( pExpr || pName ){ i = pList->nExpr++; pList->a[i].pExpr = pExpr; pList->a[i].zName = 0; if( pName ){ sqliteSetNString(&pList->a[i].zName, pName->z, pName->n, 0); sqliteDequote(pList->a[i].zName); } } return pList;}/*** Delete an entire expression list.*/void sqliteExprListDelete(ExprList *pList){ int i; if( pList==0 ) return; for(i=0; i<pList->nExpr; i++){ sqliteExprDelete(pList->a[i].pExpr); sqliteFree(pList->a[i].zName); } sqliteFree(pList->a); sqliteFree(pList);}/*** Walk an expression tree. Return 1 if the expression is constant** and 0 if it involves variables.**** For the purposes of this function, a double-quoted string (ex: "abc")** is considered a variable but a single-quoted string (ex: 'abc') is** a constant.*/int sqliteExprIsConstant(Expr *p){ switch( p->op ){ case TK_ID: case TK_COLUMN: case TK_DOT: case TK_FUNCTION: return 0; case TK_NULL: case TK_STRING: case TK_INTEGER: case TK_FLOAT: return 1; default: { if( p->pLeft && !sqliteExprIsConstant(p->pLeft) ) return 0; if( p->pRight && !sqliteExprIsConstant(p->pRight) ) return 0; if( p->pList ){ int i; for(i=0; i<p->pList->nExpr; i++){ if( !sqliteExprIsConstant(p->pList->a[i].pExpr) ) return 0; } } return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0); } } return 0;}/*** If the given expression codes a constant integer, return 1 and put** the value of the integer in *pValue. If the expression is not an** integer, return 0 and leave *pValue unchanged.*/int sqliteExprIsInteger(Expr *p, int *pValue){ switch( p->op ){ case TK_INTEGER: { *pValue = atoi(p->token.z); return 1; } case TK_STRING: { const char *z = p->token.z; int n = p->token.n; if( n>0 && z[0]=='-' ){ z++; n--; } while( n>0 && *z && isdigit(*z) ){ z++; n--; } if( n==0 ){ *pValue = atoi(p->token.z); return 1; } break; } case TK_UPLUS: { return sqliteExprIsInteger(p->pLeft, pValue); } case TK_UMINUS: { int v; if( sqliteExprIsInteger(p->pLeft, &v) ){ *pValue = -v; return 1; } break; } default: break; } return 0;}/*** Return TRUE if the given string is a row-id column name.*/int sqliteIsRowid(const char *z){ if( sqliteStrICmp(z, "_ROWID_")==0 ) return 1; if( sqliteStrICmp(z, "ROWID")==0 ) return 1; if( sqliteStrICmp(z, "OID")==0 ) return 1; return 0;}/*** This routine walks an expression tree and resolves references to** table columns. Nodes of the form ID.ID or ID resolve into an** index to the table in the table list and a column offset. The ** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable** value is changed to the index of the referenced table in pTabList** plus the "base" value. The base value will ultimately become the** VDBE cursor number for a cursor that is pointing into the referenced** table. The Expr.iColumn value is changed to the index of the column ** of the referenced table. The Expr.iColumn value for the special** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an** alias for ROWID.**** We also check for instances of the IN operator. IN comes in two** forms:**** expr IN (exprlist)** and** expr IN (SELECT ...)**** The first form is handled by creating a set holding the list** of allowed values. The second form causes the SELECT to generate ** a temporary table.**** This routine also looks for scalar SELECTs that are part of an expression.** If it finds any, it generates code to write the value of that select** into a memory cell.**** Unknown columns or tables provoke an error. The function returns** the number of errors seen and leaves an error message on pParse->zErrMsg.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -