Repository: edgedb/edgedb

Issue:
Selecting subtype property after update returns old data
<!-- Please search existing issues to avoid creating duplicates. -->

<!--
For the EdgeDB Version: run `edgedb query 'select sys::get_version_as_str()'` from your project directory (or run `select sys::get_version_as_str();` in the EdgeDB interactive shell).
For the EdgeDB CLI Version: Run `edgedb --version` from anywhere
-->

- EdgeDB Version: 2.9
- EdgeDB CLI Version: 2.3.0
- OS Version: WSL

Steps to Reproduce:

1. Insert a Dog with a name:
```
insert Dog {
  name := "oldName"
}
```

2. Update Animal with a new name:
```
select (update Animal set {
  name := "newName"
}) {
  c1 := .name,
  c2 := [is Animal].name,
  c3 := [is Cat].name,
  c4 := [is Dog].name
}
```
this returns:
```json
[
  {
    "c1": "newName",
    "c2": "newName",
    "c3": null,
    "c4": "oldName"
  }
]
```

I would expect `c4` to also return `"newName"`

<br/>
<!-- If the issue is about a query error, please also provide your schema -->

Schema:
```
abstract type Animal {
    required property name -> str;
}

type Cat extending Animal {
}

type Dog extending Animal {
}
```


Discussion:

Resolving patch:
diff --git a/edb/pgsql/compiler/relctx.py b/edb/pgsql/compiler/relctx.py
--- a/edb/pgsql/compiler/relctx.py
+++ b/edb/pgsql/compiler/relctx.py
@@ -444,7 +444,7 @@ def new_free_object_rvar(
     return rvar_for_rel(qry, typeref=typeref, lateral=lateral, ctx=ctx)
 
 
-def _deep_copy_primitive_rvar_path_var(
+def deep_copy_primitive_rvar_path_var(
     orig_id: irast.PathId, new_id: irast.PathId,
     rvar: pgast.PathRangeVar, *,
     env: context.Environment
@@ -521,7 +521,7 @@ def new_primitive_rvar(
             # to use _lateral_union_join; this means that all of the
             # path bonds need to be valid on each *subquery*, so we
             # need to set them up in each subquery.
-            _deep_copy_primitive_rvar_path_var(
+            deep_copy_primitive_rvar_path_var(
                 flipped_id, prefix_path_id, set_rvar, env=ctx.env)
             pathctx.put_rvar_path_bond(set_rvar, prefix_path_id)
 
@@ -1543,6 +1543,7 @@ def range_for_material_objtype(
             typeref.name_hint,
             lateral=lateral,
             path_id=path_id,
+            typeref=typeref,
             tag='overlay-stack',
             ctx=ctx,
         )
@@ -1630,7 +1631,7 @@ def range_for_typeref(
             )
 
         pathctx.put_path_bond(wrapper, path_id)
-        rvar = rvar_for_rel(wrapper, lateral=lateral, ctx=ctx)
+        rvar = rvar_for_rel(wrapper, lateral=lateral, typeref=typeref, ctx=ctx)
 
     else:
         rvar = range_for_material_objtype(
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
@@ -887,21 +887,15 @@ def process_set_as_path_type_intersection(
         poly_rvar = relctx.range_for_typeref(
             target_typeref,
             path_id=ir_set.path_id,
+            dml_source=irutils.get_nearest_dml_stmt(ir_set),
             lateral=True,
             ctx=ctx,
         )
 
         prefix_path_id = ir_set.path_id.src_path()
         assert prefix_path_id is not None, 'expected a path'
-        pathctx.put_rvar_path_output(
-            rvar=poly_rvar,
-            path_id=prefix_path_id,
-            aspect='identity',
-            var=pathctx.get_rvar_path_identity_var(
-                poly_rvar, ir_set.path_id, env=ctx.env,
-            ),
-            env=ctx.env,
-        )
+        relctx.deep_copy_primitive_rvar_path_var(
+            ir_set.path_id, prefix_path_id, poly_rvar, env=ctx.env)
         pathctx.put_rvar_path_bond(poly_rvar, prefix_path_id)
         relctx.include_rvar(stmt, poly_rvar, ir_set.path_id, ctx=ctx)
         int_rvar = pgast.IntersectionRangeVar(


Test patch:
diff --git a/tests/test_edgeql_update.py b/tests/test_edgeql_update.py
--- a/tests/test_edgeql_update.py
+++ b/tests/test_edgeql_update.py
@@ -3697,3 +3697,34 @@ async def test_edgeql_update_volatility_02(self):
             """,
             [True],
         )
+
+    async def test_edgeql_update_poly_overlay_01(self):
+        await self.con.execute(r"""
+            insert UpdateTestSubType { name := 'update-test4' };
+        """)
+
+        await self.assert_query_result(
+            r"""
+                select (
+                  update UpdateTest filter .name = 'update-test4'
+                  set { name := '!' }
+                ) { c1 := .name, c2 := [is UpdateTestSubType].name };
+            """,
+            [{"c1": "!", "c2": "!"}]
+        )
+
+    async def test_edgeql_update_poly_overlay_02(self):
+        await self.con.execute(r"""
+            insert UpdateTestSubType { name := 'update-test4' };
+        """)
+
+        await self.assert_query_result(
+            r"""
+                with X := (
+                  update UpdateTest filter .name = 'update-test4'
+                  set { name := '!' }
+                ),
+                select X[is UpdateTestSubType] { name };
+            """,
+            [{"name": "!"}]
+        )