Repository: edgedb/edgedb

Issue:
Incorrect cardinality inference on link property index
Trying to generate a migration for this schema:

```
abstract link link_with_value {
  single property value -> int64;
  index on (__subject__@value);
}
```

But seeing this:

```
$ edgedb migration create
edgedb error: ResultCardinalityMismatchError: possibly more than one element returned by the index expression where only singletons are allowed
```

It seems the cardinality of `__subject__@value` is being misinferred.


Discussion:

Resolving patch:
diff --git a/edb/pgsql/types.py b/edb/pgsql/types.py
--- a/edb/pgsql/types.py
+++ b/edb/pgsql/types.py
@@ -462,11 +462,6 @@ def _get_ptrref_storage_info(
 
     target = ptrref.out_target
 
-    if is_lprop and str(ptrref.std_parent_name) == 'std::target':
-        # Normalize link@target to link
-        ptrref = source
-        is_lprop = False
-
     if isinstance(ptrref, irast.TupleIndirectionPointerRef):
         table = None
         table_type = 'ObjectType'
@@ -476,8 +471,8 @@ def _get_ptrref_storage_info(
         table = common.get_pointer_backend_name(
             source.id, source.name.module, catenate=False)
         table_type = 'link'
-        if ptrref.shortname.name == 'source':
-            col_name = 'source'
+        if ptrref.shortname.name in ('source', 'target'):
+            col_name = ptrref.shortname.name
         else:
             col_name = str(ptrref.id)
     else:
diff --git a/edb/schema/indexes.py b/edb/schema/indexes.py
--- a/edb/schema/indexes.py
+++ b/edb/schema/indexes.py
@@ -276,8 +276,6 @@ def compile_expr_field(
         value: s_expr.Expression,
         track_schema_ref_exprs: bool=False,
     ) -> s_expr.Expression:
-        from . import objtypes as s_objtypes
-
         singletons: List[s_types.Type]
         if field.name == 'expr':
             # type ignore below, for the class is used as mixin
@@ -290,11 +288,8 @@ def compile_expr_field(
             subject = parent_ctx.op.get_object(schema, context)
 
             if isinstance(subject, s_abc.Pointer):
-                singletons = []
                 path_prefix_anchor = None
             else:
-                assert isinstance(subject, s_objtypes.ObjectType)
-                singletons = [subject]
                 path_prefix_anchor = qlast.Subject().name
 
             expr = type(value).compiled(
@@ -305,7 +300,7 @@ def compile_expr_field(
                     schema_object_context=self.get_schema_metaclass(),
                     anchors={qlast.Subject().name: subject},
                     path_prefix_anchor=path_prefix_anchor,
-                    singletons=frozenset(singletons),
+                    singletons=frozenset([subject]),
                     apply_query_rewrites=not context.stdmode,
                     track_schema_ref_exprs=track_schema_ref_exprs,
                 ),


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
@@ -2957,6 +2957,23 @@ async def test_edgeql_ddl_link_property_06(self):
                 };
             """)
 
+    async def test_edgeql_ddl_link_property_07(self):
+        await self.con.execute("""
+            CREATE ABSTRACT LINK link_with_value {
+                CREATE SINGLE PROPERTY value -> int64;
+                CREATE INDEX on (__subject__@value);
+                CREATE INDEX on ((__subject__@source, __subject__@value));
+                CREATE INDEX on ((__subject__@target, __subject__@value));
+                # FIXME: this is broken
+                # CREATE INDEX on ((__subject__, __subject__@value));
+            };
+
+            CREATE TYPE Tgt;
+            CREATE TYPE Foo {
+                CREATE LINK l1 EXTENDING link_with_value -> Tgt;
+            };
+        """)
+
     async def test_edgeql_ddl_bad_01(self):
         with self.assertRaisesRegex(
                 edgedb.InvalidReferenceError,