Repository: edgedb/edgedb

Issue:
WITH bound variables in aliases create views that don't get deleted
1. Use the branch in #5977 (`auth-jwt` branch)
2. Add extensions (`create extension pgcrypto; create extension auth;`)
3. Attempt to drop `auth` (`drop extension auth;`).

I'm getting:

```
edgedb error: SchemaError: cannot drop module 'ext::auth' because it is not empty
```

I suspect this is due to aliases in the `auth` schema.


Discussion:
Definitely a alias issue; not actually related to extensions even, I think.
```
type X;
alias Z := (with lol := X, count(lol));
```
Trying to migrate that schema to empty fails.

Resolving patch:
diff --git a/edb/schema/expraliases.py b/edb/schema/expraliases.py
--- a/edb/schema/expraliases.py
+++ b/edb/schema/expraliases.py
@@ -68,6 +68,24 @@ class AliasCommandContext(
     pass
 
 
+def _is_view_from_alias(
+    our_name: sn.QualName,
+    obj: s_types.Type,
+    schema: s_schema.Schema,
+) -> bool:
+    name = obj.get_name(schema)
+    if our_name == name:
+        return True
+    name_prefix = f'__{our_name.name}__'
+
+    name = obj.get_name(schema)
+    return (
+        isinstance(name, sn.QualName)
+        and name.module == our_name.module
+        and name.name.startswith(name_prefix)
+    )
+
+
 class AliasLikeCommand(
     sd.QualifiedObjectCommand[so.QualifiedObject_T],
 ):
@@ -118,20 +136,17 @@ def _get_created_types(
         typ = cls.get_type(scls, schema)
         our_name = typ.get_name(schema)
         assert isinstance(our_name, sn.QualName)
-        name_prefix = f'__{our_name.name}__'
 
         # XXX: This is pretty unfortunate from a performance
         # perspective, and not technically correct either.
-        # For 3.x we should track this information in the objects
+        # For 4.x we should track this information in the objects
         # (or possibly instead ensure we do not put any types in the schema
         # that are not directly part of the output type.)
         for obj in schema.get_objects(exclude_stdlib=True, type=s_types.Type):
-            name = obj.get_name(schema)
             if (
                 obj.get_alias_is_persistent(schema)
-                and isinstance(name, sn.QualName)
-                and name.module == our_name.module
-                and name.name.startswith(name_prefix)
+                and obj != typ
+                and _is_view_from_alias(our_name, obj, schema)
             ):
                 objs.add(obj)
 
@@ -496,6 +511,8 @@ def define_alias(
     old_schema: Optional[s_schema.Schema] = None
 
     for vt in ir.views.values():
+        if not _is_view_from_alias(classname, vt, new_schema):
+            continue
         if isinstance(vt, s_types.Collection):
             coll_expr_aliases.append(vt)
         elif prev_expr is not None or not schema.has_object(vt.id):
@@ -510,6 +527,8 @@ def define_alias(
         prev_ir = prev_expr.irast
         old_schema = prev_ir.schema
         for vt in prev_ir.views.values():
+            if not _is_view_from_alias(classname, vt, old_schema):
+                continue
             if isinstance(vt, s_types.Collection):
                 prev_coll_expr_aliases.append(vt)
             else:


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
@@ -9678,6 +9678,18 @@ async def test_edgeql_ddl_alias_10(self):
             alter alias X using (Bar);
         """)
 
+    async def test_edgeql_ddl_alias_11(self):
+        await self.con.execute(r"""
+            create type X;
+            create alias Z := (with lol := X, select count(lol));
+        """)
+        await self.con.execute(r"""
+            drop alias Z
+        """)
+        await self.con.execute(r"""
+            create alias Z := (with lol := X, select count(lol));
+        """)
+
     async def test_edgeql_ddl_inheritance_alter_01(self):
         await self.con.execute(r"""
             CREATE TYPE InhTest01 {
diff --git a/tests/test_schema.py b/tests/test_schema.py
--- a/tests/test_schema.py
+++ b/tests/test_schema.py
@@ -5102,6 +5102,12 @@ def test_schema_migrations_equivalence_57b(self):
             global TwoUsers := (User);
         """])
 
+    def test_schema_migrations_equivalence_57c(self):
+        self._assert_migration_equivalence([r"""
+            type X;
+            alias Z := (with lol := X, select count(lol));
+        """])
+
     def test_schema_migrations_equivalence_58(self):
         self._assert_migration_equivalence([r"""
             abstract type C {