Repository: edgedb/edgedb

Issue:
`column source_...~1.id does not exist` when migration adds a link property to existing link on new database
<!-- 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.10+66168b2
- EdgeDB CLI Version: 2.2.6+7eabbf9
- OS Version: macOS 13.1

Steps to Reproduce:

1. Create a fresh database via `edgedb project init`
2. Create two objects with a link property between them
3. Migrate to add a link property to the link

Note that this does not occur when migrating an existing database with data in it

<!-- If the issue is about a query error, please also provide your schema -->

Example migration

```
CREATE MIGRATION m1e5lg4zthhiwftctkhu42zk3an4wlckofxbbacknb6mvqucswr6tq
    ONTO m145ubndj6w5mhlvoea2qdomtgvh6ziia43mvbwsuwu43d6h3nq4ua
{
  ALTER TYPE default::Survey {
      ALTER LINK recipients {
          CREATE PROPERTY destination -> std::str {
              SET default := 'email';
          };
      };
  };
};
```

```
$ edgedb migrate
edgedb error: InternalServerError: column source_23dcd9ce-af36-11ed-b05e-69076c83b0e2~1.id does not exist
  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: column source_23dcd9ce-af36-11ed-b05e-69076c83b0e2~1.id does not exist
```

Schema:

```
module default {
    type Survey {
        multi link recipients -> User;
    }
    type User{}
}
```

```
module default {
    type Survey {
        multi link recipients -> User {
            property destination -> str {
                default := "email";
            }
        }
    }
    type User{}
}
```


Discussion:
> Note that this does not occur when migrating an existing database with data in it

I think this is a red herring; I was able to reproduce it with data in the database.

The `default` on the link property is key. The part where things fail is in trying to apply the default property to potentially existing links.


But, interestingly, despite that, adding a default to an existing linkprop works
Smells possibly related to this fix introduced in 2.10, if only for the link prop connection?
https://github.com/edgedb/edgedb/issues/4961

Resolving patch:
diff --git a/edb/pgsql/delta.py b/edb/pgsql/delta.py
--- a/edb/pgsql/delta.py
+++ b/edb/pgsql/delta.py
@@ -5253,6 +5253,11 @@ def _create_property(
                 (default := prop.get_default(schema))
                 and not prop.is_pure_computable(schema)
                 and not fills_required
+                # link properties use SQL defaults and shouldn't need
+                # us to do it explicitly (which is good, since
+                # _alter_pointer_optionality doesn't currently work on
+                # linkprops)
+                and not prop.is_link_property(schema)
             ):
                 self._alter_pointer_optionality(
                     schema, schema, context, fill_expr=default)


Test patch:
diff --git a/tests/test_edgeql_ddl.py b/tests/test_edgeql_ddl.py
--- a/tests/test_edgeql_ddl.py
+++ b/tests/test_edgeql_ddl.py
@@ -3438,6 +3438,27 @@ async def test_edgeql_ddl_link_property_09(self):
             json_only=True,
         )
 
+    async def test_edgeql_ddl_link_property_10(self):
+        await self.con.execute("""
+            CREATE TYPE default::User;
+            CREATE TYPE default::Survey {
+                CREATE MULTI LINK recipients -> default::User;
+            };
+            insert Survey { recipients := (insert User) };
+        """)
+
+        await self.con.execute("""
+            alter type Survey alter link recipients
+            create property destination -> str { set default := "email" };
+        """)
+
+        await self.assert_query_result(
+            r"""
+                select Survey { recipients: {@destination} };
+            """,
+            [{"recipients": [{"@destination": "email"}]}]
+        )
+
     async def test_edgeql_ddl_bad_01(self):
         with self.assertRaisesRegex(
                 edgedb.InvalidReferenceError,