📄 expr.c
字号:
int sqliteExprResolveIds( Parse *pParse, /* The parser context */ SrcList *pTabList, /* List of tables used to resolve column names */ ExprList *pEList, /* List of expressions used to resolve "AS" */ Expr *pExpr /* The expression to be analyzed. */){ int i; if( pExpr==0 || pTabList==0 ) return 0; for(i=0; i<pTabList->nSrc; i++){ assert( pTabList->a[i].iCursor>=0 && pTabList->a[i].iCursor<pParse->nTab ); } 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. Try and match it as follows: ** ** 1. To the name of a column of one of the tables in pTabList ** ** 2. To the right side of an AS keyword in the column list of ** a SELECT statement. (For example, match against 'x' in ** "SELECT a+b AS 'x' FROM t1".) ** ** 3. One of the special names "ROWID", "OID", or "_ROWID_". */ case TK_ID: { int cnt = 0; /* Number of matches */ char *z; int iDb = -1; assert( pExpr->token.z ); z = sqliteStrNDup(pExpr->token.z, pExpr->token.n); sqliteDequote(z); if( z==0 ) return 1; for(i=0; i<pTabList->nSrc; i++){ int j; Table *pTab = pTabList->a[i].pTab; if( pTab==0 ) continue; iDb = pTab->iDb; assert( pTab->nCol>0 ); for(j=0; j<pTab->nCol; j++){ if( sqliteStrICmp(pTab->aCol[j].zName, z)==0 ){ cnt++; pExpr->iTable = pTabList->a[i].iCursor; pExpr->iDb = pTab->iDb; if( j==pTab->iPKey ){ /* Substitute the record number for the INTEGER PRIMARY KEY */ pExpr->iColumn = -1; pExpr->dataType = SQLITE_SO_NUM; }else{ pExpr->iColumn = j; pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK; } pExpr->op = TK_COLUMN; } } } if( cnt==0 && pEList!=0 ){ int j; for(j=0; j<pEList->nExpr; j++){ char *zAs = pEList->a[j].zName; if( zAs!=0 && sqliteStrICmp(zAs, z)==0 ){ cnt++; assert( pExpr->pLeft==0 && pExpr->pRight==0 ); pExpr->op = TK_AS; pExpr->iColumn = j; pExpr->pLeft = sqliteExprDup(pEList->a[j].pExpr); } } } if( cnt==0 && iDb>=0 && sqliteIsRowid(z) ){ pExpr->iColumn = -1; pExpr->iTable = pTabList->a[0].iCursor; pExpr->iDb = iDb; cnt = 1 + (pTabList->nSrc>1); pExpr->op = TK_COLUMN; pExpr->dataType = SQLITE_SO_NUM; } sqliteFree(z); if( cnt==0 && pExpr->token.z[0]!='"' ){ sqliteErrorMsg(pParse, "no such column: %T", &pExpr->token); return 1; }else if( cnt>1 ){ sqliteErrorMsg(pParse, "ambiguous column name: %T", &pExpr->token); return 1; } if( pExpr->op==TK_COLUMN ){ sqliteAuthRead(pParse, pExpr, pTabList); } break; } /* A table name and column name: ID.ID ** Or a database, table and column: ID.ID.ID */ case TK_DOT: { int cnt = 0; /* Number of matches */ int cntTab = 0; /* Number of matching tables */ int i; /* Loop counter */ Expr *pLeft, *pRight; /* Left and right subbranches of the expr */ char *zLeft, *zRight; /* Text of an identifier */ char *zDb; /* Name of database holding table */ sqlite *db = pParse->db; pRight = pExpr->pRight; if( pRight->op==TK_ID ){ pLeft = pExpr->pLeft; zDb = 0; }else{ Expr *pDb = pExpr->pLeft; assert( pDb && pDb->op==TK_ID && pDb->token.z ); zDb = sqliteStrNDup(pDb->token.z, pDb->token.n); pLeft = pRight->pLeft; pRight = pRight->pRight; } assert( pLeft && pLeft->op==TK_ID && pLeft->token.z ); assert( pRight && pRight->op==TK_ID && pRight->token.z ); zLeft = sqliteStrNDup(pLeft->token.z, pLeft->token.n); zRight = sqliteStrNDup(pRight->token.z, pRight->token.n); if( zLeft==0 || zRight==0 ){ sqliteFree(zLeft); sqliteFree(zRight); sqliteFree(zDb); return 1; } sqliteDequote(zDb); sqliteDequote(zLeft); sqliteDequote(zRight); pExpr->iTable = -1; for(i=0; i<pTabList->nSrc; i++){ int j; char *zTab; Table *pTab = pTabList->a[i].pTab; if( pTab==0 ) continue; assert( pTab->nCol>0 ); if( pTabList->a[i].zAlias ){ zTab = pTabList->a[i].zAlias; if( sqliteStrICmp(zTab, zLeft)!=0 ) continue; }else{ zTab = pTab->zName; if( zTab==0 || sqliteStrICmp(zTab, zLeft)!=0 ) continue; if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){ continue; } } if( 0==(cntTab++) ){ pExpr->iTable = pTabList->a[i].iCursor; pExpr->iDb = pTab->iDb; } for(j=0; j<pTab->nCol; j++){ if( sqliteStrICmp(pTab->aCol[j].zName, zRight)==0 ){ cnt++; pExpr->iTable = pTabList->a[i].iCursor; pExpr->iDb = pTab->iDb; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK; } } } /* If we have not already resolved this *.* expression, then maybe * it is a new.* or old.* trigger argument reference */ if( cnt == 0 && pParse->trigStack != 0 ){ TriggerStack *pTriggerStack = pParse->trigStack; int t = 0; if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zLeft) == 0 ){ pExpr->iTable = pTriggerStack->newIdx; assert( pTriggerStack->pTab ); pExpr->iDb = pTriggerStack->pTab->iDb; cntTab++; t = 1; } if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zLeft) == 0 ){ pExpr->iTable = pTriggerStack->oldIdx; assert( pTriggerStack->pTab ); pExpr->iDb = pTriggerStack->pTab->iDb; cntTab++; t = 1; } if( t ){ int j; Table *pTab = pTriggerStack->pTab; for(j=0; j < pTab->nCol; j++) { if( sqliteStrICmp(pTab->aCol[j].zName, zRight)==0 ){ cnt++; pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK; } } } } if( cnt==0 && cntTab==1 && sqliteIsRowid(zRight) ){ cnt = 1; pExpr->iColumn = -1; pExpr->dataType = SQLITE_SO_NUM; } sqliteFree(zDb); sqliteFree(zLeft); sqliteFree(zRight); if( cnt==0 ){ sqliteErrorMsg(pParse, "no such column: %T.%T", &pLeft->token, &pRight->token); return 1; }else if( cnt>1 ){ sqliteErrorMsg(pParse, "ambiguous column name: %T.%T", &pLeft->token, &pRight->token); return 1; } sqliteExprDelete(pExpr->pLeft); pExpr->pLeft = 0; sqliteExprDelete(pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; sqliteAuthRead(pParse, pExpr, pTabList); break; } case TK_IN: { Vdbe *v = sqliteGetVdbe(pParse); if( v==0 ) return 1; if( sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pLeft) ){ return 1; } if( pExpr->pSelect ){ /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into a temporary ** table. The cursor number of the temporary table has already ** been put in iTable by sqliteExprResolveInSelect(). */ pExpr->iTable = pParse->nTab++; sqliteVdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1); sqliteSelect(pParse, pExpr->pSelect, SRT_Set, pExpr->iTable, 0,0,0); }else if( pExpr->pList ){ /* Case 2: expr IN (exprlist) ** ** Create a set to put the exprlist values in. The Set id is stored ** in iTable. */ int i, iSet; for(i=0; i<pExpr->pList->nExpr; i++){ Expr *pE2 = pExpr->pList->a[i].pExpr; if( !sqliteExprIsConstant(pE2) ){ sqliteErrorMsg(pParse, "right-hand side of IN operator must be constant"); return 1; } if( sqliteExprCheck(pParse, pE2, 0, 0) ){ return 1; } } iSet = pExpr->iTable = pParse->nSet++; for(i=0; i<pExpr->pList->nExpr; i++){ Expr *pE2 = pExpr->pList->a[i].pExpr; switch( pE2->op ){ case TK_FLOAT: case TK_INTEGER: case TK_STRING: { int addr = sqliteVdbeAddOp(v, OP_SetInsert, iSet, 0); assert( pE2->token.z ); sqliteVdbeChangeP3(v, addr, pE2->token.z, pE2->token.n); sqliteVdbeDequoteP3(v, addr); break; } default: { sqliteExprCode(pParse, pE2); sqliteVdbeAddOp(v, OP_SetInsert, iSet, 0); break; } } } } break; } case TK_SELECT: { /* This has to be a scalar SELECT. Generate code to put the ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ pExpr->iColumn = pParse->nMem++; if( sqliteSelect(pParse, pExpr->pSelect, SRT_Mem, pExpr->iColumn,0,0,0) ){ return 1; } break; } /* For all else, just recursively walk the tree */ default: { if( pExpr->pLeft && sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pLeft) ){ return 1; } if( pExpr->pRight && sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pRight) ){ return 1; } if( pExpr->pList ){ int i; ExprList *pList = pExpr->pList; for(i=0; i<pList->nExpr; i++){ Expr *pArg = pList->a[i].pExpr; if( sqliteExprResolveIds(pParse, pTabList, pEList, pArg) ){ return 1; } } } } } return 0;}/*** pExpr is a node that defines a function of some kind. It might** be a syntactic function like "count(x)" or it might be a function** that implements an operator, like "a LIKE b". **** This routine makes *pzName point to the name of the function and ** *pnName hold the number of characters in the function name.*/static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){ switch( pExpr->op ){ case TK_FUNCTION: { *pzName = pExpr->token.z; *pnName = pExpr->token.n; break; } case TK_LIKE: { *pzName = "like"; *pnName = 4; break; } case TK_GLOB: { *pzName = "glob"; *pnName = 4; break; } default: { *pzName = "can't happen"; *pnName = 12; break; } }}/*** Error check the functions in an expression. 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 pIsAgg is not null and this expression is an aggregate function** (like count(*) or max(value)) then write a 1 into *pIsAgg.*/int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){ int nErr = 0; if( pExpr==0 ) return 0; switch( pExpr->op ){ case TK_GLOB: case TK_LIKE: case TK_FUNCTION: { int n = pExpr->pList ? pExpr->pList->nExpr : 0; /* Number of arguments */ int no_such_func = 0; /* True if no such function exists */ int is_type_of = 0; /* True if is the special TypeOf() function */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ int i; int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; getFunctionName(pExpr, &zId, &nId); pDef = sqliteFindFunction(pParse->db, zId, nId, n, 0); if( pDef==0 ){ pDef = sqliteFindFunction(pParse->db, zId, nId, -1, 0); if( pDef==0 ){ if( n==1 && nId==6 && sqliteStrNICmp(zId, "typeof", 6)==0 ){ is_type_of = 1; }else { no_such_func = 1; } }else{ wrong_num_args = 1; } }else{ is_agg = pDef->xFunc==0; } if( is_agg && !allowAgg ){ sqliteSetNString(&pParse->zErrMsg, "misuse of aggregate function ", -1, zId, nId, "()", 2, 0); pParse->nErr++; nErr++; is_agg = 0; }else if( no_such_func ){ sqliteSetNString(&pParse->zErrMsg, "no such function: ", -1, zId,nId,0); pParse->nErr++; nErr++; }else if( wrong_num_args ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -