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

📄 expr.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*** 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.392 2008/08/29 02:14:03 drh Exp $*/#include "sqliteInt.h"#include <ctype.h>/*** Return the 'affinity' of the expression pExpr if any.**** If pExpr is a column, a reference to a column via an 'AS' alias,** or a sub-select with a column as the return value, then the ** affinity of that column is returned. Otherwise, 0x00 is returned,** indicating no affinity for the expression.**** i.e. the WHERE clause expresssions in the following statements all** have an affinity:**** CREATE TABLE t1(a);** SELECT * FROM t1 WHERE a;** SELECT a AS b FROM t1 WHERE b;** SELECT * FROM t1 WHERE (select a from t1);*/char sqlite3ExprAffinity(Expr *pExpr){  int op = pExpr->op;  if( op==TK_SELECT ){    return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr);  }#ifndef SQLITE_OMIT_CAST  if( op==TK_CAST ){    return sqlite3AffinityType(&pExpr->token);  }#endif  if( (op==TK_COLUMN || op==TK_REGISTER) && pExpr->pTab!=0 ){    /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally    ** a TK_COLUMN but was previously evaluated and cached in a register */    int j = pExpr->iColumn;    if( j<0 ) return SQLITE_AFF_INTEGER;    assert( pExpr->pTab && j<pExpr->pTab->nCol );    return pExpr->pTab->aCol[j].affinity;  }  return pExpr->affinity;}/*** Set the collating sequence for expression pExpr to be the collating** sequence named by pToken.   Return a pointer to the revised expression.** The collating sequence is marked as "explicit" using the EP_ExpCollate** flag.  An explicit collating sequence will override implicit** collating sequences.*/Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pCollName){  char *zColl = 0;            /* Dequoted name of collation sequence */  CollSeq *pColl;  sqlite3 *db = pParse->db;  zColl = sqlite3NameFromToken(db, pCollName);  if( pExpr && zColl ){    pColl = sqlite3LocateCollSeq(pParse, zColl, -1);    if( pColl ){      pExpr->pColl = pColl;      pExpr->flags |= EP_ExpCollate;    }  }  sqlite3DbFree(db, zColl);  return pExpr;}/*** Return the default collation sequence for the expression pExpr. If** there is no default collation type, return 0.*/CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){  CollSeq *pColl = 0;  Expr *p = pExpr;  while( p ){    int op;    pColl = p->pColl;    if( pColl ) break;    op = p->op;    if( (op==TK_COLUMN || op==TK_REGISTER) && p->pTab!=0 ){      /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally      ** a TK_COLUMN but was previously evaluated and cached in a register */      const char *zColl;      int j = p->iColumn;      if( j>=0 ){        sqlite3 *db = pParse->db;        zColl = p->pTab->aCol[j].zColl;        pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0);        pExpr->pColl = pColl;      }      break;    }    if( op!=TK_CAST && op!=TK_UPLUS ){      break;    }    p = p->pLeft;  }  if( sqlite3CheckCollSeq(pParse, pColl) ){     pColl = 0;  }  return pColl;}/*** pExpr is an operand of a comparison operator.  aff2 is the** type affinity of the other operand.  This routine returns the** type affinity that should be used for the comparison operator.*/char sqlite3CompareAffinity(Expr *pExpr, char aff2){  char aff1 = sqlite3ExprAffinity(pExpr);  if( aff1 && aff2 ){    /* Both sides of the comparison are columns. If one has numeric    ** affinity, use that. Otherwise use no affinity.    */    if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){      return SQLITE_AFF_NUMERIC;    }else{      return SQLITE_AFF_NONE;    }  }else if( !aff1 && !aff2 ){    /* Neither side of the comparison is a column.  Compare the    ** results directly.    */    return SQLITE_AFF_NONE;  }else{    /* One side is a column, the other is not. Use the columns affinity. */    assert( aff1==0 || aff2==0 );    return (aff1 + aff2);  }}/*** pExpr is a comparison operator.  Return the type affinity that should** be applied to both operands prior to doing the comparison.*/static char comparisonAffinity(Expr *pExpr){  char aff;  assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||          pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||          pExpr->op==TK_NE );  assert( pExpr->pLeft );  aff = sqlite3ExprAffinity(pExpr->pLeft);  if( pExpr->pRight ){    aff = sqlite3CompareAffinity(pExpr->pRight, aff);  }  else if( pExpr->pSelect ){    aff = sqlite3CompareAffinity(pExpr->pSelect->pEList->a[0].pExpr, aff);  }  else if( !aff ){    aff = SQLITE_AFF_NONE;  }  return aff;}/*** pExpr is a comparison expression, eg. '=', '<', IN(...) etc.** idx_affinity is the affinity of an indexed column. Return true** if the index with affinity idx_affinity may be used to implement** the comparison in pExpr.*/int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){  char aff = comparisonAffinity(pExpr);  switch( aff ){    case SQLITE_AFF_NONE:      return 1;    case SQLITE_AFF_TEXT:      return idx_affinity==SQLITE_AFF_TEXT;    default:      return sqlite3IsNumericAffinity(idx_affinity);  }}/*** Return the P5 value that should be used for a binary comparison** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.*/static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){  u8 aff = (char)sqlite3ExprAffinity(pExpr2);  aff = sqlite3CompareAffinity(pExpr1, aff) | jumpIfNull;  return aff;}/*** Return a pointer to the collation sequence that should be used by** a binary comparison operator comparing pLeft and pRight.**** If the left hand expression has a collating sequence type, then it is** used. Otherwise the collation sequence for the right hand expression** is used, or the default (BINARY) if neither expression has a collating** type.**** Argument pRight (but not pLeft) may be a null pointer. In this case,** it is not considered.*/CollSeq *sqlite3BinaryCompareCollSeq(  Parse *pParse,   Expr *pLeft,   Expr *pRight){  CollSeq *pColl;  assert( pLeft );  if( pLeft->flags & EP_ExpCollate ){    assert( pLeft->pColl );    pColl = pLeft->pColl;  }else if( pRight && pRight->flags & EP_ExpCollate ){    assert( pRight->pColl );    pColl = pRight->pColl;  }else{    pColl = sqlite3ExprCollSeq(pParse, pLeft);    if( !pColl ){      pColl = sqlite3ExprCollSeq(pParse, pRight);    }  }  return pColl;}/*** Generate the operands for a comparison operation.  Before** generating the code for each operand, set the EP_AnyAff** flag on the expression so that it will be able to used a** cached column value that has previously undergone an** affinity change.*/static void codeCompareOperands(  Parse *pParse,    /* Parsing and code generating context */  Expr *pLeft,      /* The left operand */  int *pRegLeft,    /* Register where left operand is stored */  int *pFreeLeft,   /* Free this register when done */  Expr *pRight,     /* The right operand */  int *pRegRight,   /* Register where right operand is stored */  int *pFreeRight   /* Write temp register for right operand there */){  while( pLeft->op==TK_UPLUS ) pLeft = pLeft->pLeft;  pLeft->flags |= EP_AnyAff;  *pRegLeft = sqlite3ExprCodeTemp(pParse, pLeft, pFreeLeft);  while( pRight->op==TK_UPLUS ) pRight = pRight->pLeft;  pRight->flags |= EP_AnyAff;  *pRegRight = sqlite3ExprCodeTemp(pParse, pRight, pFreeRight);}/*** Generate code for a comparison operator.*/static int codeCompare(  Parse *pParse,    /* The parsing (and code generating) context */  Expr *pLeft,      /* The left operand */  Expr *pRight,     /* The right operand */  int opcode,       /* The comparison opcode */  int in1, int in2, /* Register holding operands */  int dest,         /* Jump here if true.  */  int jumpIfNull    /* If true, jump if either operand is NULL */){  int p5;  int addr;  CollSeq *p4;  p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);  p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);  addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,                           (void*)p4, P4_COLLSEQ);  sqlite3VdbeChangeP5(pParse->pVdbe, p5);  if( (p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_NONE ){    sqlite3ExprCacheAffinityChange(pParse, in1, 1);    sqlite3ExprCacheAffinityChange(pParse, in2, 1);  }  return addr;}#if SQLITE_MAX_EXPR_DEPTH>0/*** Check that argument nHeight is less than or equal to the maximum** expression depth allowed. If it is not, leave an error message in** pParse.*/int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){  int rc = SQLITE_OK;  int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];  if( nHeight>mxHeight ){    sqlite3ErrorMsg(pParse,        "Expression tree is too large (maximum depth %d)", mxHeight    );    rc = SQLITE_ERROR;  }  return rc;}/* The following three functions, heightOfExpr(), heightOfExprList()** and heightOfSelect(), are used to determine the maximum height** of any expression tree referenced by the structure passed as the** first argument.**** If this maximum height is greater than the current value pointed** to by pnHeight, the second parameter, then set *pnHeight to that** value.*/static void heightOfExpr(Expr *p, int *pnHeight){  if( p ){    if( p->nHeight>*pnHeight ){      *pnHeight = p->nHeight;    }  }}static void heightOfExprList(ExprList *p, int *pnHeight){  if( p ){    int i;    for(i=0; i<p->nExpr; i++){      heightOfExpr(p->a[i].pExpr, pnHeight);    }  }}static void heightOfSelect(Select *p, int *pnHeight){  if( p ){    heightOfExpr(p->pWhere, pnHeight);    heightOfExpr(p->pHaving, pnHeight);    heightOfExpr(p->pLimit, pnHeight);    heightOfExpr(p->pOffset, pnHeight);    heightOfExprList(p->pEList, pnHeight);    heightOfExprList(p->pGroupBy, pnHeight);    heightOfExprList(p->pOrderBy, pnHeight);    heightOfSelect(p->pPrior, pnHeight);  }}/*** Set the Expr.nHeight variable in the structure passed as an ** argument. An expression with no children, Expr.pList or ** Expr.pSelect member has a height of 1. Any other expression** has a height equal to the maximum height of any other ** referenced Expr plus one.*/static void exprSetHeight(Expr *p){  int nHeight = 0;  heightOfExpr(p->pLeft, &nHeight);  heightOfExpr(p->pRight, &nHeight);  heightOfExprList(p->pList, &nHeight);  heightOfSelect(p->pSelect, &nHeight);  p->nHeight = nHeight + 1;}/*** Set the Expr.nHeight variable using the exprSetHeight() function. If** the height is greater than the maximum allowed expression depth,** leave an error in pParse.*/void sqlite3ExprSetHeight(Parse *pParse, Expr *p){  exprSetHeight(p);  sqlite3ExprCheckHeight(pParse, p->nHeight);}/*** Return the maximum height of any expression tree referenced** by the select statement passed as an argument.*/int sqlite3SelectExprHeight(Select *p){  int nHeight = 0;  heightOfSelect(p, &nHeight);  return nHeight;}#else  #define exprSetHeight(y)#endif /* SQLITE_MAX_EXPR_DEPTH>0 *//*** Construct a new expression node and return a pointer to it.  Memory** for this node is obtained from sqlite3_malloc().  The calling function** is responsible for making sure the node eventually gets freed.*/Expr *sqlite3Expr(  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 */){  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 = op;  pNew->pLeft = pLeft;  pNew->pRight = pRight;  pNew->iAgg = -1;  pNew->span.z = (u8*)"";  if( pToken ){    assert( pToken->dyn==0 );    pNew->span = pNew->token = *pToken;  }else if( pLeft ){    if( pRight ){      if( pRight->span.dyn==0 && pLeft->span.dyn==0 ){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -