diff options
Diffstat (limited to 'src/resolve.c')
-rw-r--r-- | src/resolve.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/src/resolve.c b/src/resolve.c index a194a2655..43a3870e2 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -55,7 +55,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){ ** column reference is so that the column reference will be recognized as ** usable by indices within the WHERE clause processing logic. ** -** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means +** The TK_AS operator is inhibited if zType[0]=='G'. This means ** that in a GROUP BY clause, the expression is evaluated twice. Hence: ** ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x @@ -65,8 +65,9 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){ ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 ** ** The result of random()%5 in the GROUP BY clause is probably different -** from the result in the result-set. We might fix this someday. Or -** then again, we might not... +** from the result in the result-set. On the other hand Standard SQL does +** not allow the GROUP BY clause to contain references to result-set columns. +** So this should never come up in well-formed queries. ** ** If the reference is followed by a COLLATE operator, then make sure ** the COLLATE operator is preserved. For example: @@ -396,10 +397,16 @@ static int lookupName( ** 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. + ** + ** The ability to use an output result-set column in the WHERE, GROUP BY, + ** or HAVING clauses, or as part of a larger expression in the ORDRE BY + ** clause is not standard SQL. This is a (goofy) SQLite extension, that + ** is supported for backwards compatibility only. TO DO: Issue a warning + ** on sqlite3_log() whenever the capability is used. */ if( (pEList = pNC->pEList)!=0 && zTab==0 - && ((pNC->ncFlags & NC_AsMaybe)==0 || cnt==0) + && cnt==0 ){ for(j=0; j<pEList->nExpr; j++){ char *zAs = pEList->a[j].zName; @@ -961,7 +968,7 @@ static int resolveCompoundOrderBy( /* ** Check every term in the ORDER BY or GROUP BY clause pOrderBy of ** the SELECT statement pSelect. If any term is reference to a -** result set expression (as determined by the ExprList.a.iCol field) +** result set expression (as determined by the ExprList.a.iOrderByCol field) ** then convert that term into a copy of the corresponding result set ** column. ** @@ -1009,7 +1016,7 @@ int sqlite3ResolveOrderGroupBy( ** 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 +** the order-by term is an identifier 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(). @@ -1035,16 +1042,19 @@ static int resolveOrderGroupBy( 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 ){ - /* 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->iOrderByCol = (u16)iCol; - continue; + Expr *pE2 = sqlite3ExprSkipCollate(pE); + if( zType[0]!='G' ){ + iCol = resolveAsName(pParse, pSelect->pEList, pE2); + 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->iOrderByCol = (u16)iCol; + continue; + } } - if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){ + if( sqlite3ExprIsInteger(pE2, &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 */ @@ -1187,7 +1197,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ return WRC_Abort; } - /* Add the expression list to the name-context before parsing the + /* Add the output column 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. @@ -1196,10 +1206,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ ** re-evaluated for each reference to it. */ sNC.pEList = p->pEList; - sNC.ncFlags |= NC_AsMaybe; if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; - sNC.ncFlags &= ~NC_AsMaybe; /* The ORDER BY and GROUP BY clauses may not refer to terms in ** outer queries |