📄 resolve.c
字号:
** then convert that term into a copy of the corresponding result set** column.**** If any errors are detected, add an error message to pParse and** return non-zero. Return zero if no errors are seen.*/int sqlite3ResolveOrderGroupBy( Parse *pParse, /* Parsing context. Leave error messages here */ Select *pSelect, /* The SELECT statement containing the clause */ ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ const char *zType /* "ORDER" or "GROUP" */){ int i; sqlite3 *db = pParse->db; ExprList *pEList; struct ExprList_item *pItem; if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;#if SQLITE_MAX_COLUMN if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); return 1; }#endif pEList = pSelect->pEList; assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */ for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ if( pItem->iCol ){ if( pItem->iCol>pEList->nExpr ){ resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); return 1; } resolveAlias(pParse, pEList, pItem->iCol-1, pItem->pExpr, zType); } } return 0;}/*** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.** The Name context of the SELECT statement is pNC. zType is either** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.**** This routine resolves each term of the clause into an expression.** If the order-by term is an integer I between 1 and N (where N is the** number of columns in the result set of the SELECT) then the expression** in the resolution is a copy of the I-th result-set expression. If** the order-by term is an identify that corresponds to the AS-name of** a result-set expression, then the term resolves to a copy of the** result-set expression. Otherwise, the expression is resolved in** the usual way - using sqlite3ResolveExprNames().**** This routine returns the number of errors. If errors occur, then** an appropriate error message might be left in pParse. (OOM errors** excepted.)*/static int resolveOrderGroupBy( NameContext *pNC, /* The name context of the SELECT statement */ Select *pSelect, /* The SELECT statement holding pOrderBy */ ExprList *pOrderBy, /* An ORDER BY or GROUP BY clause to resolve */ const char *zType /* Either "ORDER" or "GROUP", as appropriate */){ int i; /* Loop counter */ int iCol; /* Column number */ struct ExprList_item *pItem; /* A term of the ORDER BY clause */ Parse *pParse; /* Parsing context */ int nResult; /* Number of terms in the result set */ if( pOrderBy==0 ) return 0; nResult = pSelect->pEList->nExpr; pParse = pNC->pParse; for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ Expr *pE = pItem->pExpr; iCol = resolveAsName(pParse, pSelect->pEList, pE); if( iCol<0 ){ return 1; /* OOM error */ } if( iCol>0 ){ /* If an AS-name match is found, mark this ORDER BY column as being ** a copy of the iCol-th result-set column. The subsequent call to ** sqlite3ResolveOrderGroupBy() will convert the expression to a ** copy of the iCol-th result-set expression. */ pItem->iCol = iCol; continue; } if( sqlite3ExprIsInteger(pE, &iCol) ){ /* The ORDER BY term is an integer constant. Again, set the column ** number so that sqlite3ResolveOrderGroupBy() will convert the ** order-by term to a copy of the result-set expression */ if( iCol<1 ){ resolveOutOfRangeError(pParse, zType, i+1, nResult); return 1; } pItem->iCol = iCol; continue; } /* Otherwise, treat the ORDER BY term as an ordinary expression */ pItem->iCol = 0; if( sqlite3ResolveExprNames(pNC, pE) ){ return 1; } } return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);}/*** Resolve names in the SELECT statement p and all of its descendents.*/static int resolveSelectStep(Walker *pWalker, Select *p){ NameContext *pOuterNC; /* Context that contains this SELECT */ NameContext sNC; /* Name context of this SELECT */ int isCompound; /* True if p is a compound select */ int nCompound; /* Number of compound terms processed so far */ Parse *pParse; /* Parsing context */ ExprList *pEList; /* Result set expression list */ int i; /* Loop counter */ ExprList *pGroupBy; /* The GROUP BY clause */ Select *pLeftmost; /* Left-most of SELECT of a compound */ sqlite3 *db; /* Database connection */ assert( p!=0 ); if( p->selFlags & SF_Resolved ){ return WRC_Prune; } pOuterNC = pWalker->u.pNC; pParse = pWalker->pParse; db = pParse->db; /* Normally sqlite3SelectExpand() will be called first and will have ** already expanded this SELECT. However, if this is a subquery within ** an expression, sqlite3ResolveExprNames() will be called without a ** prior call to sqlite3SelectExpand(). When that happens, let ** sqlite3SelectPrep() do all of the processing for this SELECT. ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and ** this routine in the correct order. */ if( (p->selFlags & SF_Expanded)==0 ){ sqlite3SelectPrep(pParse, p, pOuterNC); return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune; } isCompound = p->pPrior!=0; nCompound = 0; pLeftmost = p; while( p ){ assert( (p->selFlags & SF_Expanded)!=0 ); assert( (p->selFlags & SF_Resolved)==0 ); p->selFlags |= SF_Resolved; /* Resolve the expressions in the LIMIT and OFFSET clauses. These ** are not allowed to refer to any names, so pass an empty NameContext. */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; if( sqlite3ResolveExprNames(&sNC, p->pLimit) || sqlite3ResolveExprNames(&sNC, p->pOffset) ){ return WRC_Abort; } /* Set up the local name-context to pass to sqlite3ResolveExprNames() to ** resolve the result-set expression list. */ sNC.allowAgg = 1; sNC.pSrcList = p->pSrc; sNC.pNext = pOuterNC; /* Resolve names in the result set. */ pEList = p->pEList; assert( pEList!=0 ); for(i=0; i<pEList->nExpr; i++){ Expr *pX = pEList->a[i].pExpr; if( sqlite3ResolveExprNames(&sNC, pX) ){ return WRC_Abort; } } /* Recursively resolve names in all subqueries */ for(i=0; i<p->pSrc->nSrc; i++){ struct SrcList_item *pItem = &p->pSrc->a[i]; if( pItem->pSelect ){ const char *zSavedContext = pParse->zAuthContext; if( pItem->zName ) pParse->zAuthContext = pItem->zName; sqlite3ResolveSelectNames(pParse, pItem->pSelect, &sNC); pParse->zAuthContext = zSavedContext; if( pParse->nErr || db->mallocFailed ) return WRC_Abort; } } /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( (p->selFlags & SF_Aggregate)==0 ); pGroupBy = p->pGroupBy; if( pGroupBy || sNC.hasAgg ){ p->selFlags |= SF_Aggregate; }else{ sNC.allowAgg = 0; } /* If a HAVING clause is present, then there must be a GROUP BY clause. */ if( p->pHaving && !pGroupBy ){ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); return WRC_Abort; } /* Add the expression list to the name-context before parsing the ** other expressions in the SELECT statement. This is so that ** expressions in the WHERE clause (etc.) can refer to expressions by ** aliases in the result set. ** ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ sNC.pEList = p->pEList; if( sqlite3ResolveExprNames(&sNC, p->pWhere) || sqlite3ResolveExprNames(&sNC, p->pHaving) ){ return WRC_Abort; } /* The ORDER BY and GROUP BY clauses may not refer to terms in ** outer queries */ sNC.pNext = 0; sNC.allowAgg = 1; /* Process the ORDER BY clause for singleton SELECT statements. ** The ORDER BY clause for compounds SELECT statements is handled ** below, after all of the result-sets for all of the elements of ** the compound have been resolved. */ if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){ return WRC_Abort; } if( db->mallocFailed ){ return WRC_Abort; } /* Resolve the GROUP BY clause. At the same time, make sure ** the GROUP BY clause does not contain aggregate functions. */ if( pGroupBy ){ struct ExprList_item *pItem; if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){ return WRC_Abort; } for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){ if( ExprHasProperty(pItem->pExpr, EP_Agg) ){ sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " "the GROUP BY clause"); return WRC_Abort; } } } /* Advance to the next term of the compound */ p = p->pPrior; nCompound++; } /* Resolve the ORDER BY on a compound SELECT after all terms of ** the compound have been resolved. */ if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){ return WRC_Abort; } return WRC_Prune;}/*** This routine walks an expression tree and resolves references to** table columns and result-set columns. At the same time, do error** checking on function usage and set a flag if any aggregate functions** are seen.**** To resolve table columns references we look for nodes (or subtrees) of the ** form X.Y.Z or Y.Z or just Z where**** X: The name of a database. Ex: "main" or "temp" or** the symbolic name assigned to an ATTACH-ed database.**** Y: The name of a table in a FROM clause. Or in a trigger** one of the special names "old" or "new".**** Z: The name of a column in table Y.**** The node at the root of the subtree is modified as follows:**** Expr.op Changed to TK_COLUMN** Expr.pTab Points to the Table object for X.Y** Expr.iColumn The column index in X.Y. -1 for the rowid.** Expr.iTable The VDBE cursor number for X.Y****** To resolve result-set references, look for expression nodes of the** form Z (with no X and Y prefix) where the Z matches the right-hand** size of an AS clause in the result-set of a SELECT. The Z expression** is replaced by a copy of the left-hand side of the result-set expression.** Table-name and function resolution occurs on the substituted expression** tree. For example, in:**** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;**** The "x" term of the order by is replaced by "a+b" to render:**** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;**** Function calls are checked to make sure that the function is ** defined and that the correct number of arguments are specified.** If the function is an aggregate function, then the pNC->hasAgg is** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.** If an expression contains aggregate functions then the EP_Agg** property on the expression is set.**** An error message is left in pParse if anything is amiss. The number** if errors is returned.*/int sqlite3ResolveExprNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */){ int savedHasAgg; Walker w; if( pExpr==0 ) return 0;#if SQLITE_MAX_EXPR_DEPTH>0 { Parse *pParse = pNC->pParse; if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){ return 1; } pParse->nHeight += pExpr->nHeight; }#endif savedHasAgg = pNC->hasAgg; pNC->hasAgg = 0; w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.pParse = pNC->pParse; w.u.pNC = pNC; sqlite3WalkExpr(&w, pExpr);#if 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);}/*** Resolve all names in all expressions of a SELECT and in all** decendents of the SELECT, including compounds off of p->pPrior,** subqueries in expressions, and subqueries used as FROM clause** terms.**** See sqlite3ResolveExprNames() for a description of the kinds of** transformations that occur.**** All SELECT statements should have been expanded using** sqlite3SelectExpand() prior to invoking this routine.*/void sqlite3ResolveSelectNames( Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for parent SELECT statement */){ Walker w; assert( p!=0 ); w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.pParse = pParse; w.u.pNC = pOuterNC; sqlite3WalkSelect(&w, p);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -