Repository: edgedb/edgedb

Issue:
enumerate ignores clauses on implicit SELECTs of function calls
`SELECT enumerate(_gen_series(0,99) FILTER false);` doesn't FILTER anything.
Similar issue for ORDER BY.

Looks like the issue is that `process_set_as_func_enumerate` just drops this all.

(`SELECT enumerate((SELECT _gen_series(0,99) FILTER false));` filters everything.)




Discussion:

Resolving patch:
diff --git a/edb/pgsql/compiler/relgen.py b/edb/pgsql/compiler/relgen.py
--- a/edb/pgsql/compiler/relgen.py
+++ b/edb/pgsql/compiler/relgen.py
@@ -266,8 +266,18 @@ def _get_set_rvar(
 
     elif isinstance(ir_set.expr, irast.FunctionCall):
         if str(ir_set.expr.func_shortname) == 'std::enumerate':
-            if isinstance(irutils.unwrap_set(ir_set.expr.args[0].expr).expr,
-                          irast.FunctionCall):
+            arg_set = ir_set.expr.args[0].expr
+            arg_expr = arg_set.expr
+            if (
+                isinstance(irutils.unwrap_set(arg_set).expr,
+                           irast.FunctionCall)
+                and not (
+                    isinstance(arg_expr, irast.SelectStmt) and (
+                        arg_expr.where or arg_expr.orderby
+                        or arg_expr.limit or arg_expr.offset
+                    )
+                )
+            ):
                 # Enumeration of a SET-returning function
                 rvars = process_set_as_func_enumerate(ir_set, stmt, ctx=ctx)
             else:
@@ -1748,8 +1758,6 @@ def process_set_as_enumerate(
     assert isinstance(expr, irast.FunctionCall)
 
     with ctx.subrel() as newctx:
-        newctx.expr_exposed = False
-
         ir_arg = expr.args[0].expr
         arg_ref = dispatch.compile(ir_arg, ctx=newctx)
         arg_val = output.output_as_value(arg_ref, env=newctx.env)
@@ -1788,10 +1796,17 @@ def process_set_as_enumerate(
             pathctx.put_path_value_var(
                 newctx.rel, element.path_id, element.val, env=newctx.env)
 
+        var = pathctx.maybe_get_path_var(
+            newctx.rel, ir_arg.path_id,
+            aspect='serialized', env=newctx.env)
+        if var is not None:
+            pathctx.put_path_var(newctx.rel, set_expr.elements[1].path_id, var,
+                                 aspect='serialized', env=newctx.env)
+
         pathctx.put_path_var_if_not_exists(
             newctx.rel, ir_set.path_id, set_expr, aspect='value', env=ctx.env)
 
-    aspects = ('value',)
+    aspects = ('value', 'source')
 
     func_rvar = relctx.new_rel_rvar(ir_set, newctx.rel, ctx=ctx)
     relctx.include_rvar(stmt, func_rvar, ir_set.path_id,


Test patch:
diff --git a/tests/test_edgeql_functions.py b/tests/test_edgeql_functions.py
--- a/tests/test_edgeql_functions.py
+++ b/tests/test_edgeql_functions.py
@@ -524,6 +524,24 @@ async def test_edgeql_functions_enumerate_04(self):
                 'select <json>enumerate({(1, 2), (3, 4)})'),
             '[[0, [1, 2]], [1, [3, 4]]]')
 
+    async def test_edgeql_functions_enumerate_05(self):
+        await self.assert_query_result(
+            r'''SELECT enumerate(test::User { name } ORDER BY .name);''',
+            [[0, {"name": "Elvis"}],
+             [1, {"name": "Yury"}]],
+        )
+
+        await self.assert_query_result(
+            r'''SELECT enumerate(test::User ORDER BY .name).1.name;''',
+            ["Elvis", "Yury"],
+        )
+
+    async def test_edgeql_functions_enumerate_06(self):
+        await self.assert_query_result(
+            r'''SELECT enumerate(_gen_series(0, 99) FILTER FALSE);''',
+            [],
+        )
+
     async def test_edgeql_functions_array_get_01(self):
         await self.assert_query_result(
             r'''SELECT array_get([1, 2, 3], 2);''',