📄 expr.c
字号:
){ char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */ char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */ char *zCol = 0; /* Name of the column. The "Z" */ int i, j; /* Loop counters */ int cnt = 0; /* Number of matching column names */ int cntTab = 0; /* Number of matching table names */ sqlite *db = pParse->db; /* The database */ assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ if( pDbToken && pDbToken->z ){ zDb = sqliteStrNDup(pDbToken->z, pDbToken->n); sqliteDequote(zDb); }else{ zDb = 0; } if( pTableToken && pTableToken->z ){ zTab = sqliteStrNDup(pTableToken->z, pTableToken->n); sqliteDequote(zTab); }else{ assert( zDb==0 ); zTab = 0; } zCol = sqliteStrNDup(pColumnToken->z, pColumnToken->n); sqliteDequote(zCol); if( sqlite_malloc_failed ){ return 1; /* Leak memory (zDb and zTab) if malloc fails */ } assert( zTab==0 || pEList==0 ); pExpr->iTable = -1; for(i=0; i<pSrcList->nSrc; i++){ struct SrcList_item *pItem = &pSrcList->a[i]; Table *pTab = pItem->pTab; Column *pCol; if( pTab==0 ) continue; assert( pTab->nCol>0 ); if( zTab ){ if( pItem->zAlias ){ char *zTabName = pItem->zAlias; if( sqliteStrICmp(zTabName, zTab)!=0 ) continue; }else{ char *zTabName = pTab->zName; if( zTabName==0 || sqliteStrICmp(zTabName, zTab)!=0 ) continue; if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){ continue; } } } if( 0==(cntTab++) ){ pExpr->iTable = pItem->iCursor; pExpr->iDb = pTab->iDb; } for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ if( sqliteStrICmp(pCol->zName, zCol)==0 ){ cnt++; pExpr->iTable = pItem->iCursor; pExpr->iDb = pTab->iDb; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK; break; } } } /* If we have not already resolved the name, then maybe ** it is a new.* or old.* trigger argument reference */ if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){ TriggerStack *pTriggerStack = pParse->trigStack; Table *pTab = 0; if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zTab) == 0 ){ pExpr->iTable = pTriggerStack->newIdx; assert( pTriggerStack->pTab ); pTab = pTriggerStack->pTab; }else if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zTab) == 0 ){ pExpr->iTable = pTriggerStack->oldIdx; assert( pTriggerStack->pTab ); pTab = pTriggerStack->pTab; } if( pTab ){ int j; Column *pCol = pTab->aCol; pExpr->iDb = pTab->iDb; cntTab++; for(j=0; j < pTab->nCol; j++, pCol++) { if( sqliteStrICmp(pCol->zName, zCol)==0 ){ cnt++; pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK; break; } } } } /* ** Perhaps the name is a reference to the ROWID */ if( cnt==0 && cntTab==1 && sqliteIsRowid(zCol) ){ cnt = 1; pExpr->iColumn = -1; pExpr->dataType = SQLITE_SO_NUM; } /* ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z ** might refer to an result-set alias. This happens, for example, when ** we are resolving names in the WHERE clause of the following command: ** ** SELECT a+b AS x FROM table WHERE x<10; ** ** In cases like this, replace pExpr with a copy of the expression that ** forms the result set entry ("a+b" in the example) and return immediately. ** Note that the expression in the result set should have already been ** resolved by the time the WHERE clause is resolved. */ if( cnt==0 && pEList!=0 ){ for(j=0; j<pEList->nExpr; j++){ char *zAs = pEList->a[j].zName; if( zAs!=0 && sqliteStrICmp(zAs, zCol)==0 ){ assert( pExpr->pLeft==0 && pExpr->pRight==0 ); pExpr->op = TK_AS; pExpr->iColumn = j; pExpr->pLeft = sqliteExprDup(pEList->a[j].pExpr); sqliteFree(zCol); assert( zTab==0 && zDb==0 ); return 0; } } } /* ** If X and Y are NULL (in other words if only the column name Z is ** supplied) and the value of Z is enclosed in double-quotes, then ** Z is a string literal if it doesn't match any column names. In that ** case, we need to return right away and not make any changes to ** pExpr. */ if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ sqliteFree(zCol); return 0; } /* ** cnt==0 means there was not match. cnt>1 means there were two or ** more matches. Either way, we have an error. */ if( cnt!=1 ){ char *z = 0; char *zErr; zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s"; if( zDb ){ sqliteSetString(&z, zDb, ".", zTab, ".", zCol, 0); }else if( zTab ){ sqliteSetString(&z, zTab, ".", zCol, 0); }else{ z = sqliteStrDup(zCol); } sqliteErrorMsg(pParse, zErr, z); sqliteFree(z); } /* Clean up and return */ sqliteFree(zDb); sqliteFree(zTab); sqliteFree(zCol); sqliteExprDelete(pExpr->pLeft); pExpr->pLeft = 0; sqliteExprDelete(pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; sqliteAuthRead(pParse, pExpr, pSrcList); return cnt!=1;}/*** 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.**** We also check for instances of the IN operator. IN comes in two** forms:**** expr IN (exprlist)** and** expr IN (SELECT ...)**** The first form is handled by creating a set holding the list** of allowed values. The second form causes the SELECT to generate ** a temporary table.**** This routine also looks for scalar SELECTs that are part of an expression.** If it finds any, it generates code to write the value of that select** into a memory cell.**** Unknown columns or tables provoke an error. The function returns** the number of errors seen and leaves an error message on pParse->zErrMsg.*/int sqliteExprResolveIds( Parse *pParse, /* The parser context */ SrcList *pSrcList, /* 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 || pSrcList==0 ) return 0; for(i=0; i<pSrcList->nSrc; i++){ assert( pSrcList->a[i].iCursor>=0 && pSrcList->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 is the name of a columnd. */ case TK_ID: { if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){ return 1; } break; } /* 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; 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; } if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){ return 1; } break; } case TK_IN: { Vdbe *v = sqliteGetVdbe(pParse); if( v==0 ) return 1; if( sqliteExprResolveIds(pParse, pSrcList, 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; assert( pE2->token.z ); addr = sqliteVdbeOp3(v, OP_SetInsert, iSet, 0, 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, pSrcList, pEList, pExpr->pLeft) ){ return 1; } if( pExpr->pRight && sqliteExprResolveIds(pParse, pSrcList, 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, pSrcList, 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 wrong_num_args = 0; /* True if wrong number of arguments */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -