Skip to content

Commit

Permalink
Allow except in link constraints. (#7250)
Browse files Browse the repository at this point in the history
Enables schemas like this:
```
    create type Foo;
    create type ExceptTest {
        create link l -> Foo {
            create property flag -> bool;
            create constraint always_fail except (@Flag);
        };
    };
```
  • Loading branch information
dnwpark authored Apr 23, 2024
1 parent ed8d99c commit 344b401
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 20 deletions.
9 changes: 8 additions & 1 deletion edb/pgsql/schemamech.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ def compile_constraint(
assert isinstance(ir, irast.Statement)
assert isinstance(ir.expr.expr, irast.SelectStmt)

except_ir: Optional[irast.Statement] = None
except_data = None
if except_expr := constraint.get_except_expr(schema):
assert isinstance(except_expr, s_expr.Expression)
Expand All @@ -270,7 +271,13 @@ def compile_constraint(
)
except_data = _edgeql_tree_to_expr_data(except_sql.ast)

terminal_refs = ir_utils.get_longest_paths(ir.expr.expr.result)
terminal_refs: set[irast.Set] = (
ir_utils.get_longest_paths(ir.expr.expr.result)
)
if except_ir is not None:
terminal_refs.update(
ir_utils.get_longest_paths(except_ir.expr)
)
ref_tables = get_ref_storage_info(ir.schema, terminal_refs)

if len(ref_tables) > 1:
Expand Down
6 changes: 0 additions & 6 deletions edb/schema/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -871,12 +871,6 @@ def _populate_concrete_constraint_attrs(
)

except_expr: s_expr.Expression | None = attrs.get('except_expr')
if except_expr:
if isinstance(subject, s_pointers.Pointer):
raise errors.InvalidConstraintDefinitionError(
"only object constraints may use EXCEPT",
span=sourcectx
)

if subjectexpr is not None:
options = qlcompiler.CompilerOptions(
Expand Down
51 changes: 38 additions & 13 deletions tests/test_edgeql_ddl.py
Original file line number Diff line number Diff line change
Expand Up @@ -10507,27 +10507,52 @@ async def test_edgeql_ddl_constraint_18(self):
else:
await op

@test.xerror('only object constraints may use EXCEPT')
async def test_edgeql_ddl_constraint_19(self):
# This is pretty marginal, but make sure we can distinguish
# on and except in name creation;
# Make sure we distinguish between on and except in name creation;
await self.con.execute(r"""
create abstract constraint always_ok extending constraint {
using (true)
create abstract constraint always_fail extending constraint {
using (false)
};
create type Foo;
create type OnTest {
create link l -> Foo {
create property flag -> bool;
create constraint always_fail on (@flag);
};
};
""")

await self.con.execute(r"""
create type ExceptTest {
create property b -> bool;
create property e -> bool;
create link l -> Object {
create constraint always_ok except (.e);
create constraint always_ok on (.e);
create link l -> Foo {
create property flag -> bool;
create constraint always_fail except (@flag);
};
};
""")

async with self.assertRaisesRegexTx(
edgedb.ConstraintViolationError,
r'invalid l'):
await self.con.execute("""
insert OnTest { l := (insert Foo) { @flag := false } }
""")

async with self.assertRaisesRegexTx(
edgedb.ConstraintViolationError,
r'invalid l'):
await self.con.execute("""
insert OnTest { l := (insert Foo) { @flag := true } }
""")

async with self.assertRaisesRegexTx(
edgedb.ConstraintViolationError,
r'invalid l'):
await self.con.execute("""
insert ExceptTest { l := (insert Foo) { @flag := false } }
""")

await self.con.execute("""
insert ExceptTest { l := (insert Foo) { @flag := true } }
""")

async def test_edgeql_ddl_constraint_20(self):
async with self.assertRaisesRegexTx(
edgedb.InvalidConstraintDefinitionError,
Expand Down

0 comments on commit 344b401

Please sign in to comment.