Repository: edgedb/edgedb

Issue:
edb.errors.InternalServerError: there is no range var for (__derived__::expr~15) source in <pg.SelectStmt at 0x7f9393526e80>
```
SELECT
    ast::Expr
FILTER
    count (.value[IS ast::Call].args) = 2
    AND (
        WITH
            items := array_agg(
                (
                    FOR _singleton
                    IN {.value[IS ast::Call]}
                    UNION (SELECT _singleton.args ORDER BY @index)
                )
            )
        SELECT
            items[0] IS ast::Name
    )
LIMIT 10;
```

while playing with the edgeql, I noticed this throws an `edb.errors.InternalServerError`, so reporting it. Here is the [schema](https://github.com/reizio/reiz.io/blob/master/static/Python-reiz.edgeql)


Discussion:
Here is a similar query that successfully yields results (if I change `[0][IS ast::Name].py_id = 'foo'` into `[0] IS ast::Name`, I get the same error)
```
SELECT
    ast::Expr
FILTER
    count(.value[IS ast::Call].args) > 0
    AND (
        SELECT
            array_agg(
                (
                    FOR
                        _singleton
                    IN 
                        {.value[IS ast::Call]}
                    UNION 
                        (SELECT _singleton.args ORDER BY @index)
                )
            )
    )[0][IS ast::Name].py_id = 'foo'
LIMIT 10;
```
Same query when the `IS` check is inlined produces another error (even though the array is ensured to be not empty)
```
reiz_store> SELECT
...........     ast::Expr
........... FILTER
...........     count (.value[IS ast::Call].args) = 2
...........     AND (
...........         WITH
...........             items := array_agg(
...........                 (
...........                     FOR _singleton
...........                     IN {.value[IS ast::Call]}
...........                     UNION (SELECT _singleton.args ORDER BY @index)
...........                 )
...........             )
...........         SELECT
...........             items[0][IS ast::Name].py_id = 'foo'
...........     )
........... LIMIT 10;
ERROR: InternalServerError: cannot determine type of empty array
  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: cannot determine type of empty array
```
Minimization:
```
CREATE TYPE Foo;
WITH X := array_agg(Object) SELECT X[0] IS Foo;
```


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
@@ -902,6 +902,12 @@ def process_set_as_path(
         with ctx.subrel() as srcctx:
             srcctx.expr_exposed = False
             src_rvar = get_set_rvar(ir_source, ctx=srcctx)
+            # semi_join needs a source rvar, so make sure we have one.
+            # (The returned one won't be a source rvar if it comes
+            # from a function, for example)
+            if not ir_source.path_id.is_type_intersection_path():
+                src_rvar = relctx.ensure_source_rvar(
+                    ir_source, ctx.rel, ctx=srcctx)
             set_rvar = relctx.semi_join(stmt, ir_set, src_rvar, ctx=srcctx)
             rvars.append(SetRVar(set_rvar, ir_set.path_id,
                                  ['value', 'source']))
diff --git a/edb/pgsql/types.py b/edb/pgsql/types.py
--- a/edb/pgsql/types.py
+++ b/edb/pgsql/types.py
@@ -184,7 +184,8 @@ def pg_type_from_ir_typeref(
 
     if irtyputils.is_array(ir_typeref):
         if (irtyputils.is_generic(ir_typeref)
-                or irtyputils.is_abstract(ir_typeref.subtypes[0])):
+                or (irtyputils.is_abstract(ir_typeref.subtypes[0])
+                    and irtyputils.is_scalar(ir_typeref.subtypes[0]))):
             return ('anyarray',)
         else:
             tp = pg_type_from_ir_typeref(


Test patch:
diff --git a/tests/test_edgeql_select.py b/tests/test_edgeql_select.py
--- a/tests/test_edgeql_select.py
+++ b/tests/test_edgeql_select.py
@@ -6100,3 +6100,44 @@ async def test_edgeql_select_revlink_on_union(self):
                 }
             ],
         )
+
+    async def test_edgeql_select_expr_objects_01(self):
+        await self.assert_query_result(
+            r'''
+                SELECT array_agg(test::Issue ORDER BY .body)[0].owner.name;
+            ''',
+            ["Elvis"],
+        )
+
+    async def test_edgeql_select_expr_objects_02(self):
+        await self.assert_query_result(
+            r'''
+                SELECT _ := array_unpack(array_agg(test::Issue)).owner.name
+                ORDER BY _;
+            ''',
+            ["Elvis", "Yury"],
+        )
+
+    async def test_edgeql_select_expr_objects_03(self):
+        await self.con.execute(
+            '''
+                CREATE FUNCTION test::issues() -> SET OF test::Issue
+                USING (test::Issue);
+            '''
+        )
+
+        await self.assert_query_result(
+            r'''
+                SELECT _ := test::issues().owner.name ORDER BY _;
+            ''',
+            ["Elvis", "Yury"],
+        )
+
+    async def test_edgeql_select_expr_objects_04(self):
+        await self.assert_query_result(
+            r'''
+                WITH items := array_agg((SELECT test::Named ORDER BY .name))
+                SELECT items[0] IS test::Status;
+            ''',
+            [True],
+        )