0001-Allow-partition-wise-join-when-reltarget-contains-wh.patch
text/x-diff
Filename: 0001-Allow-partition-wise-join-when-reltarget-contains-wh.patch
Type: text/x-diff
Part: 5
From 6cdc583c10dc20859425a86f8d9fbf583e308907 Mon Sep 17 00:00:00 2001
From: Alexander Pyhalov <a.pyhalov@postgrespro.ru>
Date: Mon, 25 Dec 2023 15:51:28 +0300
Subject: [PATCH 1/6] Allow partition-wise join when reltarget contains whole
row vars
This partially revert 7cfdc77023ad50731723e85c215a4127436ed09c,
restoring setrefs logic to handle converted whole row reference.
---
src/backend/optimizer/path/allpaths.c | 3 +-
src/backend/optimizer/plan/setrefs.c | 51 ++++++++++++++++++++++++---
2 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 172edb643a4..53092d66153 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -976,8 +976,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
*/
if (enable_partitionwise_join &&
rel->reloptkind == RELOPT_BASEREL &&
- rte->relkind == RELKIND_PARTITIONED_TABLE &&
- bms_is_empty(rel->attr_needed[InvalidAttrNumber - rel->min_attr]))
+ rte->relkind == RELKIND_PARTITIONED_TABLE)
rel->consider_partitionwise_join = true;
/*
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 6d23df108da..0bf1ca3910b 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -52,6 +52,9 @@ typedef struct
int num_vars; /* number of plain Var tlist entries */
bool has_ph_vars; /* are there PlaceHolderVar entries? */
bool has_non_vars; /* are there other entries? */
+ bool has_conv_whole_rows; /* are there ConvertRowtypeExpr
+ * entries encapsulating a whole-row
+ * Var? */
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]; /* has num_vars entries */
} indexed_tlist;
@@ -211,6 +214,7 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
List *runcondition,
Plan *plan);
+static bool is_converted_whole_row_reference(Node *node);
/*****************************************************************************
*
@@ -2707,6 +2711,7 @@ build_tlist_index(List *tlist)
itlist->tlist = tlist;
itlist->has_ph_vars = false;
itlist->has_non_vars = false;
+ itlist->has_conv_whole_rows = false;
/* Find the Vars and fill in the index array */
vinfo = itlist->vars;
@@ -2726,6 +2731,8 @@ build_tlist_index(List *tlist)
}
else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
itlist->has_ph_vars = true;
+ else if (is_converted_whole_row_reference((Node *) tle->expr))
+ itlist->has_conv_whole_rows = true;
else
itlist->has_non_vars = true;
}
@@ -2741,7 +2748,10 @@ build_tlist_index(List *tlist)
* This is like build_tlist_index, but we only index tlist entries that
* are Vars belonging to some rel other than the one specified. We will set
* has_ph_vars (allowing PlaceHolderVars to be matched), but not has_non_vars
- * (so nothing other than Vars and PlaceHolderVars can be matched).
+ * (so nothing other than Vars and PlaceHolderVars can be matched). In case of
+ * DML, where this function will be used, returning lists from child relations
+ * will be appended similar to a simple append relation. That does not require
+ * fixing ConvertRowtypeExpr references. So, those are not considered here.
*/
static indexed_tlist *
build_tlist_index_other_vars(List *tlist, int ignore_rel)
@@ -2758,6 +2768,7 @@ build_tlist_index_other_vars(List *tlist, int ignore_rel)
itlist->tlist = tlist;
itlist->has_ph_vars = false;
itlist->has_non_vars = false;
+ itlist->has_conv_whole_rows = false;
/* Find the desired Vars and fill in the index array */
vinfo = itlist->vars;
@@ -3063,6 +3074,7 @@ static Node *
fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
{
Var *newvar;
+ bool converted_whole_row;
if (node == NULL)
return NULL;
@@ -3136,7 +3148,8 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
return fix_join_expr_mutator((Node *) phv->phexpr, context);
}
/* Try matching more complex expressions too, if tlists have any */
- if (context->outer_itlist && context->outer_itlist->has_non_vars)
+ converted_whole_row = is_converted_whole_row_reference(node);
+ if (context->outer_itlist && (context->outer_itlist->has_non_vars || (context->outer_itlist->has_conv_whole_rows && converted_whole_row)))
{
newvar = search_indexed_tlist_for_non_var((Expr *) node,
context->outer_itlist,
@@ -3144,7 +3157,7 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
if (newvar)
return (Node *) newvar;
}
- if (context->inner_itlist && context->inner_itlist->has_non_vars)
+ if (context->inner_itlist && (context->inner_itlist->has_non_vars || (context->inner_itlist->has_conv_whole_rows && converted_whole_row)))
{
newvar = search_indexed_tlist_for_non_var((Expr *) node,
context->inner_itlist,
@@ -3255,7 +3268,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
return fix_upper_expr_mutator((Node *) phv->phexpr, context);
}
/* Try matching more complex expressions too, if tlist has any */
- if (context->subplan_itlist->has_non_vars)
+ if (context->subplan_itlist->has_non_vars || (context->subplan_itlist->has_conv_whole_rows && is_converted_whole_row_reference(node)))
{
newvar = search_indexed_tlist_for_non_var((Expr *) node,
context->subplan_itlist,
@@ -3655,3 +3668,33 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
return expression_tree_walker(node, extract_query_dependencies_walker,
context);
}
+
+/*
+ * is_converted_whole_row_reference
+ * If the given node is a ConvertRowtypeExpr encapsulating a whole-row
+ * reference as implicit cast, return true. Otherwise return false.
+ */
+static bool
+is_converted_whole_row_reference(Node *node)
+{
+ ConvertRowtypeExpr *convexpr;
+
+ if (!node || !IsA(node, ConvertRowtypeExpr))
+ return false;
+
+ /* Traverse nested ConvertRowtypeExpr's. */
+ convexpr = castNode(ConvertRowtypeExpr, node);
+ while (convexpr->convertformat == COERCE_IMPLICIT_CAST &&
+ IsA(convexpr->arg, ConvertRowtypeExpr))
+ convexpr = castNode(ConvertRowtypeExpr, convexpr->arg);
+
+ if (IsA(convexpr->arg, Var))
+ {
+ Var *var = castNode(Var, convexpr->arg);
+
+ if (var->varattno == 0)
+ return true;
+ }
+
+ return false;
+}
--
2.43.0