Repository: edgedb/edgedb

Issue:
Unable to create migration to add default value for `multi link`
<!-- Please search existing issues to avoid creating duplicates. -->
- EdgeDB Version: `EdgeDB CLI 1.1.0+8bc2c20`
- OS Version: `MacOS Catalina 10.15.7`

Steps to Reproduce:

1. Create a default EdgeDB project with `default` module with below schema, then migrate the database
```
module default {
    abstract type Person {
        multi link visited_places -> Place;
    }

    type Firefighter extending Person {}
    
    type Place {
        required property name -> str {
            constraint exclusive;
        }
    }
}

```

2. Update the schema to add default value for `default::Person::visited_places` as below
```
module default {
    abstract type Person {
        multi link visited_places -> Place { default := ( select Place filter .name = 'London' ) };
    }

    type Firefighter extending Person {}
    
    type Place {
        required property name -> str {
            constraint exclusive;
        }
    }
}
```
3. Try to create new migration and error will show `EdgeDB could not resolve migration with the provided answers. Please retry with different answers.`
```
user@local> edgedb migration create
did you alter link 'visited_places' of object type 'default::Person'? [y,n,l,c,b,s,q,?]
> y
edgedb error: EdgeDB could not resolve migration with the provided answers. Please retry with different answers.

```

**Notice**: 
The step 3 can be done without error if 
- `default::Place::name` does not have `exclusive` constraint.
OR
- type `default::Firefighter` does not exists

Is it a bug?


Discussion:
It's a bug.
Oh, and it's even spicier than just that: we fail to migrate to that second schema from an empty schema.

Resolving patch:
diff --git a/edb/schema/delta.py b/edb/schema/delta.py
--- a/edb/schema/delta.py
+++ b/edb/schema/delta.py
@@ -2012,7 +2012,12 @@ def _propagate_if_expr_refs(
                                     schema, cmd_create, fn, context, value)
 
                         cmd_drop.set_attribute_value(fn, dummy)
-                        cmd_create.set_attribute_value(fn, value)
+                        cmd_create.set_attribute_value(
+                            fn,
+                            value,
+                            inherited=ref.field_is_inherited(schema, fn),
+                            computed=ref.field_is_computed(schema, fn),
+                        )
 
                     context.affected_finalization[self].append(
                         (delta_create, cmd_create, this_ref_desc)
diff --git a/edb/schema/objects.py b/edb/schema/objects.py
--- a/edb/schema/objects.py
+++ b/edb/schema/objects.py
@@ -1462,6 +1462,20 @@ def add_classref(
 
         return schema
 
+    def field_is_computed(
+        self,
+        schema: s_schema.Schema,
+        field_name: str,
+    ) -> bool:
+        return field_name in self.get_computed_fields(schema)
+
+    def field_is_inherited(
+        self,
+        schema: s_schema.Schema,
+        field_name: str,
+    ) -> bool:
+        return False
+
     def del_classref(
         self,
         schema: s_schema.Schema,


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
@@ -8899,6 +8899,55 @@ async def test_edgeql_migration_invalid_scalar_01(self):
                 POPULATE MIGRATION;
             """)
 
+    async def test_edgeql_migration_inherited_default_01(self):
+        await self.migrate(r"""
+            abstract type Foo {
+                multi link link -> Obj {
+                    default := ( select Obj filter .name = 'X' )
+                };
+            }
+
+            type Bar extending Foo {}
+
+            type Obj {
+                required property name -> str {
+                    constraint exclusive;
+                }
+            }
+        """)
+
+    async def test_edgeql_migration_inherited_default_02(self):
+        await self.migrate(r"""
+            abstract type Foo {
+                multi link link -> Obj {
+                };
+            }
+
+            type Bar extending Foo {}
+
+            type Obj {
+                required property name -> str {
+                    constraint exclusive;
+                }
+            }
+        """)
+
+        await self.migrate(r"""
+            abstract type Foo {
+                multi link link -> Obj {
+                    default := ( select Obj filter .name = 'X' )
+                };
+            }
+
+            type Bar extending Foo {}
+
+            type Obj {
+                required property name -> str {
+                    constraint exclusive;
+                }
+            }
+        """)
+
     async def test_edgeql_migration_scalar_array_01(self):
         await self.migrate(r"""
             type User {