⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expr.c

📁 sqlite数据库管理系统开放源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*** 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 + -