📄 expr.c
字号:
if( cnt!=1 ){ char *z = 0; char *zErr; zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s"; if( zDb ){ sqlite3SetString(&z, zDb, ".", zTab, ".", zCol, (char*)0); }else if( zTab ){ sqlite3SetString(&z, zTab, ".", zCol, (char*)0); }else{ z = sqlite3StrDup(zCol); } if( z ){ sqlite3ErrorMsg(pParse, zErr, z); sqlite3_free(z); pTopNC->nErr++; }else{ db->mallocFailed = 1; } } /* If a column from a table in pSrcList is referenced, then record ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the ** column number is greater than the number of bits in the bitmask ** then set the high-order bit of the bitmask. */ if( pExpr->iColumn>=0 && pMatch!=0 ){ int n = pExpr->iColumn; if( n>=sizeof(Bitmask)*8 ){ n = sizeof(Bitmask)*8-1; } assert( pMatch->iCursor==pExpr->iTable ); pMatch->colUsed |= ((Bitmask)1)<<n; }lookupname_end: /* Clean up and return */ sqlite3_free(zDb); sqlite3_free(zTab); sqlite3ExprDelete(pExpr->pLeft); pExpr->pLeft = 0; sqlite3ExprDelete(pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN;lookupname_end_2: sqlite3_free(zCol); if( cnt==1 ){ assert( pNC!=0 ); sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); if( pMatch && !pMatch->pSelect ){ pExpr->pTab = pMatch->pTab; } /* Increment the nRef value on all name contexts from TopNC up to ** the point where the name matched. */ for(;;){ assert( pTopNC!=0 ); pTopNC->nRef++; if( pTopNC==pNC ) break; pTopNC = pTopNC->pNext; } return 0; } else { return 1; }}/*** This routine is designed as an xFunc for walkExprTree().**** Resolve symbolic names into TK_COLUMN operators for the current** node in the expression tree. Return 0 to continue the search down** the tree or 2 to abort the tree walk.**** This routine also does error checking and name resolution for** function names. The operator for aggregate functions is changed** to TK_AGG_FUNCTION.*/static int nameResolverStep(void *pArg, Expr *pExpr){ NameContext *pNC = (NameContext*)pArg; Parse *pParse; if( pExpr==0 ) return 1; assert( pNC!=0 ); pParse = pNC->pParse; if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1; ExprSetProperty(pExpr, EP_Resolved);#ifndef NDEBUG if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ SrcList *pSrcList = pNC->pSrcList; int i; for(i=0; i<pNC->pSrcList->nSrc; i++){ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab); } }#endif switch( pExpr->op ){ /* Double-quoted strings (ex: "abc") are used as identifiers if ** possible. Otherwise they remain as strings. Single-quoted ** strings (ex: 'abc') are always string literals. */ case TK_STRING: { if( pExpr->token.z[0]=='\'' ) break; /* Fall thru into the TK_ID case if this is a double-quoted string */ } /* A lone identifier is the name of a column. */ case TK_ID: { lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr); return 1; } /* A table name and column name: ID.ID ** Or a database, table and column: ID.ID.ID */ case TK_DOT: { Token *pColumn; Token *pTable; Token *pDb; Expr *pRight; /* if( pSrcList==0 ) break; */ pRight = pExpr->pRight; if( pRight->op==TK_ID ){ pDb = 0; pTable = &pExpr->pLeft->token; pColumn = &pRight->token; }else{ assert( pRight->op==TK_DOT ); pDb = &pExpr->pLeft->token; pTable = &pRight->pLeft->token; pColumn = &pRight->pRight->token; } lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr); return 1; } /* Resolve function names */ case TK_CONST_FUNC: case TK_FUNCTION: { ExprList *pList = pExpr->pList; /* The argument list */ int n = pList ? pList->nExpr : 0; /* Number of arguments */ int no_such_func = 0; /* True if no such function exists */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ int i; int auth; /* Authorization to use the function */ int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ int enc = ENC(pParse->db); /* The database encoding */ zId = (char*)pExpr->token.z; nId = pExpr->token.n; pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); if( pDef==0 ){ no_such_func = 1; }else{ wrong_num_args = 1; } }else{ is_agg = pDef->xFunc==0; }#ifndef SQLITE_OMIT_AUTHORIZATION if( pDef ){ auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); if( auth!=SQLITE_OK ){ if( auth==SQLITE_DENY ){ sqlite3ErrorMsg(pParse, "not authorized to use function: %s", pDef->zName); pNC->nErr++; } pExpr->op = TK_NULL; return 1; } }#endif if( is_agg && !pNC->allowAgg ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); pNC->nErr++; is_agg = 0; }else if( no_such_func ){ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); pNC->nErr++; }else if( wrong_num_args ){ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", nId, zId); pNC->nErr++; } if( is_agg ){ pExpr->op = TK_AGG_FUNCTION; pNC->hasAgg = 1; } if( is_agg ) pNC->allowAgg = 0; for(i=0; pNC->nErr==0 && i<n; i++){ walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC); } if( is_agg ) pNC->allowAgg = 1; /* FIX ME: Compute pExpr->affinity based on the expected return ** type of the function */ return is_agg; }#ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: case TK_EXISTS:#endif case TK_IN: { if( pExpr->pSelect ){ int nRef = pNC->nRef;#ifndef SQLITE_OMIT_CHECK if( pNC->isCheck ){ sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints"); }#endif sqlite3SelectResolve(pParse, pExpr->pSelect, pNC); assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); } } break; }#ifndef SQLITE_OMIT_CHECK case TK_VARIABLE: { if( pNC->isCheck ){ sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints"); } break; }#endif } return 0;}/*** This routine walks an expression tree and resolves references to** table columns. Nodes of the form ID.ID or ID resolve into an** index to the table in the table list and a column offset. The ** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable** value is changed to the index of the referenced table in pTabList** plus the "base" value. The base value will ultimately become the** VDBE cursor number for a cursor that is pointing into the referenced** table. The Expr.iColumn value is changed to the index of the column ** of the referenced table. The Expr.iColumn value for the special** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an** alias for ROWID.**** Also resolve function names and check the functions for proper** usage. Make sure all function names are recognized and all functions** have the correct number of arguments. Leave an error message** in pParse->zErrMsg if anything is amiss. Return the number of errors.**** If the expression contains aggregate functions then set the EP_Agg** property on the expression.*/int sqlite3ExprResolveNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */){ int savedHasAgg; if( pExpr==0 ) return 0;#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 if( (pExpr->nHeight+pNC->pParse->nHeight)>SQLITE_MAX_EXPR_DEPTH ){ sqlite3ErrorMsg(pNC->pParse, "Expression tree is too large (maximum depth %d)", SQLITE_MAX_EXPR_DEPTH ); return 1; } pNC->pParse->nHeight += pExpr->nHeight;#endif savedHasAgg = pNC->hasAgg; pNC->hasAgg = 0; walkExprTree(pExpr, nameResolverStep, pNC);#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 pNC->pParse->nHeight -= pExpr->nHeight;#endif if( pNC->nErr>0 ){ ExprSetProperty(pExpr, EP_Error); } if( pNC->hasAgg ){ ExprSetProperty(pExpr, EP_Agg); }else if( savedHasAgg ){ pNC->hasAgg = 1; } return ExprHasProperty(pExpr, EP_Error);}/*** A pointer instance of this structure is used to pass information** through walkExprTree into codeSubqueryStep().*/typedef struct QueryCoder QueryCoder;struct QueryCoder { Parse *pParse; /* The parsing context */ NameContext *pNC; /* Namespace of first enclosing query */};#ifdef SQLITE_TEST int sqlite3_enable_in_opt = 1;#else #define sqlite3_enable_in_opt 1#endif/*** 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 indec.** 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 the mustBeUnique parameter is false, 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.**** If mustBeUnique is true, 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.*/#ifndef SQLITE_OMIT_SUBQUERYint sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){ Select *p; int eType = 0; int iTab = pParse->nTab++; /* 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. */ if( sqlite3_enable_in_opt && (p=pX->pSelect) && !p->pPrior && !p->isDistinct && !p->isAgg && !p->pGroupBy && p->pSrc && p->pSrc->nSrc==1 && !p->pSrc->a[0].pSelect && !p->pSrc->a[0].pTab->pSelect && p->pEList->nExpr==1 && p->pEList->a[0].pExpr->op==TK_COLUMN && !p->pLimit && !p->pOffset && !p->pWhere ){ 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); sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0); iAddr = sqlite3VdbeAddOp(v, OP_If, 0, iMem); sqlite3VdbeAddOp(v, OP_MemInt, 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))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -