Repository: edgedb/edgedb

Issue:
Omitting `__subject__` in constraints on object types fails.
Steps to Reproduce:

```
EdgeDB 1.0-alpha.4+dev.145.g4d9ce642
Type "\?" for help.
victor> 
victor> 
victor> create type Vector {
.......     create required property x -> float64;
.......     create required property y -> float64;
....... };
OK: CREATE
victor> alter type Vector { create constraint expression on (.x^2 + .y^2 < 25) };
error: could not resolve partial path 
  ┌─ query:1:54
  │
1 │ alter type Vector { create constraint expression on (.x^2 + .y^2 < 25) };
  │                                                      ^^^ error
```

Ideally, the short path should assume `__subject__` as its start.


Discussion:

Resolving patch:
diff --git a/edb/pgsql/schemamech.py b/edb/pgsql/schemamech.py
--- a/edb/pgsql/schemamech.py
+++ b/edb/pgsql/schemamech.py
@@ -34,6 +34,7 @@
 
 from edb.schema import scalars as s_scalars
 from edb.schema import utils as s_utils
+from edb.schema import types as s_types
 
 from edb.common import ast
 
@@ -227,11 +228,16 @@ def schema_constraint_to_backend_constraint(
             cls, subject, constraint, schema):
         assert constraint.get_subject(schema) is not None
 
+        path_prefix_anchor = (
+            qlast.Subject().name if isinstance(subject, s_types.Type)
+            else None
+        )
         ir = qlcompiler.compile_ast_to_ir(
             constraint.get_finalexpr(schema).qlast,
             schema,
             options=qlcompiler.CompilerOptions(
                 anchors={qlast.Subject().name: subject},
+                path_prefix_anchor=path_prefix_anchor,
             ),
         )
 
diff --git a/edb/schema/constraints.py b/edb/schema/constraints.py
--- a/edb/schema/constraints.py
+++ b/edb/schema/constraints.py
@@ -404,12 +404,17 @@ def compile_expr_field(
 
             elif field.name in {'subjectexpr', 'finalexpr'}:
                 anchors = {'__subject__': referrer_ctx.op.scls}
+                path_prefix_anchor = (
+                    '__subject__'
+                    if isinstance(referrer_ctx.op.scls, s_types.Type) else None
+                )
                 return s_expr.Expression.compiled(
                     value,
                     schema=schema,
                     options=qlcompiler.CompilerOptions(
                         modaliases=context.modaliases,
                         anchors=anchors,
+                        path_prefix_anchor=path_prefix_anchor,
                         allow_generic_type_output=True,
                         schema_object_context=self.get_schema_metaclass(),
                     ),
@@ -826,11 +831,17 @@ def _populate_concrete_constraint_attrs(
             expr_context = None
 
         assert subject is not None
+        path_prefix_anchor = (
+            qlast.Subject().name if isinstance(subject, s_types.Type)
+            else None
+        )
+
         final_expr = s_expr.Expression.compiled(
             s_expr.Expression.from_ast(expr_ql, schema, {}),
             schema=schema,
             options=qlcompiler.CompilerOptions(
                 anchors={qlast.Subject().name: subject},
+                path_prefix_anchor=path_prefix_anchor,
             ),
         )
 
@@ -853,6 +864,7 @@ def _populate_concrete_constraint_attrs(
                 schema=schema,
                 options=qlcompiler.CompilerOptions(
                     anchors={qlast.Subject().name: subject},
+                    path_prefix_anchor=path_prefix_anchor,
                     singletons=frozenset({subject_obj}),
                 ),
             )


Test patch:
diff --git a/tests/test_constraints.py b/tests/test_constraints.py
--- a/tests/test_constraints.py
+++ b/tests/test_constraints.py
@@ -1223,3 +1223,24 @@ async def test_constraints_tuple(self):
                     INSERT Transaction {
                         credit := (nest := (amount := 1, currency := "usd")) };
                 """)
+
+    async def test_constraints_partial_path(self):
+        async with self._run_and_rollback():
+            await self.con.execute('''\
+                CREATE TYPE Vector {
+                    CREATE PROPERTY x -> float64;
+                    CREATE PROPERTY y -> float64;
+                    CREATE CONSTRAINT expression ON (
+                        .x^2 + .y^2 < 25
+                    );
+                };
+            ''')
+
+            await self.con.execute(r"""
+                INSERT Vector { x := 3, y := 3 };
+            """)
+
+            with self.assertRaises(edgedb.ConstraintViolationError):
+                await self.con.execute(r"""
+                    INSERT Vector { x := 4, y := 4 };
+                """)