static ElidedNode *pgpa_descend_node(PlannedStmt *pstmt, Plan **plan);
static ElidedNode *pgpa_descend_any_gather(PlannedStmt *pstmt, Plan **plan);
static ElidedNode *pgpa_descend_any_unique(PlannedStmt *pstmt, Plan **plan);
+
+static Bitmapset *pgpa_add_member_relids(Bitmapset *relids,
+ pgpa_join_member *member);
+
static Index pgpa_scanrelid(Plan *plan);
static Bitmapset *pgpa_relids(Plan *plan);
return NULL;
}
+/*
+ * Create a Bitmapset of all RTIs that we associated with an unrolled join.
+ *
+ * As usual, join RTIs are excluded.
+ */
+Bitmapset *
+pgpa_unrolled_join_all_relids(pgpa_unrolled_join *join)
+{
+ Bitmapset *relids = NULL;
+
+ relids = pgpa_add_member_relids(relids, &join->outer);
+
+ for (int k = 0; k < join->ninner; ++k)
+ relids = pgpa_add_member_relids(relids, &join->inner[k]);
+
+ return relids;
+}
+
+/*
+ * Add all RTIs that we associate with a join member to the provided set,
+ * returning the result.
+ */
+static Bitmapset *
+pgpa_add_member_relids(Bitmapset *relids, pgpa_join_member *member)
+{
+ if (member->clump_join != NULL)
+ return bms_union(relids, member->clump_join->relids);
+ else if (member->unrolled_join != NULL)
+ return bms_union(relids,
+ pgpa_unrolled_join_all_relids(member->unrolled_join));
+ else
+ return bms_add_member(relids, member->rti);
+}
+
/*
* Update a pgpa_gathered_join to include RTIs scanned by the provided
* plan node.
{
const char **rt_identifiers;
StringInfo buf;
+ List *unrolled_joins[NUM_PGPA_JOIN_STRATEGY];
+ List *clumped_joins[NUM_PGPA_CLUMP_JOIN_STRATEGY];
int wrap_column;
} pgpa_output_context;
static void pgpa_output_unrolled_join(pgpa_output_context *context,
- pgpa_unrolled_join *join,
- bool toplevel);
+ pgpa_unrolled_join *join);
static void pgpa_output_join_member(pgpa_output_context *context,
pgpa_join_member *member);
static void pgpa_output_relations(pgpa_output_context *context, StringInfo buf,
ListCell *lc;
pgpa_output_context context;
+ memset(&context, 0, sizeof(pgpa_output_context));
context.rt_identifiers = rt_identifiers;
context.buf = buf;
context.wrap_column = 79; /* XXX */
if (buf->len > 0)
appendStringInfoChar(buf, '\n');
- pgpa_output_unrolled_join(&context, ujoin, true);
+ appendStringInfo(context.buf, "JOIN_ORDER(");
+ pgpa_output_unrolled_join(&context, ujoin);
+ appendStringInfoChar(context.buf, ')');
}
foreach(lc, walker->clumped_joins)
{
pgpa_clumped_join *cjoin = lfirst(lc);
- char *cstrategy;
+
+ context.clumped_joins[cjoin->strategy] =
+ lappend(context.clumped_joins[cjoin->strategy], cjoin->relids);
+ }
+
+ for (int s = 0; s < NUM_PGPA_JOIN_STRATEGY; ++s)
+ {
+ char *strategy = pgpa_cstring_join_strategy(s);
+ bool first = true;
+
+ if (context.unrolled_joins[s] == NIL)
+ continue;
+
+ if (buf->len > 0)
+ appendStringInfoChar(buf, '\n');
+ appendStringInfo(buf, "%s(", strategy);
+
+ foreach(lc, context.unrolled_joins[s])
+ {
+ Bitmapset *relids = lfirst(lc);
+
+ if (first)
+ first = false;
+ else
+ {
+ pgpa_maybe_linebreak(context.buf, context.wrap_column);
+ appendStringInfoChar(context.buf, ' ');
+ }
+
+ if (bms_membership(relids) == BMS_SINGLETON)
+ pgpa_output_relations(&context, buf, relids);
+ else
+ {
+ appendStringInfoChar(buf, '(');
+ pgpa_output_relations(&context, buf, relids);
+ appendStringInfoChar(buf, ')');
+ }
+ }
+ appendStringInfoChar(buf, ')');
+ }
+
+ for (int c = 0; c < NUM_PGPA_CLUMP_JOIN_STRATEGY; ++c)
+ {
+ char *cstrategy = pgpa_cstring_join_clump_strategy(c);
+ bool first = true;
+
+ if (context.clumped_joins[c] == NIL)
+ continue;
if (buf->len > 0)
appendStringInfoChar(buf, '\n');
- cstrategy = pgpa_cstring_join_clump_strategy(cjoin->strategy);
appendStringInfo(buf, "%s(", cstrategy);
- pgpa_output_relations(&context, buf, cjoin->relids);
+
+ foreach(lc, context.clumped_joins[c])
+ {
+ Bitmapset *relids = lfirst(lc);
+
+ if (first)
+ first = false;
+ else
+ {
+ pgpa_maybe_linebreak(context.buf, context.wrap_column);
+ appendStringInfoChar(context.buf, ' ');
+ }
+
+ appendStringInfoChar(buf, '(');
+ pgpa_output_relations(&context, buf, relids);
+ appendStringInfoChar(buf, ')');
+ }
appendStringInfoChar(buf, ')');
}
static void
pgpa_output_unrolled_join(pgpa_output_context *context,
- pgpa_unrolled_join *join, bool toplevel)
+ pgpa_unrolled_join *join)
{
- if (toplevel)
- appendStringInfo(context->buf, "JOIN_ORDER(");
- else
- appendStringInfoChar(context->buf, '(');
-
pgpa_output_join_member(context, &join->outer);
for (int k = 0; k < join->ninner; ++k)
{
- char *cstrategy;
-
- pgpa_maybe_linebreak(context->buf, context->wrap_column);
- cstrategy = pgpa_cstring_join_strategy(join->strategy[k]);
- appendStringInfo(context->buf, " %s", cstrategy);
+ pgpa_join_member *member = &join->inner[k];
+ Bitmapset *relids;
pgpa_maybe_linebreak(context->buf, context->wrap_column);
appendStringInfoChar(context->buf, ' ');
- pgpa_output_join_member(context, &join->inner[k]);
- }
+ pgpa_output_join_member(context, member);
- appendStringInfoChar(context->buf, ')');
+ if (member->clump_join != NULL)
+ relids = member->clump_join->relids;
+ else if (member->unrolled_join != NULL)
+ relids = pgpa_unrolled_join_all_relids(member->unrolled_join);
+ else
+ relids = bms_make_singleton(member->rti);
+ context->unrolled_joins[join->strategy[k]] =
+ lappend(context->unrolled_joins[join->strategy[k]], relids);
+ }
}
static void
{
if (member->clump_join != NULL)
{
+ pgpa_clumped_join *cjoin = member->clump_join;
+
appendStringInfoChar(context->buf, '{');
- pgpa_output_relations(context, context->buf,
- member->clump_join->relids);
+ pgpa_output_relations(context, context->buf, cjoin->relids);
appendStringInfoChar(context->buf, '}');
+ context->clumped_joins[cjoin->strategy] =
+ lappend(context->clumped_joins[cjoin->strategy], cjoin->relids);
}
else if (member->unrolled_join != NULL)
- pgpa_output_unrolled_join(context, member->unrolled_join, false);
+ {
+ appendStringInfoChar(context->buf, '(');
+ pgpa_output_unrolled_join(context, member->unrolled_join);
+ appendStringInfoChar(context->buf, ')');
+ }
else
{
if (context->rt_identifiers[member->rti - 1] == NULL)