Repository: edgedb/edgedb

Issue:
Renaming between modules broken
```
CREATE MODULE foo;
CREATE MODULE test;

CREATE TYPE test::Note {
    CREATE PROPERTY note -> str;
};
ALTER TYPE test::Note RENAME TO foo::Note;
DROP TYPE foo::Note;
```
fails with "cannot drop column id of table "edgedb_363de41f-0ffa-11eb-b2d3-bd7de72d02be"."363e70c1-0ffa-11eb-8f58-83d1b0e048ab" because other objects depend on it".

`ALTER TYPE foo::Note DROP PROPERTY note;`
fails with `ERROR: InvalidReferenceError: property 'note' does not exist`

Renaming it back to `test::Note` and both drops will fail with SQL errors.


Discussion:

Resolving patch:
diff --git a/edb/schema/delta.py b/edb/schema/delta.py
--- a/edb/schema/delta.py
+++ b/edb/schema/delta.py
@@ -2294,7 +2294,7 @@ def _fix_referencing_expr(
         assert compiled.irast.schema_ref_exprs is not None
 
         # Now that the compilation is done, try to do the fixup.
-        new_shortname = sn.shortname_from_fullname(self.new_name).name
+        new_shortname = sn.shortname_from_fullname(self.new_name)
         old_shortname = sn.shortname_from_fullname(self.classname).name
         for ref in compiled.irast.schema_ref_exprs.get(self.scls, []):
             if isinstance(ref, qlast.Ptr):
@@ -2302,7 +2302,9 @@ def _fix_referencing_expr(
             assert isinstance(ref, qlast.ObjectRef), (
                 f"only support object refs but got {ref}")
             assert ref.name == old_shortname, (ref.name, old_shortname)
-            ref.name = new_shortname
+            ref.name = new_shortname.name
+            if new_shortname.module != "__":
+                ref.module = new_shortname.module
 
         # say as_fragment=True as a hack to avoid renormalizing it
         out = s_expr.Expression.from_ast(


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
@@ -6643,6 +6643,63 @@ async def test_edgeql_ddl_change_module_01(self):
             DROP TYPE foo::Note;
         """)
 
+    async def test_edgeql_ddl_change_module_02(self):
+        await self.con.execute("""
+            CREATE MODULE foo;
+
+            CREATE TYPE test::Parent {
+                CREATE PROPERTY note -> str;
+            };
+            CREATE TYPE test::Sub EXTENDING test::Parent;
+            ALTER TYPE test::Parent RENAME TO foo::Parent;
+            DROP TYPE test::Sub;
+            DROP TYPE foo::Parent;
+        """)
+
+    async def test_edgeql_ddl_change_module_03(self):
+        await self.con.execute("""
+            CREATE MODULE foo;
+
+            CREATE TYPE test::Note {
+                CREATE PROPERTY note -> str {
+                    CREATE CONSTRAINT exclusive;
+                }
+            };
+            ALTER TYPE test::Note RENAME TO foo::Note;
+            DROP TYPE foo::Note;
+        """)
+
+    async def test_edgeql_ddl_change_module_04(self):
+        await self.con.execute("""
+            CREATE MODULE foo;
+
+            CREATE TYPE test::Tag;
+
+            CREATE TYPE test::Note {
+                CREATE SINGLE LINK tags -> test::Tag {
+                    ON TARGET DELETE DELETE SOURCE;
+                }
+            };
+
+            INSERT test::Note { tags := (INSERT test::Tag) };
+        """)
+
+        await self.con.execute("""
+            ALTER TYPE test::Tag RENAME TO foo::Tag;
+            DELETE foo::Tag FILTER true;
+        """)
+
+        await self.assert_query_result(
+            """SELECT test::Note;""",
+            [],
+        )
+
+        await self.con.execute("""
+            ALTER TYPE test::Note RENAME TO foo::Note;
+            DROP TYPE foo::Note;
+            DROP TYPE foo::Tag;
+        """)
+
     async def _simple_rename_ref_test(
         self,
         ddl,
@@ -6650,6 +6707,7 @@ async def _simple_rename_ref_test(
         *,
         rename_type,
         rename_prop,
+        rename_module,
         type_extra=0,
         prop_extra=0,
         type_refs=1,
@@ -6682,41 +6740,60 @@ async def _simple_rename_ref_test(
                 {prop_rename.lstrip()}
             }}
         """)
+        if rename_module:
+            await self.con.execute(f"""
+            CREATE MODULE foo;
+            ALTER TYPE test::Note RENAME TO foo::Note;
+            """)
 
-        res = await self.con.query_one("""
-            DESCRIBE MODULE test
-        """)
+        else:
+            res = await self.con.query_one("""
+                DESCRIBE MODULE test
+            """)
 
-        total_type = 1 + type_refs
-        num_type_orig = 0 if rename_type else total_type
-        self.assertEqual(res.count("Note"), num_type_orig + type_extra)
-        self.assertEqual(res.count("Remark"), total_type - num_type_orig)
-        total_prop = 1 + prop_refs
-        num_prop_orig = 0 if rename_prop else total_prop
-        self.assertEqual(res.count("note"), num_prop_orig + type_extra)
-        self.assertEqual(res.count("remark"), total_prop - num_prop_orig)
+            total_type = 1 + type_refs
+            num_type_orig = 0 if rename_type else total_type
+            self.assertEqual(res.count("Note"), num_type_orig + type_extra)
+            self.assertEqual(res.count("Remark"), total_type - num_type_orig)
+            total_prop = 1 + prop_refs
+            num_prop_orig = 0 if rename_prop else total_prop
+            self.assertEqual(res.count("note"), num_prop_orig + type_extra)
+            self.assertEqual(res.count("remark"), total_prop - num_prop_orig)
 
         if cleanup:
             if rename_prop:
                 cleanup = cleanup.replace("note", "remark")
             if rename_type:
                 cleanup = cleanup.replace("Note", "Remark")
-                await self.con.execute(f"""
-                    WITH MODULE test
-                    {cleanup.lstrip()}
-                """)
+            if rename_module:
+                cleanup = cleanup.replace("test", "foo")
+            await self.con.execute(f"""
+                WITH MODULE test
+                {cleanup.lstrip()}
+            """)
 
     async def _simple_rename_ref_tests(self, ddl, cleanup=None, **kwargs):
         """Do the three interesting invocations of _simple_rename_ref_test"""
         async with self._run_and_rollback():
             await self._simple_rename_ref_test(
-                ddl, cleanup, rename_type=False, rename_prop=True, **kwargs)
+                ddl, cleanup,
+                rename_type=False, rename_prop=True, rename_module=False,
+                **kwargs)
+        async with self._run_and_rollback():
+            await self._simple_rename_ref_test(
+                ddl, cleanup,
+                rename_type=True, rename_prop=False, rename_module=False,
+                **kwargs)
         async with self._run_and_rollback():
             await self._simple_rename_ref_test(
-                ddl, cleanup, rename_type=True, rename_prop=False, **kwargs)
+                ddl, cleanup,
+                rename_type=True, rename_prop=True, rename_module=False,
+                **kwargs)
         async with self._run_and_rollback():
             await self._simple_rename_ref_test(
-                ddl, cleanup, rename_type=True, rename_prop=True, **kwargs)
+                ddl, cleanup,
+                rename_type=False, rename_prop=False, rename_module=True,
+                **kwargs)
 
     async def test_edgeql_ddl_rename_ref_function_01(self):
         await self._simple_rename_ref_tests(
@@ -6726,7 +6803,7 @@ async def test_edgeql_ddl_rename_ref_function_01(self):
                                (SELECT Note.note LIMIT 1)))
             }
             """,
-            """DROP FUNCTION foo(x: Note);""",
+            """DROP FUNCTION foo(x: test::Note);""",
             type_extra=1,
             prop_extra=1,
             type_refs=2,
@@ -6855,7 +6932,7 @@ async def test_edgeql_ddl_rename_ref_constraint_01(self):
     async def test_edgeql_ddl_rename_ref_index_01(self):
         await self._simple_rename_ref_tests(
             """ALTER TYPE Note CREATE INDEX ON (.note);""",
-            """ALTER TYPE Note DROP INDEX ON (.note);""",
+            """ALTER TYPE test::Note DROP INDEX ON (.note);""",
             type_refs=0,
         )
 
@@ -6882,7 +6959,7 @@ async def test_edgeql_ddl_rename_ref_computable_01(self):
                 CREATE PROPERTY x := .note ++ "!";
             };
             """,
-            """ALTER TYPE Note DROP PROPERTY x;""",
+            """ALTER TYPE test::Note DROP PROPERTY x;""",
             type_refs=0,
         )