Repository: edgedb/edgedb

Issue:
ISE on group
<!-- Please search existing issues to avoid creating duplicates. -->
- EdgeDB Version: 2.0-dev+6573
- OS Version: macOS Catalina

Steps to Reproduce:

Using Netflix schema: https://github.com/colinhacks/edgedb-movies

```
edgedb> group Movie
....... using 
.......   cast_size := count(.actors)
....... by cast_size, .release_year;
edgedb error: InternalServerError: plan should not reference subplan's variable
  Hint: This is most likely a bug in EdgeDB. Please consider opening an issue ticket at https://github.com/edgedb/edgedb/issues/new?template=bug_report.md
  Server traceback:
      edb.errors.InternalServerError: plan should not reference subplan's variable
```





Discussion:
The error seems to be fun, as it's a Postgres ISE.
I have a reduced Postgres ISE:
```
drop table if exists Card;
drop table if exists awards;
create table Card (id uuid);
create table awards (source uuid, target uuid);

SELECT
    -- This line causes "variable not found in subplan target list"
    -- grouping(res.cnt)
    -- This line causes "plan should not reference subplan's variable"
    (SELECT grouping(res.cnt))
FROM Card
CROSS JOIN LATERAL
(SELECT
    (SELECT count(awds.val)
    FROM
        (SELECT awards.target AS val
         FROM awards
         WHERE (Card.id = awards.source)
        ) AS awds
    ) AS cnt
) AS res
GROUP BY
    res.cnt
```
Actually it needs even less:
```
create table Card (id uuid);

SELECT
    -- This line causes "variable not found in subplan target list"
    -- grouping(res.cnt)
    -- This line causes "plan should not reference subplan's variable"
   (SELECT grouping(res.cnt))
FROM Card
CROSS JOIN LATERAL
(SELECT
    (SELECT Card.id) AS cnt
) AS res
GROUP BY
    res.cnt
```

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
@@ -3186,12 +3186,21 @@ def process_set_as_agg_expr_inner(
 
         pathctx.put_path_var(
             stmt, ir_set.path_id, set_expr, aspect=aspect, env=ctx.env)
-        pathctx.get_path_output(
+        out = pathctx.get_path_output(
             stmt, ir_set.path_id, aspect=aspect, env=ctx.env)
+        assert isinstance(out, pgast.ColumnRef)
+
+        # HACK: We select join in the inner statement instead of just
+        # using it as a subquery to work around a postgres bug that
+        # occurs when something defined with a subquery is used as an
+        # argument to `grouping`. See #3844.
+        stmt_rvar = relctx.rvar_for_rel(stmt, ctx=ctx)
+        wrapper.from_clause.append(stmt_rvar)
+        val = astutils.get_column(stmt_rvar, out)
 
         assert wrapper
         set_expr = pgast.CoalesceExpr(
-            args=[stmt, iv], ser_safe=serialization_safe)
+            args=[val, iv], ser_safe=serialization_safe)
 
         pathctx.put_path_var(
             wrapper, ir_set.path_id, set_expr, aspect=aspect, env=ctx.env)


Test patch:
diff --git a/tests/test_edgeql_group.py b/tests/test_edgeql_group.py
--- a/tests/test_edgeql_group.py
+++ b/tests/test_edgeql_group.py
@@ -966,3 +966,15 @@ async def test_edgeql_group_agg_multi_03(self):
                 tb.bag(["red", "black"]),
             ]),
         )
+
+    async def test_edgeql_group_agg_grouping_01(self):
+        # Something about this previously triggered a postgres ISE
+        # that we had to work around.
+        await self.assert_query_result(
+            '''
+                select (group cards::Card
+                   using awd_size := count(.awards)
+                by awd_size, .element) { grouping };
+            ''',
+            [{"grouping": ["awd_size", "element"]}] * 5,
+        )