Commit 6ef77cf4 authored by Tom Lane's avatar Tom Lane

Further adjust EXPLAIN's choices of table alias names.

This patch causes EXPLAIN to always assign a separate table alias to the
parent RTE of an append relation (inheritance set); before, such RTEs
were ignored if not actually scanned by the plan.  Since the child RTEs
now always have that same alias to start with (cf. commit 55a1954d),
the net effect is that the parent RTE usually gets the alias used or
implied by the query text, and the children all get that alias with "_N"
appended.  (The exception to "usually" is if there are duplicate aliases
in different subtrees of the original query; then some of those original
RTEs will also have "_N" appended.)

This results in more uniform output for partitioned-table plans than
we had before: the partitioned table itself gets the original alias,
and all child tables have aliases with "_N", rather than the previous
behavior where one of the children would get an alias without "_N".

The reason for giving the parent RTE an alias, even if it isn't scanned
by the plan, is that we now use the parent's alias to qualify Vars that
refer to an appendrel output column and appear above the Append or
MergeAppend that computes the appendrel.  But below the append, Vars
refer to some one of the child relations, and are displayed that way.
This seems clearer than the old behavior where a Var that could carry
values from any child relation was displayed as if it referred to only
one of them.

While at it, change ruleutils.c so that the code paths used by EXPLAIN
deal in Plan trees not PlanState trees.  This effectively reverts a
decision made in commit 1cc29fe7, which seemed like a good idea at
the time to make ruleutils.c consistent with explain.c.  However,
it's problematic because we'd really like to allow executor startup
pruning to remove all the children of an append node when possible,
leaving no child PlanState to resolve Vars against.  (That's not done
here, but will be in the next patch.)  This requires different handling
of subplans and initplans than before, but is otherwise a pretty
straightforward change.

Discussion: https://postgr.es/m/001001d4f44b$2a2cca50$7e865ef0$@lab.ntt.co.jp
parent ba79cb5d
......@@ -689,8 +689,8 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
es->rtable = queryDesc->plannedstmt->rtable;
ExplainPreScanNode(queryDesc->planstate, &rels_used);
es->rtable_names = select_rtable_names_for_explain(es->rtable, rels_used);
es->deparse_cxt = deparse_context_for_plan_rtable(es->rtable,
es->rtable_names);
es->deparse_cxt = deparse_context_for_plan_tree(queryDesc->plannedstmt,
es->rtable_names);
es->printed_subplans = NULL;
/*
......@@ -1034,6 +1034,14 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
*rels_used = bms_add_member(*rels_used,
((ModifyTable *) plan)->exclRelRTI);
break;
case T_Append:
*rels_used = bms_add_members(*rels_used,
((Append *) plan)->apprelids);
break;
case T_MergeAppend:
*rels_used = bms_add_members(*rels_used,
((MergeAppend *) plan)->apprelids);
break;
default:
break;
}
......@@ -1049,8 +1057,8 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
* We need to work from a PlanState node, not just a Plan node, in order to
* get at the instrumentation data (if any) as well as the list of subplans.
*
* ancestors is a list of parent PlanState nodes, most-closely-nested first.
* These are needed in order to interpret PARAM_EXEC Params.
* ancestors is a list of parent Plan and SubPlan nodes, most-closely-nested
* first. These are needed in order to interpret PARAM_EXEC Params.
*
* relationship describes the relationship of this plan node to its parent
* (eg, "Outer", "Inner"); it can be null at top level. plan_name is an
......@@ -1953,8 +1961,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
if (haschildren)
{
ExplainOpenGroup("Plans", "Plans", false, es);
/* Pass current PlanState as head of ancestors list for children */
ancestors = lcons(planstate, ancestors);
/* Pass current Plan as head of ancestors list for children */
ancestors = lcons(plan, ancestors);
}
/* initPlan-s */
......@@ -2075,9 +2083,9 @@ show_plan_tlist(PlanState *planstate, List *ancestors, ExplainState *es)
return;
/* Set up deparsing context */
context = set_deparse_context_planstate(es->deparse_cxt,
(Node *) planstate,
ancestors);
context = set_deparse_context_plan(es->deparse_cxt,
plan,
ancestors);
useprefix = list_length(es->rtable) > 1;
/* Deparse each result column (we now include resjunk ones) */
......@@ -2106,9 +2114,9 @@ show_expression(Node *node, const char *qlabel,
char *exprstr;
/* Set up deparsing context */
context = set_deparse_context_planstate(es->deparse_cxt,
(Node *) planstate,
ancestors);
context = set_deparse_context_plan(es->deparse_cxt,
planstate->plan,
ancestors);
/* Deparse the expression */
exprstr = deparse_expression(node, context, useprefix, false);
......@@ -2209,7 +2217,7 @@ show_agg_keys(AggState *astate, List *ancestors,
if (plan->numCols > 0 || plan->groupingSets)
{
/* The key columns refer to the tlist of the child plan */
ancestors = lcons(astate, ancestors);
ancestors = lcons(plan, ancestors);
if (plan->groupingSets)
show_grouping_sets(outerPlanState(astate), plan, ancestors, es);
......@@ -2232,9 +2240,9 @@ show_grouping_sets(PlanState *planstate, Agg *agg,
ListCell *lc;
/* Set up deparsing context */
context = set_deparse_context_planstate(es->deparse_cxt,
(Node *) planstate,
ancestors);
context = set_deparse_context_plan(es->deparse_cxt,
planstate->plan,
ancestors);
useprefix = (list_length(es->rtable) > 1 || es->verbose);
ExplainOpenGroup("Grouping Sets", "Grouping Sets", false, es);
......@@ -2339,7 +2347,7 @@ show_group_keys(GroupState *gstate, List *ancestors,
Group *plan = (Group *) gstate->ss.ps.plan;
/* The key columns refer to the tlist of the child plan */
ancestors = lcons(gstate, ancestors);
ancestors = lcons(plan, ancestors);
show_sort_group_keys(outerPlanState(gstate), "Group Key",
plan->numCols, plan->grpColIdx,
NULL, NULL, NULL,
......@@ -2371,9 +2379,9 @@ show_sort_group_keys(PlanState *planstate, const char *qlabel,
initStringInfo(&sortkeybuf);
/* Set up deparsing context */
context = set_deparse_context_planstate(es->deparse_cxt,
(Node *) planstate,
ancestors);
context = set_deparse_context_plan(es->deparse_cxt,
plan,
ancestors);
useprefix = (list_length(es->rtable) > 1 || es->verbose);
for (keyno = 0; keyno < nkeys; keyno++)
......@@ -2479,9 +2487,9 @@ show_tablesample(TableSampleClause *tsc, PlanState *planstate,
ListCell *lc;
/* Set up deparsing context */
context = set_deparse_context_planstate(es->deparse_cxt,
(Node *) planstate,
ancestors);
context = set_deparse_context_plan(es->deparse_cxt,
planstate->plan,
ancestors);
useprefix = list_length(es->rtable) > 1;
/* Get the tablesample method name */
......@@ -3344,7 +3352,7 @@ ExplainMemberNodes(PlanState **planstates, int nsubnodes, int nplans,
* Explain a list of SubPlans (or initPlans, which also use SubPlan nodes).
*
* The ancestors list should already contain the immediate parent of these
* SubPlanStates.
* SubPlans.
*/
static void
ExplainSubPlans(List *plans, List *ancestors,
......@@ -3372,8 +3380,17 @@ ExplainSubPlans(List *plans, List *ancestors,
es->printed_subplans = bms_add_member(es->printed_subplans,
sp->plan_id);
/*
* Treat the SubPlan node as an ancestor of the plan node(s) within
* it, so that ruleutils.c can find the referents of subplan
* parameters.
*/
ancestors = lcons(sp, ancestors);
ExplainNode(sps->planstate, ancestors,
relationship, sp->plan_name, es);
ancestors = list_delete_first(ancestors);
}
}
......
......@@ -181,6 +181,8 @@ ExecSerializePlan(Plan *plan, EState *estate)
pstmt->planTree = plan;
pstmt->rtable = estate->es_range_table;
pstmt->resultRelations = NIL;
pstmt->rootResultRelations = NIL;
pstmt->appendRelations = NIL;
/*
* Transfer only parallel-safe subplans, leaving a NULL "hole" in the list
......
......@@ -2526,9 +2526,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
econtext = mtstate->ps.ps_ExprContext;
relationDesc = resultRelInfo->ri_RelationDesc->rd_att;
/* carried forward solely for the benefit of explain */
mtstate->mt_excludedtlist = node->exclRelTlist;
/* create state for DO UPDATE SET operation */
resultRelInfo->ri_onConflict = makeNode(OnConflictSetState);
......
......@@ -92,6 +92,7 @@ _copyPlannedStmt(const PlannedStmt *from)
COPY_NODE_FIELD(rtable);
COPY_NODE_FIELD(resultRelations);
COPY_NODE_FIELD(rootResultRelations);
COPY_NODE_FIELD(appendRelations);
COPY_NODE_FIELD(subplans);
COPY_BITMAPSET_FIELD(rewindPlanIDs);
COPY_NODE_FIELD(rowMarks);
......@@ -241,6 +242,7 @@ _copyAppend(const Append *from)
/*
* copy remainder of node
*/
COPY_BITMAPSET_FIELD(apprelids);
COPY_NODE_FIELD(appendplans);
COPY_SCALAR_FIELD(first_partial_plan);
COPY_NODE_FIELD(part_prune_info);
......@@ -264,6 +266,7 @@ _copyMergeAppend(const MergeAppend *from)
/*
* copy remainder of node
*/
COPY_BITMAPSET_FIELD(apprelids);
COPY_NODE_FIELD(mergeplans);
COPY_SCALAR_FIELD(numCols);
COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber));
......
......@@ -310,6 +310,7 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node)
WRITE_NODE_FIELD(rtable);
WRITE_NODE_FIELD(resultRelations);
WRITE_NODE_FIELD(rootResultRelations);
WRITE_NODE_FIELD(appendRelations);
WRITE_NODE_FIELD(subplans);
WRITE_BITMAPSET_FIELD(rewindPlanIDs);
WRITE_NODE_FIELD(rowMarks);
......@@ -431,6 +432,7 @@ _outAppend(StringInfo str, const Append *node)
_outPlanInfo(str, (const Plan *) node);
WRITE_BITMAPSET_FIELD(apprelids);
WRITE_NODE_FIELD(appendplans);
WRITE_INT_FIELD(first_partial_plan);
WRITE_NODE_FIELD(part_prune_info);
......@@ -443,6 +445,7 @@ _outMergeAppend(StringInfo str, const MergeAppend *node)
_outPlanInfo(str, (const Plan *) node);
WRITE_BITMAPSET_FIELD(apprelids);
WRITE_NODE_FIELD(mergeplans);
WRITE_INT_FIELD(numCols);
WRITE_ATTRNUMBER_ARRAY(sortColIdx, node->numCols);
......@@ -2167,6 +2170,7 @@ _outPlannerGlobal(StringInfo str, const PlannerGlobal *node)
WRITE_NODE_FIELD(finalrowmarks);
WRITE_NODE_FIELD(resultRelations);
WRITE_NODE_FIELD(rootResultRelations);
WRITE_NODE_FIELD(appendRelations);
WRITE_NODE_FIELD(relationOids);
WRITE_NODE_FIELD(invalItems);
WRITE_NODE_FIELD(paramExecTypes);
......
......@@ -1512,6 +1512,7 @@ _readPlannedStmt(void)
READ_NODE_FIELD(rtable);
READ_NODE_FIELD(resultRelations);
READ_NODE_FIELD(rootResultRelations);
READ_NODE_FIELD(appendRelations);
READ_NODE_FIELD(subplans);
READ_BITMAPSET_FIELD(rewindPlanIDs);
READ_NODE_FIELD(rowMarks);
......@@ -1636,6 +1637,7 @@ _readAppend(void)
ReadCommonPlan(&local_node->plan);
READ_BITMAPSET_FIELD(apprelids);
READ_NODE_FIELD(appendplans);
READ_INT_FIELD(first_partial_plan);
READ_NODE_FIELD(part_prune_info);
......@@ -1653,6 +1655,7 @@ _readMergeAppend(void)
ReadCommonPlan(&local_node->plan);
READ_BITMAPSET_FIELD(apprelids);
READ_NODE_FIELD(mergeplans);
READ_INT_FIELD(numCols);
READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols);
......
......@@ -1118,6 +1118,7 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
plan->plan.qual = NIL;
plan->plan.lefttree = NULL;
plan->plan.righttree = NULL;
plan->apprelids = rel->relids;
if (pathkeys != NIL)
{
......@@ -1295,6 +1296,7 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
plan->qual = NIL;
plan->lefttree = NULL;
plan->righttree = NULL;
node->apprelids = rel->relids;
/*
* Compute sort column info, and adjust MergeAppend's tlist as needed.
......
......@@ -304,6 +304,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
glob->finalrowmarks = NIL;
glob->resultRelations = NIL;
glob->rootResultRelations = NIL;
glob->appendRelations = NIL;
glob->relationOids = NIL;
glob->invalItems = NIL;
glob->paramExecTypes = NIL;
......@@ -494,6 +495,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
Assert(glob->finalrowmarks == NIL);
Assert(glob->resultRelations == NIL);
Assert(glob->rootResultRelations == NIL);
Assert(glob->appendRelations == NIL);
top_plan = set_plan_references(root, top_plan);
/* ... and the subplans (both regular subplans and initplans) */
Assert(list_length(glob->subplans) == list_length(glob->subroots));
......@@ -520,6 +522,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result->rtable = glob->finalrtable;
result->resultRelations = glob->resultRelations;
result->rootResultRelations = glob->rootResultRelations;
result->appendRelations = glob->appendRelations;
result->subplans = glob->subplans;
result->rewindPlanIDs = glob->rewindPlanIDs;
result->rowMarks = glob->finalrowmarks;
......@@ -1219,6 +1222,7 @@ inheritance_planner(PlannerInfo *root)
Index rootRelation = 0;
List *final_rtable = NIL;
List *final_rowmarks = NIL;
List *final_appendrels = NIL;
int save_rel_array_size = 0;
RelOptInfo **save_rel_array = NULL;
AppendRelInfo **save_append_rel_array = NULL;
......@@ -1627,12 +1631,13 @@ inheritance_planner(PlannerInfo *root)
* modified subquery RTEs into final_rtable, to ensure we have sane
* copies of those. Also save the first non-excluded child's version
* of the rowmarks list; we assume all children will end up with
* equivalent versions of that.
* equivalent versions of that. Likewise for append_rel_list.
*/
if (final_rtable == NIL)
{
final_rtable = subroot->parse->rtable;
final_rowmarks = subroot->rowMarks;
final_appendrels = subroot->append_rel_list;
}
else
{
......@@ -1764,8 +1769,9 @@ inheritance_planner(PlannerInfo *root)
root->simple_rte_array[rti++] = rte;
}
/* Put back adjusted rowmarks, too */
/* Put back adjusted rowmarks and appendrels, too */
root->rowMarks = final_rowmarks;
root->append_rel_list = final_appendrels;
}
/*
......
......@@ -108,6 +108,7 @@ static Plan *set_mergeappend_references(PlannerInfo *root,
MergeAppend *mplan,
int rtoffset);
static void set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset);
static Relids offset_relid_set(Relids relids, int rtoffset);
static Node *fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset);
static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
......@@ -208,7 +209,8 @@ static List *set_returning_clause_references(PlannerInfo *root,
*
* The flattened rangetable entries are appended to root->glob->finalrtable.
* Also, rowmarks entries are appended to root->glob->finalrowmarks, and the
* RT indexes of ModifyTable result relations to root->glob->resultRelations.
* RT indexes of ModifyTable result relations to root->glob->resultRelations,
* and flattened AppendRelInfos are appended to root->glob->appendRelations.
* Plan dependencies are appended to root->glob->relationOids (for relations)
* and root->glob->invalItems (for everything else).
*
......@@ -250,6 +252,28 @@ set_plan_references(PlannerInfo *root, Plan *plan)
glob->finalrowmarks = lappend(glob->finalrowmarks, newrc);
}
/*
* Adjust RT indexes of AppendRelInfos and add to final appendrels list.
* We assume the AppendRelInfos were built during planning and don't need
* to be copied.
*/
foreach(lc, root->append_rel_list)
{
AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
/* adjust RT indexes */
appinfo->parent_relid += rtoffset;
appinfo->child_relid += rtoffset;
/*
* Rather than adjust the translated_vars entries, just drop 'em.
* Neither the executor nor EXPLAIN currently need that data.
*/
appinfo->translated_vars = NIL;
glob->appendRelations = lappend(glob->appendRelations, appinfo);
}
/* Now fix the Plan tree */
return set_plan_refs(root, plan, rtoffset);
}
......@@ -1215,16 +1239,7 @@ set_foreignscan_references(PlannerInfo *root,
fix_scan_list(root, fscan->fdw_recheck_quals, rtoffset);
}
/* Adjust fs_relids if needed */
if (rtoffset > 0)
{
Bitmapset *tempset = NULL;
int x = -1;
while ((x = bms_next_member(fscan->fs_relids, x)) >= 0)
tempset = bms_add_member(tempset, x + rtoffset);
fscan->fs_relids = tempset;
}
fscan->fs_relids = offset_relid_set(fscan->fs_relids, rtoffset);
}
/*
......@@ -1287,16 +1302,7 @@ set_customscan_references(PlannerInfo *root,
lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
}
/* Adjust custom_relids if needed */
if (rtoffset > 0)
{
Bitmapset *tempset = NULL;
int x = -1;
while ((x = bms_next_member(cscan->custom_relids, x)) >= 0)
tempset = bms_add_member(tempset, x + rtoffset);
cscan->custom_relids = tempset;
}
cscan->custom_relids = offset_relid_set(cscan->custom_relids, rtoffset);
}
/*
......@@ -1338,6 +1344,8 @@ set_append_references(PlannerInfo *root,
*/
set_dummy_tlist_references((Plan *) aplan, rtoffset);
aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
if (aplan->part_prune_info)
{
foreach(l, aplan->part_prune_info->prune_infos)
......@@ -1400,6 +1408,8 @@ set_mergeappend_references(PlannerInfo *root,
*/
set_dummy_tlist_references((Plan *) mplan, rtoffset);
mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
if (mplan->part_prune_info)
{
foreach(l, mplan->part_prune_info->prune_infos)
......@@ -1454,6 +1464,25 @@ set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset)
Assert(plan->qual == NIL);
}
/*
* offset_relid_set
* Apply rtoffset to the members of a Relids set.
*/
static Relids
offset_relid_set(Relids relids, int rtoffset)
{
Relids result = NULL;
int rtindex;
/* If there's no offset to apply, we needn't recompute the value */
if (rtoffset == 0)
return relids;
rtindex = -1;
while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
result = bms_add_member(result, rtindex + rtoffset);
return result;
}
/*
* copyVar
* Copy a Var node.
......
This diff is collapsed.
......@@ -1171,7 +1171,6 @@ typedef struct ModifyTableState
List **mt_arowmarks; /* per-subplan ExecAuxRowMark lists */
EPQState mt_epqstate; /* for evaluating EvalPlanQual rechecks */
bool fireBSTriggers; /* do we need to fire stmt triggers? */
List *mt_excludedtlist; /* the excluded pseudo relation's tlist */
/*
* Slot for storing tuples in the root partitioned table's rowtype during
......
......@@ -122,6 +122,8 @@ typedef struct PlannerGlobal
List *rootResultRelations; /* "flat" list of integer RT indexes */
List *appendRelations; /* "flat" list of AppendRelInfos */
List *relationOids; /* OIDs of relations the plan depends on */
List *invalItems; /* other dependencies, as PlanInvalItems */
......
......@@ -74,6 +74,8 @@ typedef struct PlannedStmt
*/
List *rootResultRelations;
List *appendRelations; /* list of AppendRelInfo nodes */
List *subplans; /* Plan trees for SubPlan expressions; note
* that some could be NULL */
......@@ -249,6 +251,7 @@ struct PartitionPruneInfo; /* forward reference to struct below */
typedef struct Append
{
Plan plan;
Bitmapset *apprelids; /* RTIs of appendrel(s) formed by this node */
List *appendplans;
/*
......@@ -269,6 +272,7 @@ typedef struct Append
typedef struct MergeAppend
{
Plan plan;
Bitmapset *apprelids; /* RTIs of appendrel(s) formed by this node */
List *mergeplans;
/* these fields are just like the sort-key info in struct Sort: */
int numCols; /* number of sort-key columns */
......
......@@ -17,6 +17,9 @@
#include "nodes/parsenodes.h"
#include "nodes/pg_list.h"
struct Plan; /* avoid including plannodes.h here */
struct PlannedStmt;
extern char *pg_get_indexdef_string(Oid indexrelid);
extern char *pg_get_indexdef_columns(Oid indexrelid, bool pretty);
......@@ -28,9 +31,10 @@ extern char *pg_get_constraintdef_command(Oid constraintId);
extern char *deparse_expression(Node *expr, List *dpcontext,
bool forceprefix, bool showimplicit);
extern List *deparse_context_for(const char *aliasname, Oid relid);
extern List *deparse_context_for_plan_rtable(List *rtable, List *rtable_names);
extern List *set_deparse_context_planstate(List *dpcontext,
Node *planstate, List *ancestors);
extern List *deparse_context_for_plan_tree(struct PlannedStmt *pstmt,
List *rtable_names);
extern List *set_deparse_context_plan(List *dpcontext,
struct Plan *plan, List *ancestors);
extern List *select_rtable_names_for_explain(List *rtable,
Bitmapset *rels_used);
extern char *generate_collation_name(Oid collid);
......
......@@ -1005,24 +1005,24 @@ explain (costs off)
-> Limit
-> Merge Append
Sort Key: minmaxtest.f1
-> Index Only Scan using minmaxtesti on minmaxtest
-> Index Only Scan using minmaxtesti on minmaxtest minmaxtest_1
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_1
-> Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_2
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_2
-> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_3
-> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4
InitPlan 2 (returns $1)
-> Limit
-> Merge Append
Sort Key: minmaxtest_4.f1 DESC
-> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_4
Sort Key: minmaxtest_5.f1 DESC
-> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_6
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_5
-> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_7
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_6
-> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_8
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_7
-> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9
(23 rows)
select min(f1), max(f1) from minmaxtest;
......@@ -1041,24 +1041,24 @@ explain (costs off)
-> Limit
-> Merge Append
Sort Key: minmaxtest.f1
-> Index Only Scan using minmaxtesti on minmaxtest
-> Index Only Scan using minmaxtesti on minmaxtest minmaxtest_1
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_1
-> Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_2
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_2
-> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_3
-> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4
InitPlan 2 (returns $1)
-> Limit
-> Merge Append
Sort Key: minmaxtest_4.f1 DESC
-> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_4
Sort Key: minmaxtest_5.f1 DESC
-> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_6
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_5
-> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_7
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_6
-> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_8
Index Cond: (f1 IS NOT NULL)
-> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_7
-> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9
-> Sort
Sort Key: ($0), ($1)
-> Result
......@@ -1155,8 +1155,8 @@ explain (costs off) select * from t1 group by a,b,c,d;
HashAggregate
Group Key: t1.a, t1.b, t1.c, t1.d
-> Append
-> Seq Scan on t1
-> Seq Scan on t1c t1_1
-> Seq Scan on t1 t1_1
-> Seq Scan on t1c t1_2
(5 rows)
-- Okay to remove columns if we're only querying the parent.
......@@ -1179,13 +1179,13 @@ create temp table p_t1_1 partition of p_t1 for values in(1);
create temp table p_t1_2 partition of p_t1 for values in(2);
-- Ensure we can remove non-PK columns for partitioned tables.
explain (costs off) select * from p_t1 group by a,b,c,d;
QUERY PLAN
---------------------------------------
QUERY PLAN
--------------------------------
HashAggregate
Group Key: p_t1.a, p_t1.b
-> Append
-> Seq Scan on p_t1_1 p_t1
-> Seq Scan on p_t1_2 p_t1_1
-> Seq Scan on p_t1_1
-> Seq Scan on p_t1_2
(5 rows)
drop table t1 cascade;
......
......@@ -540,11 +540,11 @@ explain (costs off) select * from nv_parent where d between '2011-08-01' and '20
QUERY PLAN
---------------------------------------------------------------------------
Append
-> Seq Scan on nv_parent
-> Seq Scan on nv_parent nv_parent_1
Filter: ((d >= '08-01-2011'::date) AND (d <= '08-31-2011'::date))
-> Seq Scan on nv_child_2010 nv_parent_1
-> Seq Scan on nv_child_2010 nv_parent_2
Filter: ((d >= '08-01-2011'::date) AND (d <= '08-31-2011'::date))
-> Seq Scan on nv_child_2011 nv_parent_2
-> Seq Scan on nv_child_2011 nv_parent_3
Filter: ((d >= '08-01-2011'::date) AND (d <= '08-31-2011'::date))
(7 rows)
......@@ -553,11 +553,11 @@ explain (costs off) select * from nv_parent where d between '2011-08-01'::date a
QUERY PLAN
---------------------------------------------------------------------------
Append
-> Seq Scan on nv_parent
-> Seq Scan on nv_parent nv_parent_1
Filter: ((d >= '08-01-2011'::date) AND (d <= '08-31-2011'::date))
-> Seq Scan on nv_child_2010 nv_parent_1
-> Seq Scan on nv_child_2010 nv_parent_2
Filter: ((d >= '08-01-2011'::date) AND (d <= '08-31-2011'::date))
-> Seq Scan on nv_child_2011 nv_parent_2
-> Seq Scan on nv_child_2011 nv_parent_3
Filter: ((d >= '08-01-2011'::date) AND (d <= '08-31-2011'::date))
(7 rows)
......@@ -565,13 +565,13 @@ explain (costs off) select * from nv_parent where d between '2009-08-01'::date a
QUERY PLAN
---------------------------------------------------------------------------
Append
-> Seq Scan on nv_parent
-> Seq Scan on nv_parent nv_parent_1
Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date))
-> Seq Scan on nv_child_2010 nv_parent_1
-> Seq Scan on nv_child_2010 nv_parent_2
Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date))
-> Seq Scan on nv_child_2011 nv_parent_2
-> Seq Scan on nv_child_2011 nv_parent_3
Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date))
-> Seq Scan on nv_child_2009 nv_parent_3
-> Seq Scan on nv_child_2009 nv_parent_4
Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date))
(9 rows)
......@@ -581,11 +581,11 @@ explain (costs off) select * from nv_parent where d between '2009-08-01'::date a
QUERY PLAN
---------------------------------------------------------------------------
Append
-> Seq Scan on nv_parent
-> Seq Scan on nv_parent nv_parent_1
Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date))
-> Seq Scan on nv_child_2010 nv_parent_1
-> Seq Scan on nv_child_2010 nv_parent_2
Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date))
-> Seq Scan on nv_child_2009 nv_parent_2
-> Seq Scan on nv_child_2009 nv_parent_3
Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date))
(7 rows)
......
This diff is collapsed.
......@@ -5779,8 +5779,8 @@ select t1.b, ss.phv from join_ut1 t1 left join lateral
(select t2.a as t2a, t3.a t3a, least(t1.a, t2.a, t3.a) phv
from join_pt1 t2 join join_ut1 t3 on t2.a = t3.b) ss
on t1.a = ss.t2a order by t1.a;
QUERY PLAN
------------------------------------------------------------------
QUERY PLAN
--------------------------------------------------------------------
Sort
Output: t1.b, (LEAST(t1.a, t2.a, t3.a)), t1.a
Sort Key: t1.a
......@@ -5796,12 +5796,12 @@ select t1.b, ss.phv from join_ut1 t1 left join lateral
-> Hash
Output: t2.a
-> Append
-> Seq Scan on public.join_pt1p1p1 t2
Output: t2.a
Filter: (t1.a = t2.a)
-> Seq Scan on public.join_pt1p2 t2_1
-> Seq Scan on public.join_pt1p1p1 t2_1
Output: t2_1.a
Filter: (t1.a = t2_1.a)
-> Seq Scan on public.join_pt1p2 t2_2
Output: t2_2.a
Filter: (t1.a = t2_2.a)
(21 rows)
select t1.b, ss.phv from join_ut1 t1 left join lateral
......
This diff is collapsed.
......@@ -21,12 +21,12 @@ explain (costs off)
Workers Planned: 3
-> Partial Aggregate
-> Parallel Append
-> Parallel Seq Scan on d_star a_star_3
-> Parallel Seq Scan on f_star a_star_5
-> Parallel Seq Scan on e_star a_star_4
-> Parallel Seq Scan on b_star a_star_1
-> Parallel Seq Scan on c_star a_star_2
-> Parallel Seq Scan on a_star
-> Parallel Seq Scan on d_star a_star_4
-> Parallel Seq Scan on f_star a_star_6
-> Parallel Seq Scan on e_star a_star_5
-> Parallel Seq Scan on b_star a_star_2
-> Parallel Seq Scan on c_star a_star_3
-> Parallel Seq Scan on a_star a_star_1
(11 rows)
select round(avg(aa)), sum(aa) from a_star a1;
......@@ -47,12 +47,12 @@ explain (costs off)
Workers Planned: 3
-> Partial Aggregate
-> Parallel Append
-> Seq Scan on d_star a_star_3
-> Seq Scan on c_star a_star_2
-> Parallel Seq Scan on f_star a_star_5
-> Parallel Seq Scan on e_star a_star_4
-> Parallel Seq Scan on b_star a_star_1
-> Parallel Seq Scan on a_star
-> Seq Scan on d_star a_star_4
-> Seq Scan on c_star a_star_3
-> Parallel Seq Scan on f_star a_star_6
-> Parallel Seq Scan on e_star a_star_5
-> Parallel Seq Scan on b_star a_star_2
-> Parallel Seq Scan on a_star a_star_1
(11 rows)
select round(avg(aa)), sum(aa) from a_star a2;
......@@ -75,12 +75,12 @@ explain (costs off)
Workers Planned: 3
-> Partial Aggregate
-> Parallel Append
-> Seq Scan on d_star a_star_3
-> Seq Scan on f_star a_star_5
-> Seq Scan on e_star a_star_4
-> Seq Scan on b_star a_star_1
-> Seq Scan on c_star a_star_2
-> Seq Scan on a_star
-> Seq Scan on d_star a_star_4
-> Seq Scan on f_star a_star_6
-> Seq Scan on e_star a_star_5
-> Seq Scan on b_star a_star_2
-> Seq Scan on c_star a_star_3
-> Seq Scan on a_star a_star_1
(11 rows)
select round(avg(aa)), sum(aa) from a_star a3;
......@@ -106,12 +106,12 @@ explain (costs off)
Workers Planned: 1
-> Partial Aggregate
-> Append
-> Parallel Seq Scan on a_star
-> Parallel Seq Scan on b_star a_star_1
-> Parallel Seq Scan on c_star a_star_2
-> Parallel Seq Scan on d_star a_star_3
-> Parallel Seq Scan on e_star a_star_4
-> Parallel Seq Scan on f_star a_star_5
-> Parallel Seq Scan on a_star a_star_1
-> Parallel Seq Scan on b_star a_star_2
-> Parallel Seq Scan on c_star a_star_3
-> Parallel Seq Scan on d_star a_star_4
-> Parallel Seq Scan on e_star a_star_5
-> Parallel Seq Scan on f_star a_star_6
(11 rows)
select round(avg(aa)), sum(aa) from a_star a4;
......@@ -145,15 +145,15 @@ explain (costs off)
-> Gather
Workers Planned: 3
-> Parallel Append
-> Parallel Seq Scan on part_pa_test_p1 pa2
-> Parallel Seq Scan on part_pa_test_p2 pa2_1
-> Parallel Seq Scan on part_pa_test_p1 pa2_1
-> Parallel Seq Scan on part_pa_test_p2 pa2_2
SubPlan 2
-> Result
SubPlan 1
-> Append
-> Seq Scan on part_pa_test_p1 pa1
-> Seq Scan on part_pa_test_p1 pa1_1
Filter: (a = pa2.a)
-> Seq Scan on part_pa_test_p2 pa1_1
-> Seq Scan on part_pa_test_p2 pa1_2
Filter: (a = pa2.a)
(14 rows)
......
......@@ -198,13 +198,13 @@ explain (costs off)
-------------------------------------------------
Aggregate
-> Append
-> Sample Scan on person
-> Sample Scan on person person_1
Sampling: bernoulli ('100'::real)
-> Sample Scan on emp person_1
-> Sample Scan on emp person_2
Sampling: bernoulli ('100'::real)
-> Sample Scan on student person_2
-> Sample Scan on student person_3
Sampling: bernoulli ('100'::real)
-> Sample Scan on stud_emp person_3
-> Sample Scan on stud_emp person_4
Sampling: bernoulli ('100'::real)
(10 rows)
......@@ -319,12 +319,12 @@ create table parted_sample_1 partition of parted_sample for values in (1);
create table parted_sample_2 partition of parted_sample for values in (2);
explain (costs off)
select * from parted_sample tablesample bernoulli (100);
QUERY PLAN
------------------------------------------------------
QUERY PLAN
-------------------------------------------
Append
-> Sample Scan on parted_sample_1 parted_sample
-> Sample Scan on parted_sample_1
Sampling: bernoulli ('100'::real)
-> Sample Scan on parted_sample_2 parted_sample_1
-> Sample Scan on parted_sample_2
Sampling: bernoulli ('100'::real)
(5 rows)
......
......@@ -1548,16 +1548,16 @@ INSERT INTO other_tbl_parent VALUES (7),(200);
INSERT INTO other_tbl_child VALUES (8),(100);
EXPLAIN (costs off)
UPDATE rw_view1 SET a = a + 1000 FROM other_tbl_parent WHERE a = id;
QUERY PLAN
------------------------------------------------------------------------
QUERY PLAN
-------------------------------------------------------------------------
Update on base_tbl_parent
Update on base_tbl_parent
Update on base_tbl_child base_tbl_parent_1
-> Hash Join
Hash Cond: (other_tbl_parent.id = base_tbl_parent.a)
-> Append
-> Seq Scan on other_tbl_parent
-> Seq Scan on other_tbl_child other_tbl_parent_1
-> Seq Scan on other_tbl_parent other_tbl_parent_1
-> Seq Scan on other_tbl_child other_tbl_parent_2
-> Hash
-> Seq Scan on base_tbl_parent
-> Merge Join
......@@ -1568,8 +1568,8 @@ UPDATE rw_view1 SET a = a + 1000 FROM other_tbl_parent WHERE a = id;
-> Sort
Sort Key: other_tbl_parent.id
-> Append
-> Seq Scan on other_tbl_parent
-> Seq Scan on other_tbl_child other_tbl_parent_1
-> Seq Scan on other_tbl_parent other_tbl_parent_1
-> Seq Scan on other_tbl_child other_tbl_parent_2
(20 rows)
UPDATE rw_view1 SET a = a + 1000 FROM other_tbl_parent WHERE a = id;
......@@ -2293,16 +2293,16 @@ UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6;
Filter: ((t1.a <> 6) AND (alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t1.a) AND leakproof(t1.a))
SubPlan 1
-> Append
-> Seq Scan on public.t12
Filter: (t12.a = t1.a)
-> Seq Scan on public.t111 t12_1
-> Seq Scan on public.t12 t12_1
Filter: (t12_1.a = t1.a)
-> Seq Scan on public.t111 t12_2
Filter: (t12_2.a = t1.a)
SubPlan 2
-> Append
-> Seq Scan on public.t12 t12_2
Output: t12_2.a
-> Seq Scan on public.t111 t12_3
Output: t12_3.a
-> Seq Scan on public.t12 t12_4
Output: t12_4.a
-> Seq Scan on public.t111 t12_5
Output: t12_5.a
-> Index Scan using t11_a_idx on public.t11 t1_1
Output: 100, t1_1.b, t1_1.c, t1_1.d, t1_1.ctid
Index Cond: ((t1_1.a > 5) AND (t1_1.a < 7))
......@@ -2343,16 +2343,16 @@ UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
Filter: ((alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t1.a) AND leakproof(t1.a))
SubPlan 1
-> Append
-> Seq Scan on public.t12
Filter: (t12.a = t1.a)
-> Seq Scan on public.t111 t12_1
-> Seq Scan on public.t12 t12_1
Filter: (t12_1.a = t1.a)
-> Seq Scan on public.t111 t12_2
Filter: (t12_2.a = t1.a)
SubPlan 2
-> Append
-> Seq Scan on public.t12 t12_2
Output: t12_2.a
-> Seq Scan on public.t111 t12_3
Output: t12_3.a
-> Seq Scan on public.t12 t12_4
Output: t12_4.a
-> Seq Scan on public.t111 t12_5
Output: t12_5.a
-> Index Scan using t11_a_idx on public.t11 t1_1
Output: (t1_1.a + 1), t1_1.b, t1_1.c, t1_1.d, t1_1.ctid
Index Cond: ((t1_1.a > 5) AND (t1_1.a = 8))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment