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

📄 expr.c

📁 一个小型嵌入式数据库SQLite的源码,C语言
💻 C
📖 第 1 页 / 共 5 页
字号:
      assert( TK_RSHIFT==OP_ShiftRight );      assert( TK_CONCAT==OP_Concat );      sqlite3ExprCode(pParse, pExpr->pLeft);      sqlite3ExprCode(pParse, pExpr->pRight);      sqlite3VdbeAddOp(v, op, 0, 0);      stackChng = -1;      break;    }    case TK_UMINUS: {      Expr *pLeft = pExpr->pLeft;      assert( pLeft );      if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){        Token *p = &pLeft->token;        char *z = sqlite3MPrintf("-%.*s", p->n, p->z);        if( pLeft->op==TK_FLOAT ){          sqlite3VdbeOp3(v, OP_Real, 0, 0, z, p->n+1);        }else{          codeInteger(v, z, p->n+1);        }        sqliteFree(z);        break;      }      /* Fall through into TK_NOT */    }    case TK_BITNOT:    case TK_NOT: {      assert( TK_BITNOT==OP_BitNot );      assert( TK_NOT==OP_Not );      sqlite3ExprCode(pParse, pExpr->pLeft);      sqlite3VdbeAddOp(v, op, 0, 0);      stackChng = 0;      break;    }    case TK_ISNULL:    case TK_NOTNULL: {      int dest;      assert( TK_ISNULL==OP_IsNull );      assert( TK_NOTNULL==OP_NotNull );      sqlite3VdbeAddOp(v, OP_Integer, 1, 0);      sqlite3ExprCode(pParse, pExpr->pLeft);      dest = sqlite3VdbeCurrentAddr(v) + 2;      sqlite3VdbeAddOp(v, op, 1, dest);      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);      stackChng = 0;      break;    }    case TK_AGG_FUNCTION: {      AggInfo *pInfo = pExpr->pAggInfo;      if( pInfo==0 ){        sqlite3ErrorMsg(pParse, "misuse of aggregate: %T",            &pExpr->span);      }else{        sqlite3VdbeAddOp(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem, 0);      }      break;    }    case TK_CONST_FUNC:    case TK_FUNCTION: {      ExprList *pList = pExpr->pList;      int nExpr = pList ? pList->nExpr : 0;      FuncDef *pDef;      int nId;      const char *zId;      int constMask = 0;      int i;      u8 enc = ENC(pParse->db);      CollSeq *pColl = 0;      zId = (char*)pExpr->token.z;      nId = pExpr->token.n;      pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);      assert( pDef!=0 );      nExpr = sqlite3ExprCodeExprList(pParse, pList);#ifndef SQLITE_OMIT_VIRTUALTABLE      /* Possibly overload the function if the first argument is      ** a virtual table column.      **      ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the      ** second argument, not the first, as the argument to test to      ** see if it is a column in a virtual table.  This is done because      ** the left operand of infix functions (the operand we want to      ** control overloading) ends up as the second argument to the      ** function.  The expression "A glob B" is equivalent to       ** "glob(B,A).  We want to use the A in "A glob B" to test      ** for function overloading.  But we use the B term in "glob(B,A)".      */      if( nExpr>=2 && (pExpr->flags & EP_InfixFunc) ){        pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[1].pExpr);      }else if( nExpr>0 ){        pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[0].pExpr);      }#endif      for(i=0; i<nExpr && i<32; i++){        if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){          constMask |= (1<<i);        }        if( pDef->needCollSeq && !pColl ){          pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);        }      }      if( pDef->needCollSeq ){        if( !pColl ) pColl = pParse->db->pDfltColl;         sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ);      }      sqlite3VdbeOp3(v, OP_Function, constMask, nExpr, (char*)pDef, P3_FUNCDEF);      stackChng = 1-nExpr;      break;    }#ifndef SQLITE_OMIT_SUBQUERY    case TK_EXISTS:    case TK_SELECT: {      if( pExpr->iColumn==0 ){        sqlite3CodeSubselect(pParse, pExpr);      }      sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0);      VdbeComment((v, "# load subquery result"));      break;    }    case TK_IN: {      int addr;      char affinity;      int ckOffset = pParse->ckOffset;      sqlite3CodeSubselect(pParse, pExpr);      /* Figure out the affinity to use to create a key from the results      ** of the expression. affinityStr stores a static string suitable for      ** P3 of OP_MakeRecord.      */      affinity = comparisonAffinity(pExpr);      sqlite3VdbeAddOp(v, OP_Integer, 1, 0);      pParse->ckOffset = ckOffset+1;      /* Code the <expr> from "<expr> IN (...)". The temporary table      ** pExpr->iTable contains the values that make up the (...) set.      */      sqlite3ExprCode(pParse, pExpr->pLeft);      addr = sqlite3VdbeCurrentAddr(v);      sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4);            /* addr + 0 */      sqlite3VdbeAddOp(v, OP_Pop, 2, 0);      sqlite3VdbeAddOp(v, OP_Null, 0, 0);      sqlite3VdbeAddOp(v, OP_Goto, 0, addr+7);      sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1);   /* addr + 4 */      sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7);      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);                  /* addr + 6 */      break;    }#endif    case TK_BETWEEN: {      Expr *pLeft = pExpr->pLeft;      struct ExprList_item *pLItem = pExpr->pList->a;      Expr *pRight = pLItem->pExpr;      sqlite3ExprCode(pParse, pLeft);      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);      sqlite3ExprCode(pParse, pRight);      codeCompare(pParse, pLeft, pRight, OP_Ge, 0, 0);      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);      pLItem++;      pRight = pLItem->pExpr;      sqlite3ExprCode(pParse, pRight);      codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0);      sqlite3VdbeAddOp(v, OP_And, 0, 0);      break;    }    case TK_UPLUS:    case TK_AS: {      sqlite3ExprCode(pParse, pExpr->pLeft);      stackChng = 0;      break;    }    case TK_CASE: {      int expr_end_label;      int jumpInst;      int nExpr;      int i;      ExprList *pEList;      struct ExprList_item *aListelem;      assert(pExpr->pList);      assert((pExpr->pList->nExpr % 2) == 0);      assert(pExpr->pList->nExpr > 0);      pEList = pExpr->pList;      aListelem = pEList->a;      nExpr = pEList->nExpr;      expr_end_label = sqlite3VdbeMakeLabel(v);      if( pExpr->pLeft ){        sqlite3ExprCode(pParse, pExpr->pLeft);      }      for(i=0; i<nExpr; i=i+2){        sqlite3ExprCode(pParse, aListelem[i].pExpr);        if( pExpr->pLeft ){          sqlite3VdbeAddOp(v, OP_Dup, 1, 1);          jumpInst = codeCompare(pParse, pExpr->pLeft, aListelem[i].pExpr,                                 OP_Ne, 0, 1);          sqlite3VdbeAddOp(v, OP_Pop, 1, 0);        }else{          jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0);        }        sqlite3ExprCode(pParse, aListelem[i+1].pExpr);        sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label);        sqlite3VdbeJumpHere(v, jumpInst);      }      if( pExpr->pLeft ){        sqlite3VdbeAddOp(v, OP_Pop, 1, 0);      }      if( pExpr->pRight ){        sqlite3ExprCode(pParse, pExpr->pRight);      }else{        sqlite3VdbeAddOp(v, OP_Null, 0, 0);      }      sqlite3VdbeResolveLabel(v, expr_end_label);      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 );         sqlite3DequoteExpr(pExpr);         sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,                        (char*)pExpr->token.z, pExpr->token.n);      } else {         assert( pExpr->iColumn == OE_Ignore );         sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);         sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump);         VdbeComment((v, "# raise(IGNORE)"));      }      stackChng = 0;      break;    }#endif  }  if( pParse->ckOffset ){    pParse->ckOffset += stackChng;    assert( pParse->ckOffset );  }}#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;  if( pList==0 ) return 0;  n = pList->nExpr;  for(pItem=pList->a, i=n; i>0; 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;  int ckOffset = pParse->ckOffset;  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);      sqlite3VdbeJumpHere(v, addr);      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);      break;    }    default: {      sqlite3ExprCode(pParse, pExpr);      sqlite3VdbeAddOp(v, OP_If, jumpIfNull, dest);      break;    }  }  pParse->ckOffset = ckOffset;}/*** 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;  int ckOffset = pParse->ckOffset;  if( v==0 || pExpr==0 ) return;  /* The value of pExpr->op and op are related as follows:  **  **       pExpr->op            op  **       ---------          ----------  *

⌨️ 快捷键说明

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