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

📄 expr.c

📁 sqlite数据库管理系统开放源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	  sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,                           pExpr->token.z, pExpr->token.n);	  sqliteVdbeDequoteP3(v, -1);      } else {	  assert( pExpr->iColumn == OE_Ignore );	  sqliteVdbeOp3(v, OP_Goto, 0, pParse->trigStack->ignoreJump,                           "(IGNORE jump)", 0);      }    }    break;  }}/*** Generate code that pushes the value of every element of the given** expression list onto the stack.  If the includeTypes flag is true,** then also push a string that is the datatype of each element onto** the stack after the value.**** Return the number of elements pushed onto the stack.*/int sqliteExprCodeExprList(  Parse *pParse,     /* Parsing context */  ExprList *pList,   /* The expression list to be coded */  int includeTypes   /* TRUE to put datatypes on the stack too */){  struct ExprList_item *pItem;  int i, n;  Vdbe *v;  if( pList==0 ) return 0;  v = sqliteGetVdbe(pParse);  n = pList->nExpr;  for(pItem=pList->a, i=0; i<n; i++, pItem++){    sqliteExprCode(pParse, pItem->pExpr);    if( includeTypes ){      sqliteVdbeOp3(v, OP_String, 0, 0,          sqliteExprType(pItem->pExpr)==SQLITE_SO_NUM ? "numeric" : "text",         P3_STATIC);    }  }  return includeTypes ? n*2 : 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.*/void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){  Vdbe *v = pParse->pVdbe;  int op = 0;  if( v==0 || pExpr==0 ) return;  switch( pExpr->op ){    case TK_LT:       op = OP_Lt;       break;    case TK_LE:       op = OP_Le;       break;    case TK_GT:       op = OP_Gt;       break;    case TK_GE:       op = OP_Ge;       break;    case TK_NE:       op = OP_Ne;       break;    case TK_EQ:       op = OP_Eq;       break;    case TK_ISNULL:   op = OP_IsNull;   break;    case TK_NOTNULL:  op = OP_NotNull;  break;    default:  break;  }  switch( pExpr->op ){    case TK_AND: {      int d2 = sqliteVdbeMakeLabel(v);      sqliteExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull);      sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);      sqliteVdbeResolveLabel(v, d2);      break;    }    case TK_OR: {      sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);      sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);      break;    }    case TK_NOT: {      sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);      break;    }    case TK_LT:    case TK_LE:    case TK_GT:    case TK_GE:    case TK_NE:    case TK_EQ: {      sqliteExprCode(pParse, pExpr->pLeft);      sqliteExprCode(pParse, pExpr->pRight);      if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){        op += 6;  /* Convert numeric opcodes to text opcodes */      }      sqliteVdbeAddOp(v, op, jumpIfNull, dest);      break;    }    case TK_ISNULL:    case TK_NOTNULL: {      sqliteExprCode(pParse, pExpr->pLeft);      sqliteVdbeAddOp(v, op, 1, dest);      break;    }    case TK_IN: {      int addr;      sqliteExprCode(pParse, pExpr->pLeft);      addr = sqliteVdbeCurrentAddr(v);      sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3);      sqliteVdbeAddOp(v, OP_Pop, 1, 0);      sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4);      if( pExpr->pSelect ){        sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, dest);      }else{        sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, dest);      }      break;    }    case TK_BETWEEN: {      int addr;      sqliteExprCode(pParse, pExpr->pLeft);      sqliteVdbeAddOp(v, OP_Dup, 0, 0);      sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);      addr = sqliteVdbeAddOp(v, OP_Lt, !jumpIfNull, 0);      sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);      sqliteVdbeAddOp(v, OP_Le, jumpIfNull, dest);      sqliteVdbeAddOp(v, OP_Integer, 0, 0);      sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));      sqliteVdbeAddOp(v, OP_Pop, 1, 0);      break;    }    default: {      sqliteExprCode(pParse, pExpr);      sqliteVdbeAddOp(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 sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){  Vdbe *v = pParse->pVdbe;  int op = 0;  if( v==0 || pExpr==0 ) return;  switch( pExpr->op ){    case TK_LT:       op = OP_Ge;       break;    case TK_LE:       op = OP_Gt;       break;    case TK_GT:       op = OP_Le;       break;    case TK_GE:       op = OP_Lt;       break;    case TK_NE:       op = OP_Eq;       break;    case TK_EQ:       op = OP_Ne;       break;    case TK_ISNULL:   op = OP_NotNull;  break;    case TK_NOTNULL:  op = OP_IsNull;   break;    default:  break;  }  switch( pExpr->op ){    case TK_AND: {      sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);      sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);      break;    }    case TK_OR: {      int d2 = sqliteVdbeMakeLabel(v);      sqliteExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull);      sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);      sqliteVdbeResolveLabel(v, d2);      break;    }    case TK_NOT: {      sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);      break;    }    case TK_LT:    case TK_LE:    case TK_GT:    case TK_GE:    case TK_NE:    case TK_EQ: {      if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){        /* Convert numeric comparison opcodes into text comparison opcodes.        ** This step depends on the fact that the text comparision opcodes are        ** always 6 greater than their corresponding numeric comparison        ** opcodes.        */        assert( OP_Eq+6 == OP_StrEq );        op += 6;      }      sqliteExprCode(pParse, pExpr->pLeft);      sqliteExprCode(pParse, pExpr->pRight);      sqliteVdbeAddOp(v, op, jumpIfNull, dest);      break;    }    case TK_ISNULL:    case TK_NOTNULL: {      sqliteExprCode(pParse, pExpr->pLeft);      sqliteVdbeAddOp(v, op, 1, dest);      break;    }    case TK_IN: {      int addr;      sqliteExprCode(pParse, pExpr->pLeft);      addr = sqliteVdbeCurrentAddr(v);      sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3);      sqliteVdbeAddOp(v, OP_Pop, 1, 0);      sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4);      if( pExpr->pSelect ){        sqliteVdbeAddOp(v, OP_NotFound, pExpr->iTable, dest);      }else{        sqliteVdbeAddOp(v, OP_SetNotFound, pExpr->iTable, dest);      }      break;    }    case TK_BETWEEN: {      int addr;      sqliteExprCode(pParse, pExpr->pLeft);      sqliteVdbeAddOp(v, OP_Dup, 0, 0);      sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);      addr = sqliteVdbeCurrentAddr(v);      sqliteVdbeAddOp(v, OP_Ge, !jumpIfNull, addr+3);      sqliteVdbeAddOp(v, OP_Pop, 1, 0);      sqliteVdbeAddOp(v, OP_Goto, 0, dest);      sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);      sqliteVdbeAddOp(v, OP_Gt, jumpIfNull, dest);      break;    }    default: {      sqliteExprCode(pParse, pExpr);      sqliteVdbeAddOp(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 sqliteExprCompare(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( !sqliteExprCompare(pA->pLeft, pB->pLeft) ) return 0;  if( !sqliteExprCompare(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( !sqliteExprCompare(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( sqliteStrNICmp(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.*/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++;}/*** 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 sqliteExprResolveIds() and sqliteExprCheck().**** If errors are seen, leave an error message in zErrMsg and return** the number of errors.*/int sqliteExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){  int i;  AggExpr *aAgg;  int nErr = 0;  if( pExpr==0 ) return 0;  switch( pExpr->op ){    case TK_COLUMN: {      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;      break;    }    case TK_AGG_FUNCTION: {      aAgg = pParse->aAgg;      for(i=0; i<pParse->nAgg; i++){        if( !aAgg[i].isAgg ) continue;        if( sqliteExprCompare(aAgg[i].pExpr, pExpr) ){          break;        }      }      if( i>=pParse->nAgg ){        i = appendAggInfo(pParse);        if( i<0 ) return 1;        pParse->aAgg[i].isAgg = 1;        pParse->aAgg[i].pExpr = pExpr;        pParse->aAgg[i].pFunc = sqliteFindFunction(pParse->db,             pExpr->token.z, pExpr->token.n,             pExpr->pList ? pExpr->pList->nExpr : 0, 0);      }      pExpr->iAgg = i;      break;    }    default: {      if( pExpr->pLeft ){        nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft);      }      if( nErr==0 && pExpr->pRight ){        nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pRight);      }      if( nErr==0 && pExpr->pList ){        int n = pExpr->pList->nExpr;        int i;        for(i=0; nErr==0 && i<n; i++){          nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pList->a[i].pExpr);        }      }      break;    }  }  return nErr;}/*** Locate a user function given a name and a number of arguments.** Return a pointer to the FuncDef structure that defines that** function, or return NULL if the function does not exist.**** If the createFlag argument is true, then a new (blank) FuncDef** structure is created and liked into the "db" structure if a** no matching function previously existed.  When createFlag is true** and the nArg parameter is -1, then only a function that accepts** any number of arguments will be returned.**** If createFlag is false and nArg is -1, then the first valid** function found is returned.  A function is valid if either xFunc** or xStep is non-zero.*/FuncDef *sqliteFindFunction(  sqlite *db,        /* An open database */  const char *zName, /* Name of the function.  Not null-terminated */  int nName,         /* Number of characters in the name */  int nArg,          /* Number of arguments.  -1 means any number */  int createFlag     /* Create new entry if true and does not otherwise exist */){  FuncDef *pFirst, *p, *pMaybe;  pFirst = p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, nName);  if( p && !createFlag && nArg<0 ){    while( p && p->xFunc==0 && p->xStep==0 ){ p = p->pNext; }    return p;  }  pMaybe = 0;  while( p && p->nArg!=nArg ){    if( p->nArg<0 && !createFlag && (p->xFunc || p->xStep) ) pMaybe = p;    p = p->pNext;  }  if( p && !createFlag && p->xFunc==0 && p->xStep==0 ){    return 0;  }  if( p==0 && pMaybe ){    assert( createFlag==0 );    return pMaybe;  }  if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){    p->nArg = nArg;    p->pNext = pFirst;    p->dataType = pFirst ? pFirst->dataType : SQLITE_NUMERIC;    sqliteHashInsert(&db->aFunc, zName, nName, (void*)p);  }  return p;}

⌨️ 快捷键说明

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