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

📄 expr.c

📁 SQLite 2.8.6 源代码,用来在Linux/Unix/Windows上编译安装.它是一个小型的数据库,但是非常好用,速度也快,一般的数据库查询之类的操作据统计比MySQL,PostgreSQL
💻 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.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 + -