Repository: edgedb/edgedb

Issue:
We generate a pointless self-join on simple link references
Part of the generated code for `SELECT User.deck.name` is

```
edgedbpub."2ba72ba6-bd92-11eb-86bd-39cdc1a3919c_t" AS "User~2"
INNER JOIN edgedbpub."2ba72ba6-bd92-11eb-86bd-39cdc1a3919c_t" AS "User~3"
    ON ("User~2".id = "User~3".id)
```


Discussion:
(This could be hard to avoid in general? but this case at least seems silly)
@elprans thoughts on this?
This should be fixable relatively easily.

Resolving patch:
diff --git a/edb/pgsql/compiler/relgen.py b/edb/pgsql/compiler/relgen.py
--- a/edb/pgsql/compiler/relgen.py
+++ b/edb/pgsql/compiler/relgen.py
@@ -441,10 +441,14 @@ def ensure_source_rvar(
         scope_stmt = relctx.maybe_get_scope_stmt(ir_set.path_id, ctx=ctx)
         if scope_stmt is None:
             scope_stmt = ctx.rel
-        rvar = relctx.new_root_rvar(ir_set, lateral=True, ctx=ctx)
-        relctx.include_rvar(scope_stmt, rvar, path_id=ir_set.path_id, ctx=ctx)
-        pathctx.put_path_rvar(
-            stmt, ir_set.path_id, rvar, aspect='source', env=ctx.env)
+        rvar = relctx.maybe_get_path_rvar(
+            scope_stmt, ir_set.path_id, aspect='source', ctx=ctx)
+        if rvar is None:
+            rvar = relctx.new_root_rvar(ir_set, lateral=True, ctx=ctx)
+            relctx.include_rvar(
+                scope_stmt, rvar, path_id=ir_set.path_id, ctx=ctx)
+            pathctx.put_path_rvar(
+                stmt, ir_set.path_id, rvar, aspect='source', env=ctx.env)
 
     return rvar
 


Test patch:
diff --git a/tests/test_edgeql_sql_codegen.py b/tests/test_edgeql_sql_codegen.py
--- a/tests/test_edgeql_sql_codegen.py
+++ b/tests/test_edgeql_sql_codegen.py
@@ -20,7 +20,6 @@
 import os.path
 
 from edb.testbase import lang as tb
-from edb.tools import test
 
 from edb.common.ast import visitor as ast_visitor
 
@@ -60,21 +59,25 @@ def _compile(self, source):
         qtree = self._compile_to_tree(source)
         return ''.join(pg_compiler.run_codegen(qtree).result)
 
-    @test.xfail('''
-        Issue #2567: We generate a pointless self join
-    ''')
-    def test_codegen_no_self_join(self):
-        sql = self._compile('''
-            SELECT User.deck.name
-        ''')
+    def no_self_join_test(self, query, tables):
+        # Issue #2567: We generate a pointless self join
 
-        # Make sure that User is only selected from *once* in the query
-        user_obj = self.schema.get('default::User')
-        user_id_str = str(user_obj.id)
+        sql = self._compile(query)
 
-        self.assertEqual(
-            sql.count(user_id_str), 1, "User table referenced more than once"
-        )
+        for table in tables:
+            # Make sure that table is only selected from *once* in the query
+            table_obj = self.schema.get("default::" + table)
+            count = sql.count(str(table_obj.id))
+            self.assertEqual(
+                count,
+                1,
+                f"{table} referenced more than once: {sql}")
+
+    def test_codegen_no_self_join_single(self):
+        self.no_self_join_test("SELECT User.avatar", ["User", "Card"])
+
+    def test_codegen_no_self_join_multi(self):
+        self.no_self_join_test("SELECT User.deck.name", ["User"])
 
     def test_codegen_elide_optional_wrapper(self):
         sql = self._compile('''