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

📄 expr.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  if( pList->nAlloc<=pList->nExpr ){    struct ExprList_item *a;    int n = pList->nAlloc*2 + 4;    a = sqlite3DbRealloc(db, pList->a, n*sizeof(pList->a[0]));    if( a==0 ){      goto no_mem;    }    pList->a = a;    pList->nAlloc = n;  }  assert( pList->a!=0 );  if( pExpr || pName ){    struct ExprList_item *pItem = &pList->a[pList->nExpr++];    memset(pItem, 0, sizeof(*pItem));    pItem->zName = sqlite3NameFromToken(db, pName);    pItem->pExpr = pExpr;    pItem->iAlias = 0;  }  return pList;no_mem:       /* Avoid leaking memory if malloc has failed. */  sqlite3ExprDelete(db, pExpr);  sqlite3ExprListDelete(db, pList);  return 0;}/*** If the expression list pEList contains more than iLimit elements,** leave an error message in pParse.*/void sqlite3ExprListCheckLength(  Parse *pParse,  ExprList *pEList,  const char *zObject){  int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];  testcase( pEList && pEList->nExpr==mx );  testcase( pEList && pEList->nExpr==mx+1 );  if( pEList && pEList->nExpr>mx ){    sqlite3ErrorMsg(pParse, "too many columns in %s", zObject);  }}/*** Delete an entire expression list.*/void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){  int i;  struct ExprList_item *pItem;  if( pList==0 ) return;  assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );  assert( pList->nExpr<=pList->nAlloc );  for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){    sqlite3ExprDelete(db, pItem->pExpr);    sqlite3DbFree(db, pItem->zName);  }  sqlite3DbFree(db, pList->a);  sqlite3DbFree(db, pList);}/*** These routines are Walker callbacks.  Walker.u.pi is a pointer** to an integer.  These routines are checking an expression to see** if it is a constant.  Set *Walker.u.pi to 0 if the expression is** not constant.**** These callback routines are used to implement the following:****     sqlite3ExprIsConstant()**     sqlite3ExprIsConstantNotJoin()**     sqlite3ExprIsConstantOrFunction()***/static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){  /* If pWalker->u.i is 3 then any term of the expression that comes from  ** the ON or USING clauses of a join disqualifies the expression  ** from being considered constant. */  if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){    pWalker->u.i = 0;    return WRC_Abort;  }  switch( pExpr->op ){    /* Consider functions to be constant if all their arguments are constant    ** and pWalker->u.i==2 */    case TK_FUNCTION:      if( pWalker->u.i==2 ) return 0;      /* Fall through */    case TK_ID:    case TK_COLUMN:    case TK_DOT:    case TK_AGG_FUNCTION:    case TK_AGG_COLUMN:#ifndef SQLITE_OMIT_SUBQUERY    case TK_SELECT:    case TK_EXISTS:      testcase( pExpr->op==TK_SELECT );      testcase( pExpr->op==TK_EXISTS );#endif      testcase( pExpr->op==TK_ID );      testcase( pExpr->op==TK_COLUMN );      testcase( pExpr->op==TK_DOT );      testcase( pExpr->op==TK_AGG_FUNCTION );      testcase( pExpr->op==TK_AGG_COLUMN );      pWalker->u.i = 0;      return WRC_Abort;    default:      return WRC_Continue;  }}static int selectNodeIsConstant(Walker *pWalker, Select *pSelect){  pWalker->u.i = 0;  return WRC_Abort;}static int exprIsConst(Expr *p, int initFlag){  Walker w;  w.u.i = initFlag;  w.xExprCallback = exprNodeIsConstant;  w.xSelectCallback = selectNodeIsConstant;  sqlite3WalkExpr(&w, p);  return w.u.i;}/*** Walk an expression tree.  Return 1 if the expression is constant** and 0 if it involves variables or function calls.**** 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 sqlite3ExprIsConstant(Expr *p){  return exprIsConst(p, 1);}/*** Walk an expression tree.  Return 1 if the expression is constant** that does no originate from the ON or USING clauses of a join.** Return 0 if it involves variables or function calls or terms from** an ON or USING clause.*/int sqlite3ExprIsConstantNotJoin(Expr *p){  return exprIsConst(p, 3);}/*** Walk an expression tree.  Return 1 if the expression is constant** or a function call with constant arguments.  Return and 0 if there** are any 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 sqlite3ExprIsConstantOrFunction(Expr *p){  return exprIsConst(p, 2);}/*** If the expression p codes a constant integer that is small enough** to fit in a 32-bit integer, return 1 and put the value of the integer** in *pValue.  If the expression is not an integer or if it is too big** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.*/int sqlite3ExprIsInteger(Expr *p, int *pValue){  int rc = 0;  if( p->flags & EP_IntValue ){    *pValue = p->iTable;    return 1;  }  switch( p->op ){    case TK_INTEGER: {      rc = sqlite3GetInt32((char*)p->token.z, pValue);      break;    }    case TK_UPLUS: {      rc = sqlite3ExprIsInteger(p->pLeft, pValue);      break;    }    case TK_UMINUS: {      int v;      if( sqlite3ExprIsInteger(p->pLeft, &v) ){        *pValue = -v;        rc = 1;      }      break;    }    default: break;  }  if( rc ){    p->op = TK_INTEGER;    p->flags |= EP_IntValue;    p->iTable = *pValue;  }  return rc;}/*** Return TRUE if the given string is a row-id column name.*/int sqlite3IsRowid(const char *z){  if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1;  if( sqlite3StrICmp(z, "ROWID")==0 ) return 1;  if( sqlite3StrICmp(z, "OID")==0 ) return 1;  return 0;}#ifdef SQLITE_TEST  int sqlite3_enable_in_opt = 1;#else  #define sqlite3_enable_in_opt 1#endif/*** Return true if the IN operator optimization is enabled and** the SELECT statement p exists and is of the** simple form:****     SELECT <column> FROM <table>**** If this is the case, it may be possible to use an existing table** or index instead of generating an epheremal table.*/#ifndef SQLITE_OMIT_SUBQUERYstatic int isCandidateForInOpt(Select *p){  SrcList *pSrc;  ExprList *pEList;  Table *pTab;  if( !sqlite3_enable_in_opt ) return 0; /* IN optimization must be enabled */  if( p==0 ) return 0;                   /* right-hand side of IN is SELECT */  if( p->pPrior ) return 0;              /* Not a compound SELECT */  if( p->selFlags & (SF_Distinct|SF_Aggregate) ){      return 0; /* No DISTINCT keyword and no aggregate functions */  }  if( p->pGroupBy ) return 0;            /* Has no GROUP BY clause */  if( p->pLimit ) return 0;              /* Has no LIMIT clause */  if( p->pOffset ) return 0;  if( p->pWhere ) return 0;              /* Has no WHERE clause */  pSrc = p->pSrc;  if( pSrc==0 ) return 0;                /* A single table in the FROM clause */  if( pSrc->nSrc!=1 ) return 0;  if( pSrc->a[0].pSelect ) return 0;     /* FROM clause is not a subquery */  pTab = pSrc->a[0].pTab;  if( pTab==0 ) return 0;  if( pTab->pSelect ) return 0;          /* FROM clause is not a view */  if( IsVirtual(pTab) ) return 0;        /* FROM clause not a virtual table */  pEList = p->pEList;  if( pEList->nExpr!=1 ) return 0;       /* One column in the result set */  if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */  return 1;}#endif /* SQLITE_OMIT_SUBQUERY *//*** This function is used by the implementation of the IN (...) operator.** It's job is to find or create a b-tree structure that may be used** either to test for membership of the (...) set or to iterate through** its members, skipping duplicates.**** The cursor opened on the structure (database table, database index ** or ephermal table) is stored in pX->iTable before this function returns.** The returned value indicates the structure type, as follows:****   IN_INDEX_ROWID - The cursor was opened on a database table.**   IN_INDEX_INDEX - The cursor was opened on a database index.**   IN_INDEX_EPH -   The cursor was opened on a specially created and**                    populated epheremal table.**** An existing structure may only be used if the SELECT is of the simple** form:****     SELECT <column> FROM <table>**** If prNotFound parameter is 0, then the structure will be used to iterate** through the set members, skipping any duplicates. In this case an** epheremal table must be used unless the selected <column> is guaranteed** to be unique - either because it is an INTEGER PRIMARY KEY or it** is unique by virtue of a constraint or implicit index.**** If the prNotFound parameter is not 0, then the structure will be used ** for fast set membership tests. In this case an epheremal table must ** be used unless <column> is an INTEGER PRIMARY KEY or an index can ** be found with <column> as its left-most column.**** When the structure is being used for set membership tests, the user** needs to know whether or not the structure contains an SQL NULL ** value in order to correctly evaluate expressions like "X IN (Y, Z)".** If there is a chance that the structure may contain a NULL value at** runtime, then a register is allocated and the register number written** to *prNotFound. If there is no chance that the structure contains a** NULL value, then *prNotFound is left unchanged.**** If a register is allocated and its location stored in *prNotFound, then** its initial value is NULL. If the structure does not remain constant** for the duration of the query (i.e. the set is a correlated sub-select), ** the value of the allocated register is reset to NULL each time the ** structure is repopulated. This allows the caller to use vdbe code ** equivalent to the following:****   if( register==NULL ){**     has_null = <test if data structure contains null>**     register = 1**   }**** in order to avoid running the <test if data structure contains null>** test more often than is necessary.*/#ifndef SQLITE_OMIT_SUBQUERYint sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){  Select *p;  int eType = 0;  int iTab = pParse->nTab++;  int mustBeUnique = !prNotFound;  /* The follwing if(...) expression is true if the SELECT is of the   ** simple form:  **  **     SELECT <column> FROM <table>  **  ** If this is the case, it may be possible to use an existing table  ** or index instead of generating an epheremal table.  */  p = pX->pSelect;  if( isCandidateForInOpt(p) ){    sqlite3 *db = pParse->db;    Index *pIdx;    Expr *pExpr = p->pEList->a[0].pExpr;    int iCol = pExpr->iColumn;    Vdbe *v = sqlite3GetVdbe(pParse);    /* This function is only called from two places. In both cases the vdbe    ** has already been allocated. So assume sqlite3GetVdbe() is always    ** successful here.    */    assert(v);    if( iCol<0 ){      int iMem = ++pParse->nMem;      int iAddr;      Table *pTab = p->pSrc->a[0].pTab;      int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);      sqlite3VdbeUsesBtree(v, iDb);      iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);      sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);      sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);      eType = IN_INDEX_ROWID;      sqlite3VdbeJumpHere(v, iAddr);    }else{      /* The collation sequence used by the comparison. If an index is to       ** be used in place of a temp-table, it must be ordered according      ** to this collation sequence.      */      CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr);      /* Check that the affinity that will be used to perform the       ** comparison is the same as the affinity of the column. If      ** it is not, it is not possible to use any index.      */      Table *pTab = p->pSrc->a[0].pTab;      char aff = comparisonAffinity(pX);      int affinity_ok = (pTab->aCol[iCol].affinity==aff||aff==SQLITE_AFF_NONE);      for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){        if( (pIdx->aiColumn[0]==iCol)         && (pReq==sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], -1, 0))         && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))        ){          int iDb;          int iMem = ++pParse->nMem;          int iAddr;          char *pKey;            pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);          iDb = sqlite3SchemaToIndex(db, pIdx->pSchema);          sqlite3VdbeUsesBtree(v, iDb);          iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);          sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);            sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIdx->nColumn);          sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,                               pKey,P4_KEYINFO_HANDOFF);          VdbeComment((v, "%s", pIdx->zName));          eType = IN_INDEX_INDEX;          sqlite3VdbeJumpHere(v, iAddr);          if( prNotFound && !pTab->aCol[iCol].notNull ){            *prNotFound = ++pParse->nMem;          }        }      }    }  }  if( eType==0 ){    int rMayHaveNull = 0;    if( prNotFound ){      *prNotFound = rMayHaveNull = ++pParse->nMem;    }    sqlite3CodeSubselect(pParse, pX, rMayHaveNull);    eType = IN_INDEX_EPH;  }else{    pX->iTable = iTab;  }

⌨️ 快捷键说明

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