From 3abf36eea3c3411c5cd08009371812510b5a0383 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 2 Dec 2025 02:22:41 +0000 Subject: [PATCH] fix: handle BinaryExpr and propagate aggregate status in complex expressions - Add BinaryExpr case in inferColNameFromExpr to handle arithmetic expressions like "100.0 * contributions / SUM(...)" - BinaryExpr checks if either operand is an aggregate/window expression and propagates IsAggregateExpr status - Multi-argument functions now propagate IsAggregateExpr from their arguments, so ROUND(expr_with_window_func, 2) is correctly marked This fixes "cannot find col" errors when using complex expressions containing window functions in CTE queries. --- internal/stackql/parserutil/parser_util.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/internal/stackql/parserutil/parser_util.go b/internal/stackql/parserutil/parser_util.go index aac48f8a..99376487 100644 --- a/internal/stackql/parserutil/parser_util.go +++ b/internal/stackql/parserutil/parser_util.go @@ -678,6 +678,10 @@ func inferColNameFromExpr( rv.DecoratedColumn = fmt.Sprintf(`%s%s`, rv.DecoratedColumn, constants.PostgresJSONCastSuffix) } } + // Propagate aggregate status from arguments + if rv.IsAggregateExpr { + retVal.IsAggregateExpr = true + } exprsDecorated = append(exprsDecorated, rv.DecoratedColumn) } } @@ -799,6 +803,23 @@ func inferColNameFromExpr( return retVal, nil } } + case *sqlparser.BinaryExpr: + // Binary expressions (arithmetic, etc.) are computed expressions + decoratedColumn := astformat.String(expr, formatter) + retVal.DecoratedColumn = getDecoratedColRendition(decoratedColumn, alias) + // Check if either operand contains aggregate/window functions + lhsRetval, _ := inferColNameFromExpr(expr.Left, formatter, "") + rhsRetval, _ := inferColNameFromExpr(expr.Right, formatter, "") + // If either side is an aggregate expression, the whole binary expr is computed + if lhsRetval.IsAggregateExpr || rhsRetval.IsAggregateExpr { + retVal.IsAggregateExpr = true + } + // Try to get a name from either operand for reference + if lhsRetval.Name != "" { + retVal.Name = lhsRetval.Name + } else if rhsRetval.Name != "" { + retVal.Name = rhsRetval.Name + } default: decoratedColumn := astformat.String(expr, formatter) retVal.DecoratedColumn = getDecoratedColRendition(decoratedColumn, alias)