Skip useless calculation of join RTE column names during EXPLAIN.
authorTom Lane <[email protected]>
Tue, 17 Dec 2024 20:52:05 +0000 (15:52 -0500)
committerTom Lane <[email protected]>
Tue, 17 Dec 2024 20:52:12 +0000 (15:52 -0500)
There's no need for set_simple_column_names() to compute unique
column names for join RTEs, because a finished plan tree will
not contain any join alias Vars that we could need names for.
Its other, internal callers will not pass it any join RTEs
anyway, so the upshot is we can just skip join RTEs here.

Aside from getting rid of a klugy against-its-documentation use of
set_relation_column_names, this can speed up EXPLAIN substantially
when considering many-join queries, because the upper join RTEs
tend to have a lot of columns.

Sami Imseih, with cosmetic changes by me

Discussion: https://postgr.es/m/CAA5RZ0th3q-0p1pri58z9grG8r8azmEBa8o1rtkwhLmJg_cH+g@mail.gmail.com

src/backend/utils/adt/ruleutils.c

index 2194ab3dfa5a48c0bd5256bd8f449ffd3e75e534..be1f1f50b78dbbdca61b62faac578840f98edadd 100644 (file)
@@ -3773,9 +3773,8 @@ deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
        dpns->appendrels = NULL;    /* don't need it */
 
    /*
-    * Set up column name aliases.  We will get rather bogus results for join
-    * RTEs, but that doesn't matter because plan trees don't contain any join
-    * alias Vars.
+    * Set up column name aliases, ignoring any join RTEs; they don't matter
+    * because plan trees don't contain any join alias Vars.
     */
    set_simple_column_names(dpns);
 
@@ -4067,8 +4066,10 @@ set_deparse_for_query(deparse_namespace *dpns, Query *query,
  *
  * This handles EXPLAIN and cases where we only have relation RTEs.  Without
  * a join tree, we can't do anything smart about join RTEs, but we don't
- * need to (note that EXPLAIN should never see join alias Vars anyway).
- * If we do hit a join RTE we'll just process it like a non-table base RTE.
+ * need to, because EXPLAIN should never see join alias Vars anyway.
+ * If we find a join RTE we'll just skip it, leaving its deparse_columns
+ * struct all-zero.  If somehow we try to deparse a join alias Var, we'll
+ * error out cleanly because the struct's num_cols will be zero.
  */
 static void
 set_simple_column_names(deparse_namespace *dpns)
@@ -4082,13 +4083,14 @@ set_simple_column_names(deparse_namespace *dpns)
        dpns->rtable_columns = lappend(dpns->rtable_columns,
                                       palloc0(sizeof(deparse_columns)));
 
-   /* Assign unique column aliases within each RTE */
+   /* Assign unique column aliases within each non-join RTE */
    forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
    {
        RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
        deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
 
-       set_relation_column_names(dpns, rte, colinfo);
+       if (rte->rtekind != RTE_JOIN)
+           set_relation_column_names(dpns, rte, colinfo);
    }
 }