Repository: edgedb/edgedb

Issue:
`InternalServerError: None` when query has multiple `delete`s in `with` clause
If one wants to delete multiple records, the error just states **None** in red. Then when trying to delete all records one by one, one is able to see the real error, like prohibited by link target policy etc. 

Interesting thing is, even if you try to delete 2 records which are non-deletable (i.e., they will indeed give you any error, unlike the first description where deletable and non-deletable were mixed), the **None** still appears and you aren't informed. Moreover, those two instances in my case are non-deletable because of the exact same reason (they only differ by some uuid in the error message, naturally), which still results in **None** error message. So I guess any number of messages that are different in content result in non-informative **None**.


Discussion:
This seems to be an error in edgedb itself; the full error message is: `InternalServerError: None`.

The query the UI generates is this:
```
with
delete1 := assert_exists((delete default::Example filter .id = <uuid>'...'), message := 'delete1 was blocked by access policy'),
delete2 := assert_exists((delete default::Example filter .id = <uuid>'...'), message := 'delete2 was blocked by access policy')
select {
  delete1,
  delete2
}
```

Resolving patch:
diff --git a/edb/ir/typeutils.py b/edb/ir/typeutils.py
--- a/edb/ir/typeutils.py
+++ b/edb/ir/typeutils.py
@@ -246,12 +246,21 @@ def _typeref(
         union_of = t.get_union_of(schema)
         union: Optional[FrozenSet[irast.TypeRef]]
         if union_of:
+            assert isinstance(t, s_objtypes.ObjectType)
+            union_types = {
+                cast(s_objtypes.ObjectType, c).get_nearest_non_derived_parent(
+                    schema)
+                for c in union_of.objects(schema)
+            }
             non_overlapping, union_is_concrete = (
-                s_utils.get_non_overlapping_union(
-                    schema,
-                    union_of.objects(schema),
-                )
+                s_utils.get_non_overlapping_union(schema, union_types)
             )
+            if union_is_concrete:
+                non_overlapping = frozenset({
+                    t for t in non_overlapping
+                    if t.is_material_object_type(schema)
+                })
+
             union = frozenset(
                 _typeref(c) for c in non_overlapping
             )


Test patch:
diff --git a/tests/test_edgeql_delete.py b/tests/test_edgeql_delete.py
--- a/tests/test_edgeql_delete.py
+++ b/tests/test_edgeql_delete.py
@@ -511,3 +511,19 @@ async def test_edgeql_delete_abstract_01(self):
                 'name': 'child of abstract 2'
             }],
         )
+
+    async def test_edgeql_delete_then_union(self):
+        await self.con.execute(r"""
+            INSERT DeleteTest2 { name := 'x' };
+            INSERT DeleteTest2 { name := 'y' };
+        """)
+
+        await self.assert_query_result(
+            r"""
+            with
+            delete1 := assert_exists((delete DeleteTest2 filter .name = 'x')),
+            delete2 := assert_exists((delete DeleteTest2 filter .name = 'y')),
+            select {delete1, delete2};
+            """,
+            [{}, {}],
+        )