From 47f544cdc1c0e44d92f67fcc01eb23350522644e Mon Sep 17 00:00:00 2001 From: chuenchen309 <48723787+chuenchen309@users.noreply.github.com> Date: Fri, 17 Jul 2026 13:53:26 +0800 Subject: [PATCH] Fix(macros): @FILTER with a single non-array argument @FILTER's docstring says "The first argument can be an Array or var args can be used", the same contract @EACH and @REDUCE state. All three route their arguments through _norm_var_arg_lambda, whose single-item branch returns a bare expression rather than a list: expressions = ( item.expressions if isinstance(item, (exp.Array, exp.Tuple)) else [item.this] if isinstance(item, exp.Paren) else item # <- bare expression ) @EACH and @REDUCE absorb that with ensure_collection(); @FILTER iterates it directly, so a lone argument raises: @EACH(a, x -> x + 1) -> SELECT a + 1 @REDUCE(a, (x, y) -> x+y) -> SELECT a @FILTER(a, x -> x > 1) -> MacroEvalError: 'Column' object is not iterable Wrap the items in ensure_collection() so @FILTER matches its siblings. An explicit array was already working and is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: chuenchen309 <48723787+chuenchen309@users.noreply.github.com> --- sqlmesh/core/macros.py | 2 +- tests/core/test_macros.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/sqlmesh/core/macros.py b/sqlmesh/core/macros.py index ad8b922a07..8706897120 100644 --- a/sqlmesh/core/macros.py +++ b/sqlmesh/core/macros.py @@ -789,7 +789,7 @@ def filter_(evaluator: MacroEvaluator, *args: t.Any) -> t.List[t.Any]: """ *items, func = args items, func = _norm_var_arg_lambda(evaluator, func, *items) # type: ignore - return list(filter(lambda arg: evaluator.eval_expression(func(arg)), items)) + return list(filter(lambda arg: evaluator.eval_expression(func(arg)), ensure_collection(items))) def _optional_expression( diff --git a/tests/core/test_macros.py b/tests/core/test_macros.py index 0135cd8ca5..17b699d11f 100644 --- a/tests/core/test_macros.py +++ b/tests/core/test_macros.py @@ -358,6 +358,18 @@ def test_ast_correctness(macro_evaluator): "700", {}, ), + # @FILTER documents "The first argument can be an Array or var args can be + # used", like @EACH and @REDUCE, so a lone item must work too. + ( + """@SQL(@REDUCE(@FILTER(300, x -> x > 250), (x,y) -> x + y))""", + "300", + {}, + ), + ( + """select @FILTER(a, x -> x > 1)""", + "SELECT a", + {}, + ), ( """select @EACH([a, b, c], x -> x and @SQL('@y'))""", "SELECT a AND z, b AND z, c AND z",