Repository: edgedb/edgedb

Issue:
Bug in constraint inheritance
```
START TRANSACTION;
CREATE ABSTRACT TYPE default::T;
CREATE ABSTRACT TYPE default::Sub1 EXTENDING default::T;
CREATE TYPE default::Sub2 EXTENDING default::Sub1, default::T;
ALTER TYPE default::T {
    CREATE PROPERTY foo -> std::str {
        CREATE CONSTRAINT std::exclusive;
    };
};
ROLLBACK;
```

Results in:

```
edgedb error: InternalServerError: column old.10370c55-36a9-11ed-89f4-638cbd27bcf9 does not exist
```


Discussion:

Resolving patch:
diff --git a/edb/pgsql/dbops/base.py b/edb/pgsql/dbops/base.py
--- a/edb/pgsql/dbops/base.py
+++ b/edb/pgsql/dbops/base.py
@@ -335,9 +335,6 @@ def as_markup(cls, self, *, ctx):
     def __iter__(self):
         return iter(self.commands)
 
-    def __call__(self, typ):
-        return filter(lambda i: isinstance(i, typ), self.commands)
-
     def __len__(self):
         return len(self.commands)
 
diff --git a/edb/pgsql/delta.py b/edb/pgsql/delta.py
--- a/edb/pgsql/delta.py
+++ b/edb/pgsql/delta.py
@@ -244,7 +244,8 @@ def schedule_post_inhview_update_command(
         self,
         schema: s_schema.Schema,
         context: sd.CommandContext,
-        cmd: sd.Command,
+        cmd: sd.Command | Callable[
+            [s_schema.Schema, sd.CommandContext], MetaCommand],
         ctxcls: Type[sd.CommandContextToken[sd.Command]],
     ) -> None:
         ctx = context.get_topmost_ancestor(ctxcls)
@@ -2140,10 +2141,16 @@ def apply(self, schema, context):
                 and isinstance(
                     subject, (s_objtypes.ObjectType, s_pointers.Pointer))
                 and not context.is_creating(subject)
+                and not context.is_deleting(subject)
             ):
                 op = self.enforce_constraint(
                     constraint, schema, context, self.source_context)
-                self.pgops.add(op)
+                self.schedule_post_inhview_update_command(
+                    schema,
+                    context,
+                    (lambda nschema, ncontext:
+                     op if nschema.has_object(subject.id) else None),
+                    s_sources.SourceCommandContext)
 
             self.pgops.add(self.fixup_base_constraint_triggers(
                 constraint, orig_schema, schema, context, self.source_context,
@@ -3077,7 +3084,12 @@ def apply_scheduled_inhview_updates(
                     self.alter_inhview(
                         schema, context, s, alter_ancestors=False)
 
-        self.pgops.update(self.post_inhview_update_commands)
+        for post_cmd in self.post_inhview_update_commands:
+            if callable(post_cmd):
+                if op := post_cmd(schema, context):
+                    self.pgops.add(op)
+            else:
+                self.pgops.add(post_cmd)
 
 
 class IndexCommand(MetaCommand):


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
@@ -10266,6 +10266,18 @@ async def test_edgeql_ddl_constraint_alter_08(self):
                 insert Foo { foo := "x" }; insert Bar { foo := "x" };
             """)
 
+    async def test_edgeql_ddl_constraint_alter_09(self):
+        await self.con.execute(r"""
+            CREATE ABSTRACT TYPE default::T;
+            CREATE ABSTRACT TYPE default::Sub1 EXTENDING default::T;
+            CREATE TYPE default::Sub2 EXTENDING default::Sub1, default::T;
+            ALTER TYPE default::T {
+                CREATE PROPERTY foo -> std::str {
+                    CREATE CONSTRAINT std::exclusive;
+                };
+            };
+        """)
+
     async def test_edgeql_ddl_drop_inherited_link(self):
         await self.con.execute(r"""
             CREATE TYPE Target;