📄 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.114.2.4 2004/11/20 20:42:10 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 ){ /* When malloc fails, we leak memory from pLeft and 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{ assert( pNew->token.dyn==0 ); assert( pNew->token.z==0 ); assert( 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){ assert( pRight!=0 ); assert( pLeft!=0 ); /* Note: pExpr might be NULL due to a prior malloc failure */ if( pExpr && pRight->z && 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; } }}/*** 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); // Leak pList when malloc fails */ return 0; } pNew->op = TK_FUNCTION; pNew->pList = pList; if( pToken ){ assert( pToken->dyn==0 ); pNew->token = *pToken; }else{ pNew->token.z = 0; } pNew->span = pNew->token; return pNew;}/*** Recursively delete an expression tree.*/void sqliteExprDelete(Expr *p){ if( p==0 ) return; if( p->span.dyn ) sqliteFree((char*)p->span.z); if( p->token.dyn ) sqliteFree((char*)p->token.z); sqliteExprDelete(p->pLeft); sqliteExprDelete(p->pRight); sqliteExprListDelete(p->pList); 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 = sqliteStrNDup(p->token.z, p->token.n); pNew->token.dyn = 1; }else{ assert( pNew->token.z==0 ); } pNew->span.z = 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->z = 0; }}ExprList *sqliteExprListDup(ExprList *p){ ExprList *pNew; struct ExprList_item *pItem; int i; if( p==0 ) return 0; pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nExpr = pNew->nAlloc = p->nExpr; pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) ); if( pItem==0 ){ sqliteFree(pNew); return 0; } for(i=0; i<p->nExpr; i++, pItem++){ Expr *pNewExpr, *pOldExpr; pItem->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 ); pItem->zName = sqliteStrDup(p->a[i].zName); pItem->sortOrder = p->a[i].sortOrder; pItem->isAgg = p->a[i].isAgg; pItem->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 = sqliteMallocRaw( nByte ); if( pNew==0 ) return 0; pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; i<p->nSrc; i++){ struct SrcList_item *pNewItem = &pNew->a[i]; struct SrcList_item *pOldItem = &p->a[i]; pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase); pNewItem->zName = sqliteStrDup(pOldItem->zName); pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; pNewItem->pTab = 0; pNewItem->pSelect = sqliteSelectDup(pOldItem->pSelect); pNewItem->pOn = sqliteExprDup(pOldItem->pOn); pNewItem->pUsing = sqliteIdListDup(pOldItem->pUsing); } return pNew;}IdList *sqliteIdListDup(IdList *p){ IdList *pNew; int i; if( p==0 ) return 0; pNew = sqliteMallocRaw( sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nId = pNew->nAlloc = p->nId; pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) ); if( pNew->a==0 ) return 0; for(i=0; i<p->nId; i++){ struct IdList_item *pNewItem = &pNew->a[i]; struct IdList_item *pOldItem = &p->a[i]; pNewItem->zName = sqliteStrDup(pOldItem->zName); pNewItem->idx = pOldItem->idx; } return pNew;}Select *sqliteSelectDup(Select *p){ Select *pNew; if( p==0 ) return 0; pNew = sqliteMallocRaw( 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){ if( pList==0 ){ pList = sqliteMalloc( sizeof(ExprList) ); if( pList==0 ){ /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */ return 0; } assert( pList->nAlloc==0 ); } if( pList->nAlloc<=pList->nExpr ){ pList->nAlloc = pList->nAlloc*2 + 4; pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0])); if( pList->a==0 ){ /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */ pList->nExpr = pList->nAlloc = 0; return pList; } } assert( pList->a!=0 ); if( pExpr || pName ){ struct ExprList_item *pItem = &pList->a[pList->nExpr++]; memset(pItem, 0, sizeof(*pItem)); pItem->pExpr = pExpr; if( pName ){ sqliteSetNString(&pItem->zName, pName->z, pName->n, 0); sqliteDequote(pItem->zName); } } return pList;}/*** Delete an entire expression list.*/void sqliteExprListDelete(ExprList *pList){ int i; if( pList==0 ) return; assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) ); assert( pList->nExpr<=pList->nAlloc ); 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: case TK_VARIABLE: 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 that is small enough** to fit in a 32-bit integer, return 1 and put the value of the integer** in *pValue. If the expression is not an integer or if it is too big** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.*/int sqliteExprIsInteger(Expr *p, int *pValue){ switch( p->op ){ case TK_INTEGER: { if( sqliteFitsIn32Bits(p->token.z) ){ *pValue = atoi(p->token.z); return 1; } break; } 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 && sqliteFitsIn32Bits(p->token.z) ){ *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;}/*** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up** that name in the set of source tables in pSrcList and make the pExpr ** expression node refer back to that source column. The following changes** are made to pExpr:**** pExpr->iDb Set the index in db->aDb[] of the database holding** the table.** pExpr->iTable Set to the cursor number for the table obtained** from pSrcList.** pExpr->iColumn Set to the column number within the table.** pExpr->dataType Set to the appropriate data type for the column.** pExpr->op Set to TK_COLUMN.** 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** 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** means that the form of the name is Z and that columns from any table** can be used.**** If the name cannot be resolved unambiguously, leave an error message** in pParse and return non-zero. Return zero on success.*/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. */ SrcList *pSrcList, /* List of tables used to resolve column names */ ExprList *pEList, /* List of expressions used to resolve "AS" */ Expr *pExpr /* Make this EXPR node point to the selected column */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -