Repository: edgedb/edgedb

Issue:
Changing the type of an abstract link property errors
<!-- Please search existing issues to avoid creating duplicates. -->
- EdgeDB Version: 1.2
- OS Version: Mac Monterray

Steps to Reproduce:

1. Change orderVal to `decimal`
2. migrate
<!-- If the issue is about a query error, please also provide your schema -->
Schema:
```
abstract type Entity{}
abstract link orderable {
    property orderVal -> str { delegated constraint exclusive };
 }
    type Topic extending Entity {
      multi link videos extends orderable -> Video;
   }
type Video extends Entity {}
```

Error
```
 InternalServerError: invalid PathId: <Link 6594eb62-b4ec-11ec-bd14-f709fa69babe at 0x0x113d8dfc0> is not concrete
  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:
      Traceback (most recent call last):
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler_pool/worker.py", line 309, in worker
          res = meth(*args)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler_pool/worker.py", line 202, in compile_in_tx
          units, cstate = COMPILER.compile_in_tx(cstate, *args, **kwargs)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 2148, in compile_in_tx
          return self._compile(ctx=ctx, source=source), ctx.state
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1669, in _compile
          return self._try_compile(ctx=ctx, source=source)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1722, in _try_compile
          comp, capabilities = self._compile_dispatch_ql(
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1605, in _compile_dispatch_ql
          query = self._compile_ql_migration(ctx, ql)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 944, in _compile_ql_migration
          query = self._compile_and_apply_ddl_stmt(ctx, ql)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 861, in _compile_and_apply_ddl_stmt
          block, new_types = self._process_delta(ctx, delta)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 342, in _process_delta
          schema = pgdelta.apply(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 5963, in apply
          schema = super().apply(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 1519, in apply
          schema = self.apply_subcommands(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 143, in apply_subcommands
          schema = super().apply_subcommands(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 1546, in apply_subcommands
          schema = objop.apply(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 2977, in apply
          schema = self._create_innards(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 2945, in _create_innards
          return self.apply_subcommands(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 143, in apply_subcommands
          schema = super().apply_subcommands(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 946, in apply_subcommands
          schema = op.apply(schema, context=context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3445, in apply
          schema = self._alter_innards(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 4410, in _alter_innards
          schema = super()._alter_innards(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3074, in _alter_innards
          return self.apply_subcommands(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 143, in apply_subcommands
          schema = super().apply_subcommands(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 946, in apply_subcommands
          schema = op.apply(schema, context=context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3445, in apply
          schema = self._alter_innards(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 4826, in _alter_innards
          schema = super()._alter_innards(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3074, in _alter_innards
          return self.apply_subcommands(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 143, in apply_subcommands
          schema = super().apply_subcommands(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 946, in apply_subcommands
          schema = op.apply(schema, context=context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3127, in apply
          schema = self._alter_begin(schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 4739, in _alter_begin
          self._alter_pointer_type(self.scls, schema, orig_schema, context)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 3683, in _alter_pointer_type
          self._compile_conversion_expr(
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 3959, in _compile_conversion_expr
          tgt_path_id = irpathid.PathId.from_pointer(
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/ir/pathid.py", line 201, in from_pointer
          prefix = cls.from_pointer(schema, source, namespace=namespace)
        File "/Users/abdellah/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/ir/pathid.py", line 197, in from_pointer
          raise ValueError(f'invalid PathId: {pointer} is not concrete')
      ValueError: invalid PathId: <Link 6594eb62-b4ec-11ec-bd14-f709fa69babe at 0x0x113d8dfc0> is not concrete
```


Discussion:
I get the same error trying to add a new value to an enum that is used in abstract link:

Original schema:

```
  scalar type EmployeeRole extending enum<ADMIN, STAFF, CAREGIVER>;

  abstract link Employee {
    property employee_role -> EmployeeRole;
    property title -> str;

    property created_at -> datetime {
      default := datetime_current();
      readonly := true;
    }
  }
```

Added a value to the `EmployeeRole` enum:

```
  scalar type EmployeeRole extending enum<OWNER, ADMIN, STAFF, CAREGIVER>;
```

Got this error on migration:

```
edgedb error: InternalServerError: invalid PathId: <Link 86344994-b6ea-11ec-8601-3f72ebb9ef36 at 0x0x10f65df40> is not concrete
  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:
      Traceback (most recent call last):
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler_pool/worker.py", line 309, in worker
          res = meth(*args)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler_pool/worker.py", line 202, in compile_in_tx
          units, cstate = COMPILER.compile_in_tx(cstate, *args, **kwargs)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 2148, in compile_in_x
          return self._compile(ctx=ctx, source=source), ctx.state
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1669, in _compile
          return self._try_compile(ctx=ctx, source=source)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1722, in _try_compile
          comp, capabilities = self._compile_dispatch_ql(
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1605, in _compile_dispatch_ql
          query = self._compile_ql_migration(ctx, ql)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 944, in _compile_ql_migration
          query = self._compile_and_apply_ddl_stmt(ctx, ql)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 861, in _compile_and_apply_ddl_stmt
          block, new_types = self._process_delta(ctx, delta)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 342, in _process_delta
          schema = pgdelta.apply(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 5963, in apply
          schema = super().apply(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 1519, in apply
          schema = self.apply_subcommands(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 143, in apply_subcommands
          schema = super().apply_subcommands(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 1546, in apply_subcommands
          schema = objop.apply(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 2977, in apply
          schema = self._create_innards(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 2945, in _create_innards
          return self.apply_subcommands(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 143, in apply_subcommands
          schema = super().apply_subcommands(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 946, in apply_subcommands
          schema = op.apply(schema, context=context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3444, in apply
          schema = self._alter_begin(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 2401, in _alter_begin
          schema = self._undo_everything(schema, context, objs, props)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 2288, in _undo_everything
          schema = acmd.apply(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 1139, in apply
          schema = self.apply_subcommands(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 143, in apply_subcommands
          schema = super().apply_subcommands(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 946, in apply_subcommands
          schema = op.apply(schema, context=context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3445, in apply
          schema = self._alter_innards(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 4410, in _alter_innards
          schema = super()._alter_innards(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3074, in _alter_innards
          return self.apply_subcommands(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 143, in apply_subcommands
          schema = super().apply_subcommands(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 946, in apply_subcommands
          schema = op.apply(schema, context=context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3445, in apply
          schema = self._alter_innards(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 4826, in _alter_innards
          schema = super()._alter_innards(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3074, in _alter_innards
          return self.apply_subcommands(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 143, in apply_subcommands
          schema = super().apply_subcommands(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 946, in apply_subcommands
          schema = op.apply(schema, context=context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/schema/delta.py", line 3127, in apply
          schema = self._alter_begin(schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 4739, in _alter_begin
          self._alter_pointer_type(self.scls, schema, orig_schema, context)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 3683, in _alter_pointer_type
          self._compile_conversion_expr(
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/pgsql/delta.py", line 3959, in _compile_conversion_expr
          tgt_path_id = irpathid.PathId.from_pointer(
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/ir/pathid.py", line 201, in from_pointer
          prefix = cls.from_pointer(schema, source, namespace=namespace)
        File "/Users/edgedb/Library/Application Support/edgedb/portable/1.2/lib/python3.10/site-packages/edb/ir/pathid.py", line 197, in from_pointer
          raise ValueError(f'invalid PathId: {pointer} is not concrete')
      ValueError: invalid PathId: <Link 86344994-b6ea-11ec-8601-3f72ebb9ef36 at 0x0x10f65df40> is not concrete
```


Resolving patch:
diff --git a/edb/edgeql/compiler/options.py b/edb/edgeql/compiler/options.py
--- a/edb/edgeql/compiler/options.py
+++ b/edb/edgeql/compiler/options.py
@@ -120,5 +120,5 @@ class CompilerOptions(GlobalCompilerOptions):
 
     #: A set of schema types and links that should be treated
     #: as singletons in the context of this compilation.
-    singletons: FrozenSet[Union[s_types.Type, s_pointers.Pointer]] = (
+    singletons: Collection[Union[s_types.Type, s_pointers.Pointer]] = (
         frozenset())
diff --git a/edb/pgsql/delta.py b/edb/pgsql/delta.py
--- a/edb/pgsql/delta.py
+++ b/edb/pgsql/delta.py
@@ -4053,10 +4053,13 @@ def _compile_conversion_expr(
             external_rvars = {}
 
             if is_lprop:
-                tgt_path_id = irpathid.PathId.from_pointer(
-                    orig_schema,
-                    pointer,
-                ).src_path()
+                # For linkprops we actually want the source path.
+                # To make it work for abstract links, get the source
+                # path out of the IR's output (to take advantage
+                # of the types we made up for it).
+                # FIXME: Maybe we shouldn't be compiling stuff
+                # for abstract links!
+                tgt_path_id = ir.singletons[0]
             else:
                 tgt_path_id = irpathid.PathId.from_pointer(
                     orig_schema,
diff --git a/edb/schema/pointers.py b/edb/schema/pointers.py
--- a/edb/schema/pointers.py
+++ b/edb/schema/pointers.py
@@ -1321,7 +1321,7 @@ def _compile_expr(
                 schema_object_context=self.get_schema_metaclass(),
                 anchors={qlast.Source().name: source},
                 path_prefix_anchor=qlast.Source().name,
-                singletons=frozenset(singletons),
+                singletons=singletons,
                 apply_query_rewrites=not context.stdmode,
                 track_schema_ref_exprs=track_schema_ref_exprs,
                 in_ddl_context_name=in_ddl_context_name,


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
@@ -13930,6 +13930,28 @@ async def test_edgeql_ddl_switch_link_target(self):
             delete Foo;
         """)
 
+    async def test_edgeql_ddl_set_abs_linkprop_type(self):
+        await self.con.execute(r"""
+            CREATE ABSTRACT LINK orderable {
+                CREATE PROPERTY orderVal -> str {
+                    CREATE DELEGATED CONSTRAINT exclusive;
+                };
+            };
+            CREATE ABSTRACT TYPE Entity;
+            CREATE TYPE Video EXTENDING Entity;
+            CREATE TYPE Topic EXTENDING Entity {
+                CREATE MULTI LINK videos EXTENDING orderable -> Video;
+            };
+        """)
+
+        await self.con.execute(r"""
+            ALTER ABSTRACT LINK orderable {
+                ALTER PROPERTY orderVal {
+                    SET TYPE decimal using (<decimal>@orderVal);
+                };
+            };
+        """)
+
     async def test_edgeql_ddl_set_multi_with_children_01(self):
         await self.con.execute(r"""
             create type Person { create link lover -> Person; };