Repository: edgedb/edgedb

Issue:
`graphql` test database doesn't migrate to empty cleanly
I haven't fully triaged this yet, but there seem to be at least two problems:
 * Some sort of cycle issue between User.fav_issues and Person.favorites
 * `TwoUsers` not having all of the types created as part of it properly cleaned up



Discussion:

Resolving patch:
diff --git a/edb/schema/pointers.py b/edb/schema/pointers.py
--- a/edb/schema/pointers.py
+++ b/edb/schema/pointers.py
@@ -801,21 +801,21 @@ def singular(
     def get_implicit_bases(self, schema: s_schema.Schema) -> List[Pointer]:
         bases = super().get_implicit_bases(schema)
 
-        # True implicit bases for pointers will have a different source.
-        my_source = self.get_source(schema)
+        # True implicit bases for pointers will have the same name
+        my_name = self.get_shortname(schema)
         return [
             b for b in bases
-            if b.get_source(schema) != my_source
+            if b.get_shortname(schema) == my_name
         ]
 
     def get_implicit_ancestors(self, schema: s_schema.Schema) -> List[Pointer]:
         ancestors = super().get_implicit_ancestors(schema)
 
-        # True implicit ancestors for pointers will have a different source.
-        my_source = self.get_source(schema)
+        # True implicit ancestors for pointers will have the same name
+        my_name = self.get_shortname(schema)
         return [
             b for b in ancestors
-            if b.get_source(schema) != my_source
+            if b.get_shortname(schema) == my_name
         ]
 
     def has_user_defined_properties(self, schema: s_schema.Schema) -> bool:
diff --git a/edb/schema/referencing.py b/edb/schema/referencing.py
--- a/edb/schema/referencing.py
+++ b/edb/schema/referencing.py
@@ -1349,7 +1349,7 @@ def _alter_begin(
             # Distinguish between actual local name change and fully-qualified
             # name change due to structural parent rename.
             if orig_ref_lname != new_ref_lname:
-                implicit_bases = scls.get_implicit_bases(schema)
+                implicit_bases = scls.get_implicit_bases(orig_schema)
                 non_renamed_bases = {
                     x for x in implicit_bases if x not in context.renamed_objs}
                 # This object is inherited from one or more ancestors that
diff --git a/edb/testbase/server.py b/edb/testbase/server.py
--- a/edb/testbase/server.py
+++ b/edb/testbase/server.py
@@ -1081,11 +1081,15 @@ async def create_db():
             if script:
                 cls.loop.run_until_complete(cls.con.execute(script))
 
+    @staticmethod
+    def get_set_up():
+        return os.environ.get('EDGEDB_TEST_CASES_SET_UP', 'run')
+
     @classmethod
     def tearDownClass(cls):
         script = ''
 
-        class_set_up = os.environ.get('EDGEDB_TEST_CASES_SET_UP', 'run')
+        class_set_up = cls.get_set_up()
 
         if cls.TEARDOWN and class_set_up != 'skip':
             script = cls.TEARDOWN.strip()
@@ -1411,6 +1415,11 @@ async def check_dump_restore_single_db(self, check_method):
             await asyncio.to_thread(
                 self.run_cli, '-d', dbname, 'restore', f.name
             )
+
+        # Cycle the connection to avoid state mismatches
+        await self.con.aclose()
+        self.con = await self.connect(database=dbname)
+
         await check_method(self)
 
     async def check_dump_restore(self, check_method):
@@ -1489,6 +1498,9 @@ def setUpClass(cls):
         except ImportError:
             raise unittest.SkipTest('SQL tests skipped: asyncpg not installed')
 
+        if cls.get_set_up() == 'inplace':
+            raise unittest.SkipTest('SQL dump tests skipped in single db mode')
+
         super().setUpClass()
         conargs = cls.get_connect_args()
         src_dbname = cls.con.dbname


Test patch:
diff --git a/tests/test_edgeql_explain.py b/tests/test_edgeql_explain.py
--- a/tests/test_edgeql_explain.py
+++ b/tests/test_edgeql_explain.py
@@ -83,7 +83,6 @@ async def test_edgeql_explain_simple_01(self):
                     "actual_rows": 1,
                     "plan_rows": 1,
                     "plan_type": "IndexScan",
-                    "plan_width": 32,
                     "properties": tb.bag([
                         {
                             "important": False,
@@ -121,7 +120,7 @@ async def test_edgeql_explain_simple_01(self):
                             "type": "expr",
                         },
                     ]),
-                    "startup_cost": 0.28,
+                    "startup_cost": float,
                 }
             ],
             "subplans": [],
@@ -157,7 +156,6 @@ async def test_edgeql_explain_with_bound_01(self):
                     "actual_rows": 1,
                     "plan_rows": 1,
                     "plan_type": "SubqueryScan",
-                    "plan_width": 32,
                     "properties": tb.bag([
                         {
                             "important": False,
@@ -165,8 +163,8 @@ async def test_edgeql_explain_with_bound_01(self):
                             "type": "expr",
                         },
                     ]),
-                    "startup_cost": 278.1,
-                    "total_cost": 278.12,
+                    "startup_cost": float,
+                    "total_cost": float,
                 }
             ],
             "subplans": [
@@ -184,7 +182,6 @@ async def test_edgeql_explain_with_bound_01(self):
                             "actual_rows": 1,
                             "plan_rows": 1,
                             "plan_type": "Aggregate",
-                            "plan_width": 32,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -211,15 +208,14 @@ async def test_edgeql_explain_with_bound_01(self):
                                     "value": "Simple",
                                 },
                             ]),
-                            "startup_cost": 8.3,
-                            "total_cost": 8.31,
+                            "startup_cost": float,
+                            "total_cost": float,
                         },
                         {
                             "actual_loops": 1,
                             "actual_rows": 1,
                             "plan_rows": 1,
                             "plan_type": "IndexScan",
-                            "plan_width": 16,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -269,8 +265,8 @@ async def test_edgeql_explain_with_bound_01(self):
                                     "type": "expr",
                                 },
                             ]),
-                            "startup_cost": 0.28,
-                            "total_cost": 8.3,
+                            "startup_cost": float,
+                            "total_cost": float,
                         },
                     ],
                     "subplans": [],
@@ -289,7 +285,6 @@ async def test_edgeql_explain_with_bound_01(self):
                             "actual_rows": 1,
                             "plan_rows": 1,
                             "plan_type": "Aggregate",
-                            "plan_width": 32,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -316,15 +311,14 @@ async def test_edgeql_explain_with_bound_01(self):
                                     "value": "Simple",
                                 },
                             ]),
-                            "startup_cost": 269.78,
-                            "total_cost": 269.79,
+                            "startup_cost": float,
+                            "total_cost": float,
                         },
                         {
                             "actual_loops": 1,
                             "actual_rows": 1,
                             "plan_rows": 5,
                             "plan_type": "SeqScan",
-                            "plan_width": 16,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -354,8 +348,8 @@ async def test_edgeql_explain_with_bound_01(self):
                                     "type": "relation",
                                 },
                             ]),
-                            "startup_cost": 0.0,
-                            "total_cost": 269.76,
+                            "startup_cost": float,
+                            "total_cost": float,
                         },
                     ],
                     "subplans": [],
@@ -383,7 +377,6 @@ async def test_edgeql_explain_multi_link_01(self):
                     "actual_rows": 1,
                     "plan_rows": 1,
                     "plan_type": "IndexScan",
-                    "plan_width": 32,
                     "properties": tb.bag([
                         {
                             "important": False,
@@ -437,7 +430,6 @@ async def test_edgeql_explain_multi_link_01(self):
                             "actual_rows": 1,
                             "plan_rows": 1,
                             "plan_type": "Aggregate",
-                            "plan_width": 32,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -470,7 +462,6 @@ async def test_edgeql_explain_multi_link_01(self):
                             "actual_rows": 2,
                             "plan_rows": 2,
                             "plan_type": "NestedLoop",
-                            "plan_width": 32,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -495,7 +486,6 @@ async def test_edgeql_explain_multi_link_01(self):
                                     "actual_rows": 2,
                                     "plan_rows": 2,
                                     "plan_type": "IndexOnlyScan",
-                                    "plan_width": 16,
                                     # This has property `heap_fetches`
                                     # that vary on github an locally.
                                     # So skip checking "properties"
@@ -510,7 +500,6 @@ async def test_edgeql_explain_multi_link_01(self):
                                     "actual_rows": 1,
                                     "plan_rows": 1,
                                     "plan_type": "IndexScan",
-                                    "plan_width": 32,
                                     "properties": tb.bag([
                                         {
                                             "important": False,
@@ -592,7 +581,6 @@ async def test_edgeql_explain_computed_backlink_01(self):
                     "actual_rows": 1,
                     "plan_rows": 1,
                     "plan_type": "IndexScan",
-                    "plan_width": 32,
                     "properties": tb.bag([
                         {
                             "important": False,
@@ -630,8 +618,8 @@ async def test_edgeql_explain_computed_backlink_01(self):
                             "type": "expr",
                         },
                     ]),
-                    "startup_cost": 0.28,
-                    "total_cost": 16.69,
+                    "startup_cost": float,
+                    "total_cost": float,
                 }
             ],
             "subplans": [
@@ -656,7 +644,6 @@ async def test_edgeql_explain_computed_backlink_01(self):
                             "actual_rows": 1,
                             "plan_rows": 1,
                             "plan_type": "Aggregate",
-                            "plan_width": 32,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -683,15 +670,14 @@ async def test_edgeql_explain_computed_backlink_01(self):
                                     "value": "Simple",
                                 },
                             ]),
-                            "startup_cost": 8.38,
-                            "total_cost": 8.39,
+                            "startup_cost": float,
+                            "total_cost": float,
                         },
                         {
                             "actual_loops": 1,
                             "actual_rows": 2,
                             "plan_rows": 5,
                             "plan_type": "Result",
-                            "plan_width": 32,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -706,15 +692,14 @@ async def test_edgeql_explain_computed_backlink_01(self):
                                     "value": '("User~2".id = "User~2".id)',
                                 },
                             ]),
-                            "startup_cost": 0.28,
-                            "total_cost": 8.37,
+                            "startup_cost": float,
+                            "total_cost": float,
                         },
                         {
                             "actual_loops": 1,
                             "actual_rows": 2,
                             "plan_rows": 5,
                             "plan_type": "IndexScan",
-                            "plan_width": 32,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -757,8 +742,8 @@ async def test_edgeql_explain_computed_backlink_01(self):
                                     "type": "expr",
                                 },
                             ]),
-                            "startup_cost": 0.28,
-                            "total_cost": 8.37,
+                            "startup_cost": float,
+                            "total_cost": float,
                         },
                     ],
                     "subplans": [],
@@ -785,16 +770,14 @@ async def test_edgeql_explain_inheritance_01(self):
                     "actual_loops": 1,
                     "plan_rows": 5001,
                     "plan_type": "Result",
-                    "plan_width": 32,
                     "properties": [],
-                    "startup_cost": 0.0,
+                    "startup_cost": float,
                 },
                 {
                     "actual_loops": 1,
                     "actual_rows": 5001,
                     "plan_rows": 5001,
                     "plan_type": "Append",
-                    "plan_width": 16,
                     "properties": tb.bag([
                         {
                             "important": False,
@@ -803,7 +786,7 @@ async def test_edgeql_explain_inheritance_01(self):
                             "value": "Outer",
                         }
                     ]),
-                    "startup_cost": 0.0,
+                    "startup_cost": float,
                 },
             ],
             # Order here can be arbitrary, unfortunately.
@@ -816,7 +799,6 @@ async def test_edgeql_explain_inheritance_01(self):
                         {
                             "actual_loops": 1,
                             "plan_type": "SeqScan",
-                            "plan_width": 16,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -841,7 +823,7 @@ async def test_edgeql_explain_inheritance_01(self):
                                     "type": "relation",
                                 },
                             ]),
-                            "startup_cost": 0.0,
+                            "startup_cost": float,
                         }
                     ],
                     "subplans": [],
@@ -851,7 +833,6 @@ async def test_edgeql_explain_inheritance_01(self):
                         {
                             "actual_loops": 1,
                             "plan_type": "SeqScan",
-                            "plan_width": 16,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -876,7 +857,7 @@ async def test_edgeql_explain_inheritance_01(self):
                                     "type": "relation",
                                 },
                             ]),
-                            "startup_cost": 0.0,
+                            "startup_cost": float,
                         }
                     ],
                     "subplans": [],
@@ -886,7 +867,6 @@ async def test_edgeql_explain_inheritance_01(self):
                         {
                             "actual_loops": 1,
                             "plan_type": "SeqScan",
-                            "plan_width": 16,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -911,7 +891,7 @@ async def test_edgeql_explain_inheritance_01(self):
                                     "type": "relation",
                                 },
                             ]),
-                            "startup_cost": 0.0,
+                            "startup_cost": float,
                         }
                     ],
                     "subplans": [],
@@ -936,10 +916,9 @@ async def test_edgeql_explain_type_intersect_01(self):
                     "actual_rows": 5001,
                     "plan_rows": 5001,
                     "plan_type": "Result",
-                    "plan_width": 32,
                     "properties": [],
-                    "startup_cost": 0.0,
-                    "total_cost": 41707.33,
+                    "startup_cost": float,
+                    "total_cost": float,
                 }
             ],
             "subplans": [
@@ -956,7 +935,6 @@ async def test_edgeql_explain_type_intersect_01(self):
                             "actual_rows": 5001,
                             "plan_rows": 5001,
                             "plan_type": "Append",
-                            "plan_width": 20,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -965,8 +943,8 @@ async def test_edgeql_explain_type_intersect_01(self):
                                     "value": "Outer",
                                 }
                             ]),
-                            "startup_cost": 0.0,
-                            "total_cost": 149.02,
+                            "startup_cost": float,
+                            "total_cost": float,
                         }
                     ],
                     "subplans": tb.bag([
@@ -977,7 +955,6 @@ async def test_edgeql_explain_type_intersect_01(self):
                                     "actual_rows": 4999,
                                     "plan_rows": 4999,
                                     "plan_type": "SeqScan",
-                                    "plan_width": 20,
                                     "properties": tb.bag([
                                         {
                                             "important": False,
@@ -1003,8 +980,8 @@ async def test_edgeql_explain_type_intersect_01(self):
                                             "type": "relation",
                                         },
                                     ]),
-                                    "startup_cost": 0.0,
-                                    "total_cost": 121.99,
+                                    "startup_cost": float,
+                                    "total_cost": float,
                                 }
                             ],
                             "subplans": [],
@@ -1016,7 +993,6 @@ async def test_edgeql_explain_type_intersect_01(self):
                                     "actual_rows": 1,
                                     "plan_rows": 1,
                                     "plan_type": "SeqScan",
-                                    "plan_width": 38,
                                     "properties": tb.bag([
                                         {
                                             "important": False,
@@ -1042,8 +1018,8 @@ async def test_edgeql_explain_type_intersect_01(self):
                                             "type": "relation",
                                         },
                                     ]),
-                                    "startup_cost": 0.0,
-                                    "total_cost": 1.01,
+                                    "startup_cost": float,
+                                    "total_cost": float,
                                 }
                             ],
                             "subplans": [],
@@ -1055,7 +1031,6 @@ async def test_edgeql_explain_type_intersect_01(self):
                                     "actual_rows": 1,
                                     "plan_rows": 1,
                                     "plan_type": "SeqScan",
-                                    "plan_width": 45,
                                     "properties": tb.bag([
                                         {
                                             "important": False,
@@ -1081,8 +1056,8 @@ async def test_edgeql_explain_type_intersect_01(self):
                                             "type": "relation",
                                         },
                                     ]),
-                                    "startup_cost": 0.0,
-                                    "total_cost": 1.01,
+                                    "startup_cost": float,
+                                    "total_cost": float,
                                 }
                             ],
                             "subplans": [],
@@ -1104,7 +1079,6 @@ async def test_edgeql_explain_type_intersect_01(self):
                             "actual_rows": 1,
                             "plan_rows": 1,
                             "plan_type": "IndexScan",
-                            "plan_width": 11,
                             "properties": tb.bag([
                                 {
                                     "important": False,
@@ -1156,8 +1130,8 @@ async def test_edgeql_explain_type_intersect_01(self):
                                     "type": "expr",
                                 },
                             ]),
-                            "startup_cost": 0.28,
-                            "total_cost": 8.3,
+                            "startup_cost": float,
+                            "total_cost": float,
                         }
                     ],
                     "subplans": [],
diff --git a/tests/test_schema.py b/tests/test_schema.py
--- a/tests/test_schema.py
+++ b/tests/test_schema.py
@@ -7850,6 +7850,22 @@ def test_schema_migrations_equivalence_nested_module_01(self):
             module foo { module bar { module baz {} } }
         """])
 
+    def test_schema_migrations_property_aliases(self):
+        self._assert_migration_equivalence([
+            r"""
+                abstract type NamedObject {
+                    required property name: std::str;
+                };
+                type Person extending default::User;
+                type User extending default::NamedObject {
+                    multi link fav_users := (.favorites[is default::User]);
+                    multi link favorites: default::NamedObject;
+                };
+            """,
+            r"""
+            """,
+        ])
+
 
 class TestDescribe(tb.BaseSchemaLoadTest):
     """Test the DESCRIBE command."""