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

📄 expr.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
      break;    }#ifndef SQLITE_OMIT_TRIGGER    case TK_RAISE: {      if( !pParse->trigStack ){        sqlite3ErrorMsg(pParse,                       "RAISE() may only be used within a trigger-program");	return;      }      if( pExpr->iColumn!=OE_Ignore ){         assert( pExpr->iColumn==OE_Rollback ||                 pExpr->iColumn == OE_Abort ||                 pExpr->iColumn == OE_Fail );         sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,                        pExpr->token.z, pExpr->token.n);         sqlite3VdbeDequoteP3(v, -1);      } else {         assert( pExpr->iColumn == OE_Ignore );         sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);         sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump);         VdbeComment((v, "# raise(IGNORE)"));      }    }#endif    break;  }}#ifndef SQLITE_OMIT_TRIGGER/*** Generate code that evalutes the given expression and leaves the result** on the stack.  See also sqlite3ExprCode().**** This routine might also cache the result and modify the pExpr tree** so that it will make use of the cached result on subsequent evaluations** rather than evaluate the whole expression again.  Trivial expressions are** not cached.  If the expression is cached, its result is stored in a ** memory location.*/void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){  Vdbe *v = pParse->pVdbe;  int iMem;  int addr1, addr2;  if( v==0 ) return;  addr1 = sqlite3VdbeCurrentAddr(v);  sqlite3ExprCode(pParse, pExpr);  addr2 = sqlite3VdbeCurrentAddr(v);  if( addr2>addr1+1 || sqlite3VdbeGetOp(v, addr1)->opcode==OP_Function ){    iMem = pExpr->iTable = pParse->nMem++;    sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0);    pExpr->op = TK_REGISTER;  }}#endif/*** Generate code that pushes the value of every element of the given** expression list onto the stack.**** Return the number of elements pushed onto the stack.*/int sqlite3ExprCodeExprList(  Parse *pParse,     /* Parsing context */  ExprList *pList    /* The expression list to be coded */){  struct ExprList_item *pItem;  int i, n;  Vdbe *v;  if( pList==0 ) return 0;  v = sqlite3GetVdbe(pParse);  n = pList->nExpr;  for(pItem=pList->a, i=0; i<n; i++, pItem++){    sqlite3ExprCode(pParse, pItem->pExpr);  }  return n;}/*** Generate code for a boolean expression such that a jump is made** to the label "dest" if the expression is true but execution** continues straight thru if the expression is false.**** If the expression evaluates to NULL (neither true nor false), then** take the jump if the jumpIfNull flag is true.**** This code depends on the fact that certain token values (ex: TK_EQ)** are the same as opcode values (ex: OP_Eq) that implement the corresponding** operation.  Special comments in vdbe.c and the mkopcodeh.awk script in** the make process cause these values to align.  Assert()s in the code** below verify that the numbers are aligned correctly.*/void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){  Vdbe *v = pParse->pVdbe;  int op = 0;  if( v==0 || pExpr==0 ) return;  op = pExpr->op;  switch( op ){    case TK_AND: {      int d2 = sqlite3VdbeMakeLabel(v);      sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull);      sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);      sqlite3VdbeResolveLabel(v, d2);      break;    }    case TK_OR: {      sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);      sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);      break;    }    case TK_NOT: {      sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);      break;    }    case TK_LT:    case TK_LE:    case TK_GT:    case TK_GE:    case TK_NE:    case TK_EQ: {      assert( TK_LT==OP_Lt );      assert( TK_LE==OP_Le );      assert( TK_GT==OP_Gt );      assert( TK_GE==OP_Ge );      assert( TK_EQ==OP_Eq );      assert( TK_NE==OP_Ne );      sqlite3ExprCode(pParse, pExpr->pLeft);      sqlite3ExprCode(pParse, pExpr->pRight);      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull);      break;    }    case TK_ISNULL:    case TK_NOTNULL: {      assert( TK_ISNULL==OP_IsNull );      assert( TK_NOTNULL==OP_NotNull );      sqlite3ExprCode(pParse, pExpr->pLeft);      sqlite3VdbeAddOp(v, op, 1, dest);      break;    }    case TK_BETWEEN: {      /* The expression "x BETWEEN y AND z" is implemented as:      **      ** 1 IF (x < y) GOTO 3      ** 2 IF (x <= z) GOTO <dest>      ** 3 ...      */      int addr;      Expr *pLeft = pExpr->pLeft;      Expr *pRight = pExpr->pList->a[0].pExpr;      sqlite3ExprCode(pParse, pLeft);      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);      sqlite3ExprCode(pParse, pRight);      addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull);      pRight = pExpr->pList->a[1].pExpr;      sqlite3ExprCode(pParse, pRight);      codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull);      sqlite3VdbeAddOp(v, OP_Integer, 0, 0);      sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);      break;    }    default: {      sqlite3ExprCode(pParse, pExpr);      sqlite3VdbeAddOp(v, OP_If, jumpIfNull, dest);      break;    }  }}/*** Generate code for a boolean expression such that a jump is made** to the label "dest" if the expression is false but execution** continues straight thru if the expression is true.**** If the expression evaluates to NULL (neither true nor false) then** jump if jumpIfNull is true or fall through if jumpIfNull is false.*/void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){  Vdbe *v = pParse->pVdbe;  int op = 0;  if( v==0 || pExpr==0 ) return;  /* The value of pExpr->op and op are related as follows:  **  **       pExpr->op            op  **       ---------          ----------  **       TK_ISNULL          OP_NotNull  **       TK_NOTNULL         OP_IsNull  **       TK_NE              OP_Eq  **       TK_EQ              OP_Ne  **       TK_GT              OP_Le  **       TK_LE              OP_Gt  **       TK_GE              OP_Lt  **       TK_LT              OP_Ge  **  ** For other values of pExpr->op, op is undefined and unused.  ** The value of TK_ and OP_ constants are arranged such that we  ** can compute the mapping above using the following expression.  ** Assert()s verify that the computation is correct.  */  op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1);  /* Verify correct alignment of TK_ and OP_ constants  */  assert( pExpr->op!=TK_ISNULL || op==OP_NotNull );  assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull );  assert( pExpr->op!=TK_NE || op==OP_Eq );  assert( pExpr->op!=TK_EQ || op==OP_Ne );  assert( pExpr->op!=TK_LT || op==OP_Ge );  assert( pExpr->op!=TK_LE || op==OP_Gt );  assert( pExpr->op!=TK_GT || op==OP_Le );  assert( pExpr->op!=TK_GE || op==OP_Lt );  switch( pExpr->op ){    case TK_AND: {      sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);      sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);      break;    }    case TK_OR: {      int d2 = sqlite3VdbeMakeLabel(v);      sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull);      sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);      sqlite3VdbeResolveLabel(v, d2);      break;    }    case TK_NOT: {      sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);      break;    }    case TK_LT:    case TK_LE:    case TK_GT:    case TK_GE:    case TK_NE:    case TK_EQ: {      sqlite3ExprCode(pParse, pExpr->pLeft);      sqlite3ExprCode(pParse, pExpr->pRight);      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull);      break;    }    case TK_ISNULL:    case TK_NOTNULL: {      sqlite3ExprCode(pParse, pExpr->pLeft);      sqlite3VdbeAddOp(v, op, 1, dest);      break;    }    case TK_BETWEEN: {      /* The expression is "x BETWEEN y AND z". It is implemented as:      **      ** 1 IF (x >= y) GOTO 3      ** 2 GOTO <dest>      ** 3 IF (x > z) GOTO <dest>      */      int addr;      Expr *pLeft = pExpr->pLeft;      Expr *pRight = pExpr->pList->a[0].pExpr;      sqlite3ExprCode(pParse, pLeft);      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);      sqlite3ExprCode(pParse, pRight);      addr = sqlite3VdbeCurrentAddr(v);      codeCompare(pParse, pLeft, pRight, OP_Ge, addr+3, !jumpIfNull);      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);      sqlite3VdbeAddOp(v, OP_Goto, 0, dest);      pRight = pExpr->pList->a[1].pExpr;      sqlite3ExprCode(pParse, pRight);      codeCompare(pParse, pLeft, pRight, OP_Gt, dest, jumpIfNull);      break;    }    default: {      sqlite3ExprCode(pParse, pExpr);      sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest);      break;    }  }}/*** Do a deep comparison of two expression trees.  Return TRUE (non-zero)** if they are identical and return FALSE if they differ in any way.*/int sqlite3ExprCompare(Expr *pA, Expr *pB){  int i;  if( pA==0 ){    return pB==0;  }else if( pB==0 ){    return 0;  }  if( pA->op!=pB->op ) return 0;  if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0;  if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0;  if( pA->pList ){    if( pB->pList==0 ) return 0;    if( pA->pList->nExpr!=pB->pList->nExpr ) return 0;    for(i=0; i<pA->pList->nExpr; i++){      if( !sqlite3ExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){        return 0;      }    }  }else if( pB->pList ){    return 0;  }  if( pA->pSelect || pB->pSelect ) return 0;  if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;  if( pA->token.z ){    if( pB->token.z==0 ) return 0;    if( pB->token.n!=pA->token.n ) return 0;    if( sqlite3StrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0;  }  return 1;}/*** Add a new element to the pParse->aAgg[] array and return its index.** The new element is initialized to zero.  The calling function is** expected to fill it in.*/static int appendAggInfo(Parse *pParse){  if( (pParse->nAgg & 0x7)==0 ){    int amt = pParse->nAgg + 8;    AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0]));    if( aAgg==0 ){      return -1;    }    pParse->aAgg = aAgg;  }  memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0]));  return pParse->nAgg++;}/*** This is an xFunc for walkExprTree() used to implement ** sqlite3ExprAnalyzeAggregates().  See sqlite3ExprAnalyzeAggregates** for additional information.**** This routine analyzes the aggregate function at pExpr.*/static int analyzeAggregate(void *pArg, Expr *pExpr){  int i;  AggExpr *aAgg;  NameContext *pNC = (NameContext *)pArg;  Parse *pParse = pNC->pParse;  SrcList *pSrcList = pNC->pSrcList;  switch( pExpr->op ){    case TK_COLUMN: {      for(i=0; pSrcList && i<pSrcList->nSrc; i++){        if( pExpr->iTable==pSrcList->a[i].iCursor ){          aAgg = pParse->aAgg;          for(i=0; i<pParse->nAgg; i++){            if( aAgg[i].isAgg ) continue;            if( aAgg[i].pExpr->iTable==pExpr->iTable             && aAgg[i].pExpr->iColumn==pExpr->iColumn ){              break;            }          }          if( i>=pParse->nAgg ){            i = appendAggInfo(pParse);            if( i<0 ) return 1;            pParse->aAgg[i].isAgg = 0;            pParse->aAgg[i].pExpr = pExpr;          }          pExpr->iAgg = i;          pExpr->iAggCtx = pNC->nDepth;          return 1;        }      }      return 1;    }    case TK_AGG_FUNCTION: {      if( pNC->nDepth==0 ){        aAgg = pParse->aAgg;        for(i=0; i<pParse->nAgg; i++){          if( !aAgg[i].isAgg ) continue;          if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){            break;          }        }        if( i>=pParse->nAgg ){          u8 enc = pParse->db->enc;          i = appendAggInfo(pParse);          if( i<0 ) return 1;          pParse->aAgg[i].isAgg = 1;          pParse->aAgg[i].pExpr = pExpr;          pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db,               pExpr->token.z, pExpr->token.n,               pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0);        }        pExpr->iAgg = i;        return 1;      }    }  }  if( pExpr->pSelect ){    pNC->nDepth++;    walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC);    pNC->nDepth--;  }  return 0;}/*** Analyze the given expression looking for aggregate functions and** for variables that need to be added to the pParse->aAgg[] array.** Make additional entries to the pParse->aAgg[] array as necessary.**** This routine should only be called after the expression has been** analyzed by sqlite3ExprResolveNames().**

⌨️ 快捷键说明

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