Repository: edgedb/edgedb

Issue:
Error renaming type extending abstract type with computed property
<!-- Please search existing issues to avoid creating duplicates. -->
- EdgeDB CLI Version: 1.1.0+8bc2c20
- EdgeDB DB Version: 1.1+ab7d5a1
- OS Version: macosx

Unable to rename a type in my schema that extends from abstract types that contain a computed property.

# Steps to Reproduce:

setup initial schema

```
module default {
	abstract type Base {
		property typename := "myapp:type:" ++ re_replace("::", ":", .__type__.name);
	}

	type NamedObject extending Base {
		required property foo -> str;
	}
}
```

migrate database

```
edgedb migration create
edgedb migration apply
```

rename `NamedObject` to `RenamedObject`

```
module default {
	abstract type Base {
		property typename := "myapp:type:" ++ re_replace("::", ":", .__type__.name);
	}

	type RenamedObject extending Base {
		required property foo -> str;
	}
}
```

attempt to create new migration with type rename

```
% edgedb migration create
did you rename object type 'default::NamedObject' to 'default::RenamedObject'? [y,n,l,c,b,s,q,?]
> y
did you alter the type of property 'typename' of object type 'default::RenamedObject'? [y,n,l,c,b,s,q,?]
> l
The following DDL statements will be applied:
    ALTER TYPE default::RenamedObject {
        ALTER PROPERTY typename {
            RESET TYPE;
        };
    };
did you alter the type of property 'typename' of object type 'default::RenamedObject'? [y,n,l,c,b,s,q,?]
> n
edgedb error: EdgeDB could not resolve migration with the provided answers. Please retry with different answers.
```

If we say `yes` to the altering of `typename` we get:

```
% edgedb migration create
did you rename object type 'default::NamedObject' to 'default::RenamedObject'? [y,n,l,c,b,s,q,?]
> y
did you alter the type of property 'typename' of object type 'default::RenamedObject'? [y,n,l,c,b,s,q,?]
> y
error: SchemaDefinitionError: it is illegal for the computed property 'typename' of object type 'default::RenamedObject' to overload an existing property
  ┌─ query:2:5
  │  
2 │ ╭     ALTER PROPERTY typename {
3 │ │         RESET TYPE;
4 │ │     };
  │ ╰─────^ error

Rolling back last operation...
```



Discussion:
since our schema is still fairly fresh and we don't yet have any production data, I'm working around this with:

```
% edgedb migration create
did you rename object type 'default::NamedObject' to 'default::RenamedObject'? [y,n,l,c,b,s,q,?]
> n
did you drop object type 'default::NamedObject'? [y,n,l,c,b,s,q,?]
> y
did you create object type 'default::RenamedObject'? [y,n,l,c,b,s,q,?]
> y
Created ./dbschema/migrations/00002.edgeql, id: m1xlnby3vlrcvo6htdjgittcov2gdl6kw5lta45efjdk5s7g7bksqa
```

Resolving patch:
diff --git a/edb/schema/delta.py b/edb/schema/delta.py
--- a/edb/schema/delta.py
+++ b/edb/schema/delta.py
@@ -2021,7 +2021,11 @@ def _propagate_if_expr_refs(
                         assert isinstance(value, s_expr.Expression)
                         # Strip the "compiled" out of the expression
                         value = s_expr.Expression.not_compiled(value)
-                        if fixer:
+                        # We don't run the fixer on inherited fields because
+                        # they can't have changed (and because running it
+                        # on inherited constraint finalexprs breaks
+                        # the extra parens in it...)
+                        if fixer and not ref.field_is_inherited(schema, fn):
                             with obj_cmd.new_context(schema, context, obj):
                                 value = fixer(
                                     schema, cmd_create, fn, context, value)
diff --git a/edb/schema/pointers.py b/edb/schema/pointers.py
--- a/edb/schema/pointers.py
+++ b/edb/schema/pointers.py
@@ -1912,7 +1912,12 @@ def canonicalize_alter_from_external_ref(
 
         assert isinstance(expression.irast, irast.Statement)
         target = expression.irast.stype
-        self.set_attribute_value('target', target)
+        self.set_attribute_value(
+            'target',
+            target,
+            inherited=pointer.field_is_inherited(schema, 'target'),
+            computed=pointer.field_is_computed(schema, 'target'),
+        )
 
 
 class DeletePointer(


Test patch:
diff --git a/tests/test_edgeql_data_migration.py b/tests/test_edgeql_data_migration.py
--- a/tests/test_edgeql_data_migration.py
+++ b/tests/test_edgeql_data_migration.py
@@ -10891,3 +10891,30 @@ async def test_edgeql_migration_on_target_delete_02(self):
             with module test
             delete Tgt;
         """)
+
+    async def test_edgeql_migration_rename_with_stuff_01(self):
+        await self.migrate(
+            r"""
+                type Base {
+                        property x -> str;
+                        property xbang := .x ++ "!";
+                }
+
+                type NamedObject extending Base {
+                        required property foo -> str;
+                }
+            """
+        )
+
+        await self.migrate(
+            r"""
+                type Base {
+                        property x -> str;
+                        property xbang := .x ++ "!";
+                }
+
+                type ReNamedObject extending Base {
+                        required property foo -> str;
+                }
+            """
+        )
diff --git a/tests/test_schema.py b/tests/test_schema.py
--- a/tests/test_schema.py
+++ b/tests/test_schema.py
@@ -6914,6 +6914,106 @@ def test_schema_migrations_on_target_delete_01(self):
             """
         ])
 
+    def test_schema_migrations_rename_with_stuff_01(self):
+        self._assert_migration_equivalence([
+            r"""
+                type Base {
+                        property x -> str;
+                        property xbang := .x ++ "!";
+                }
+
+                type NamedObject extending Base {
+                        required property foo -> str;
+                }
+            """,
+            r"""
+                type Base {
+                        property x -> str;
+                        property xbang := .x ++ "!";
+                }
+
+                type ReNamedObject extending Base {
+                        required property foo -> str;
+                }
+            """
+        ])
+
+    def test_schema_migrations_rename_with_stuff_02(self):
+        self._assert_migration_equivalence([
+            r"""
+                type Base {
+                        property x -> str;
+                        index on (.x);
+                }
+
+                type NamedObject extending Base {
+                        required property foo -> str;
+                }
+            """,
+            r"""
+                type Base {
+                        property x -> str;
+                        index on (.x);
+                }
+
+                type ReNamedObject extending Base {
+                        required property foo -> str;
+                }
+            """
+        ])
+
+    def test_schema_migrations_rename_with_stuff_03(self):
+        self._assert_migration_equivalence([
+            r"""
+                type Base {
+                        property x -> str;
+                        property z -> str {
+                            constraint expression on (__subject__ != "lol");
+                        };
+                }
+
+                type NamedObject extending Base {
+                        required property foo -> str;
+                }
+            """,
+            r"""
+                type Base {
+                        property x -> str;
+                        property z -> str {
+                            constraint expression on (__subject__ != "lol");
+                        };
+                }
+
+                type ReNamedObject extending Base {
+                        required property foo -> str;
+                }
+            """
+        ])
+
+    def test_schema_migrations_rename_with_stuff_04(self):
+        self._assert_migration_equivalence([
+            r"""
+                type Base {
+                        property x -> str;
+                        constraint expression on ((.x != "lol"));
+                }
+
+                type NamedObject extending Base {
+                        required property foo -> str;
+                }
+            """,
+            r"""
+                type Base {
+                        property x -> str;
+                        constraint expression on ((.x != "lol"));
+                }
+
+                type ReNamedObject extending Base {
+                        required property foo -> str;
+                }
+            """
+        ])
+
 
 class TestDescribe(tb.BaseSchemaLoadTest):
     """Test the DESCRIBE command."""