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 55a1954da),
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 1cc29fe7c, 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
This commit is contained in:
Tom Lane 2019-12-11 17:05:18 -05:00
parent ba79cb5dc8
commit 6ef77cf46e
26 changed files with 1966 additions and 1762 deletions

View File

@ -7094,10 +7094,10 @@ select * from bar where f1 in (select f1 from foo) for update;
Inner Unique: true Inner Unique: true
Hash Cond: (bar.f1 = foo.f1) Hash Cond: (bar.f1 = foo.f1)
-> Append -> Append
-> Seq Scan on public.bar -> Seq Scan on public.bar bar_1
Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid
-> Foreign Scan on public.bar2 bar_1
Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
-> Foreign Scan on public.bar2 bar_2
Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
-> Hash -> Hash
Output: foo.ctid, foo.f1, foo.*, foo.tableoid Output: foo.ctid, foo.f1, foo.*, foo.tableoid
@ -7105,10 +7105,10 @@ select * from bar where f1 in (select f1 from foo) for update;
Output: foo.ctid, foo.f1, foo.*, foo.tableoid Output: foo.ctid, foo.f1, foo.*, foo.tableoid
Group Key: foo.f1 Group Key: foo.f1
-> Append -> Append
-> Seq Scan on public.foo -> Seq Scan on public.foo foo_1
Output: foo.ctid, foo.f1, foo.*, foo.tableoid
-> Foreign Scan on public.foo2 foo_1
Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid
-> Foreign Scan on public.foo2 foo_2
Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
(23 rows) (23 rows)
@ -7132,10 +7132,10 @@ select * from bar where f1 in (select f1 from foo) for share;
Inner Unique: true Inner Unique: true
Hash Cond: (bar.f1 = foo.f1) Hash Cond: (bar.f1 = foo.f1)
-> Append -> Append
-> Seq Scan on public.bar -> Seq Scan on public.bar bar_1
Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid
-> Foreign Scan on public.bar2 bar_1
Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
-> Foreign Scan on public.bar2 bar_2
Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
-> Hash -> Hash
Output: foo.ctid, foo.f1, foo.*, foo.tableoid Output: foo.ctid, foo.f1, foo.*, foo.tableoid
@ -7143,10 +7143,10 @@ select * from bar where f1 in (select f1 from foo) for share;
Output: foo.ctid, foo.f1, foo.*, foo.tableoid Output: foo.ctid, foo.f1, foo.*, foo.tableoid
Group Key: foo.f1 Group Key: foo.f1
-> Append -> Append
-> Seq Scan on public.foo -> Seq Scan on public.foo foo_1
Output: foo.ctid, foo.f1, foo.*, foo.tableoid
-> Foreign Scan on public.foo2 foo_1
Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid
-> Foreign Scan on public.foo2 foo_2
Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
(23 rows) (23 rows)
@ -7180,10 +7180,10 @@ update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
Output: foo.ctid, foo.f1, foo.*, foo.tableoid Output: foo.ctid, foo.f1, foo.*, foo.tableoid
Group Key: foo.f1 Group Key: foo.f1
-> Append -> Append
-> Seq Scan on public.foo -> Seq Scan on public.foo foo_1
Output: foo.ctid, foo.f1, foo.*, foo.tableoid
-> Foreign Scan on public.foo2 foo_1
Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid
-> Foreign Scan on public.foo2 foo_2
Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
-> Hash Join -> Hash Join
Output: bar_1.f1, (bar_1.f2 + 100), bar_1.f3, bar_1.ctid, foo.ctid, foo.*, foo.tableoid Output: bar_1.f1, (bar_1.f2 + 100), bar_1.f3, bar_1.ctid, foo.ctid, foo.*, foo.tableoid
@ -7198,10 +7198,10 @@ update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
Output: foo.ctid, foo.f1, foo.*, foo.tableoid Output: foo.ctid, foo.f1, foo.*, foo.tableoid
Group Key: foo.f1 Group Key: foo.f1
-> Append -> Append
-> Seq Scan on public.foo -> Seq Scan on public.foo foo_1
Output: foo.ctid, foo.f1, foo.*, foo.tableoid
-> Foreign Scan on public.foo2 foo_1
Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid
-> Foreign Scan on public.foo2 foo_2
Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
(39 rows) (39 rows)
@ -7316,10 +7316,10 @@ explain (verbose, costs off)
Merge Cond: (foo.f1 = loct1.f1) Merge Cond: (foo.f1 = loct1.f1)
-> Merge Append -> Merge Append
Sort Key: foo.f1 Sort Key: foo.f1
-> Index Scan using i_foo_f1 on public.foo -> Index Scan using i_foo_f1 on public.foo foo_1
Output: foo.f1, foo.f2
-> Foreign Scan on public.foo2 foo_1
Output: foo_1.f1, foo_1.f2 Output: foo_1.f1, foo_1.f2
-> Foreign Scan on public.foo2 foo_2
Output: foo_2.f1, foo_2.f2
Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
-> Index Only Scan using i_loct1_f1 on public.loct1 -> Index Only Scan using i_loct1_f1 on public.loct1
Output: loct1.f1 Output: loct1.f1
@ -7356,10 +7356,10 @@ explain (verbose, costs off)
Merge Cond: (foo.f1 = loct1.f1) Merge Cond: (foo.f1 = loct1.f1)
-> Merge Append -> Merge Append
Sort Key: foo.f1 Sort Key: foo.f1
-> Index Scan using i_foo_f1 on public.foo -> Index Scan using i_foo_f1 on public.foo foo_1
Output: foo.f1, foo.f2
-> Foreign Scan on public.foo2 foo_1
Output: foo_1.f1, foo_1.f2 Output: foo_1.f1, foo_1.f2
-> Foreign Scan on public.foo2 foo_2
Output: foo_2.f1, foo_2.f2
Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
-> Index Only Scan using i_loct1_f1 on public.loct1 -> Index Only Scan using i_loct1_f1 on public.loct1
Output: loct1.f1 Output: loct1.f1
@ -8516,9 +8516,9 @@ SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER J
Sort Key: t1.a, t3.c Sort Key: t1.a, t3.c
-> Append -> Append
-> Foreign Scan -> Foreign Scan
Relations: ((ftprt1_p1 t1) INNER JOIN (ftprt2_p1 t2)) INNER JOIN (ftprt1_p1 t3) Relations: ((ftprt1_p1 t1_1) INNER JOIN (ftprt2_p1 t2_1)) INNER JOIN (ftprt1_p1 t3_1)
-> Foreign Scan -> Foreign Scan
Relations: ((ftprt1_p2 t1_1) INNER JOIN (ftprt2_p2 t2_1)) INNER JOIN (ftprt1_p2 t3_1) Relations: ((ftprt1_p2 t1_2) INNER JOIN (ftprt2_p2 t2_2)) INNER JOIN (ftprt1_p2 t3_2)
(7 rows) (7 rows)
SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3;
@ -8561,12 +8561,12 @@ SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1
-> Hash Full Join -> Hash Full Join
Hash Cond: (t1.a = t2.b) Hash Cond: (t1.a = t2.b)
-> Append -> Append
-> Foreign Scan on ftprt1_p1 t1 -> Foreign Scan on ftprt1_p1 t1_1
-> Foreign Scan on ftprt1_p2 t1_1 -> Foreign Scan on ftprt1_p2 t1_2
-> Hash -> Hash
-> Append -> Append
-> Foreign Scan on ftprt2_p1 t2 -> Foreign Scan on ftprt2_p1 t2_1
-> Foreign Scan on ftprt2_p2 t2_1 -> Foreign Scan on ftprt2_p2 t2_2
(11 rows) (11 rows)
SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2;
@ -8597,9 +8597,9 @@ SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t
Sort Key: t1.a, t1.b Sort Key: t1.a, t1.b
-> Append -> Append
-> Foreign Scan -> Foreign Scan
Relations: (ftprt1_p1 t1) INNER JOIN (ftprt2_p1 t2) Relations: (ftprt1_p1 t1_1) INNER JOIN (ftprt2_p1 t2_1)
-> Foreign Scan -> Foreign Scan
Relations: (ftprt1_p2 t1_1) INNER JOIN (ftprt2_p2 t2_1) Relations: (ftprt1_p2 t1_2) INNER JOIN (ftprt2_p2 t2_2)
(7 rows) (7 rows)
SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2;
@ -8619,16 +8619,16 @@ SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE
Sort Sort
Sort Key: fprt1.a, fprt2.b Sort Key: fprt1.a, fprt2.b
-> Append -> Append
-> Hash Full Join
Hash Cond: (fprt1.a = fprt2.b)
-> Foreign Scan on ftprt1_p1 fprt1
-> Hash
-> Foreign Scan on ftprt2_p1 fprt2
-> Hash Full Join -> Hash Full Join
Hash Cond: (fprt1_1.a = fprt2_1.b) Hash Cond: (fprt1_1.a = fprt2_1.b)
-> Foreign Scan on ftprt1_p2 fprt1_1 -> Foreign Scan on ftprt1_p1 fprt1_1
-> Hash -> Hash
-> Foreign Scan on ftprt2_p2 fprt2_1 -> Foreign Scan on ftprt2_p1 fprt2_1
-> Hash Full Join
Hash Cond: (fprt1_2.a = fprt2_2.b)
-> Foreign Scan on ftprt1_p2 fprt1_2
-> Hash
-> Foreign Scan on ftprt2_p2 fprt2_2
(13 rows) (13 rows)
SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b;
@ -8661,12 +8661,12 @@ SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a
-> Hash Join -> Hash Join
Hash Cond: (t2.b = t1.a) Hash Cond: (t2.b = t1.a)
-> Append -> Append
-> Foreign Scan on ftprt2_p1 t2 -> Foreign Scan on ftprt2_p1 t2_1
-> Foreign Scan on ftprt2_p2 t2_1 -> Foreign Scan on ftprt2_p2 t2_2
-> Hash -> Hash
-> Append -> Append
-> Foreign Scan on ftprt1_p1 t1 -> Foreign Scan on ftprt1_p1 t1_1
-> Foreign Scan on ftprt1_p2 t1_1 -> Foreign Scan on ftprt1_p2 t1_2
(12 rows) (12 rows)
SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1;
@ -8710,9 +8710,9 @@ SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 O
Group Key: pagg_tab.a Group Key: pagg_tab.a
Filter: (avg(pagg_tab.b) < '22'::numeric) Filter: (avg(pagg_tab.b) < '22'::numeric)
-> Append -> Append
-> Foreign Scan on fpagg_tab_p1 pagg_tab -> Foreign Scan on fpagg_tab_p1 pagg_tab_1
-> Foreign Scan on fpagg_tab_p2 pagg_tab_1 -> Foreign Scan on fpagg_tab_p2 pagg_tab_2
-> Foreign Scan on fpagg_tab_p3 pagg_tab_2 -> Foreign Scan on fpagg_tab_p3 pagg_tab_3
(9 rows) (9 rows)
-- Plan with partitionwise aggregates is enabled -- Plan with partitionwise aggregates is enabled

View File

@ -689,8 +689,8 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
es->rtable = queryDesc->plannedstmt->rtable; es->rtable = queryDesc->plannedstmt->rtable;
ExplainPreScanNode(queryDesc->planstate, &rels_used); ExplainPreScanNode(queryDesc->planstate, &rels_used);
es->rtable_names = select_rtable_names_for_explain(es->rtable, 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->deparse_cxt = deparse_context_for_plan_tree(queryDesc->plannedstmt,
es->rtable_names); es->rtable_names);
es->printed_subplans = NULL; es->printed_subplans = NULL;
/* /*
@ -1034,6 +1034,14 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
*rels_used = bms_add_member(*rels_used, *rels_used = bms_add_member(*rels_used,
((ModifyTable *) plan)->exclRelRTI); ((ModifyTable *) plan)->exclRelRTI);
break; 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: default:
break; 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 * 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. * 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. * ancestors is a list of parent Plan and SubPlan nodes, most-closely-nested
* These are needed in order to interpret PARAM_EXEC Params. * first. These are needed in order to interpret PARAM_EXEC Params.
* *
* relationship describes the relationship of this plan node to its parent * 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 * (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) if (haschildren)
{ {
ExplainOpenGroup("Plans", "Plans", false, es); ExplainOpenGroup("Plans", "Plans", false, es);
/* Pass current PlanState as head of ancestors list for children */ /* Pass current Plan as head of ancestors list for children */
ancestors = lcons(planstate, ancestors); ancestors = lcons(plan, ancestors);
} }
/* initPlan-s */ /* initPlan-s */
@ -2075,9 +2083,9 @@ show_plan_tlist(PlanState *planstate, List *ancestors, ExplainState *es)
return; return;
/* Set up deparsing context */ /* Set up deparsing context */
context = set_deparse_context_planstate(es->deparse_cxt, context = set_deparse_context_plan(es->deparse_cxt,
(Node *) planstate, plan,
ancestors); ancestors);
useprefix = list_length(es->rtable) > 1; useprefix = list_length(es->rtable) > 1;
/* Deparse each result column (we now include resjunk ones) */ /* Deparse each result column (we now include resjunk ones) */
@ -2106,9 +2114,9 @@ show_expression(Node *node, const char *qlabel,
char *exprstr; char *exprstr;
/* Set up deparsing context */ /* Set up deparsing context */
context = set_deparse_context_planstate(es->deparse_cxt, context = set_deparse_context_plan(es->deparse_cxt,
(Node *) planstate, planstate->plan,
ancestors); ancestors);
/* Deparse the expression */ /* Deparse the expression */
exprstr = deparse_expression(node, context, useprefix, false); exprstr = deparse_expression(node, context, useprefix, false);
@ -2209,7 +2217,7 @@ show_agg_keys(AggState *astate, List *ancestors,
if (plan->numCols > 0 || plan->groupingSets) if (plan->numCols > 0 || plan->groupingSets)
{ {
/* The key columns refer to the tlist of the child plan */ /* The key columns refer to the tlist of the child plan */
ancestors = lcons(astate, ancestors); ancestors = lcons(plan, ancestors);
if (plan->groupingSets) if (plan->groupingSets)
show_grouping_sets(outerPlanState(astate), plan, ancestors, es); show_grouping_sets(outerPlanState(astate), plan, ancestors, es);
@ -2232,9 +2240,9 @@ show_grouping_sets(PlanState *planstate, Agg *agg,
ListCell *lc; ListCell *lc;
/* Set up deparsing context */ /* Set up deparsing context */
context = set_deparse_context_planstate(es->deparse_cxt, context = set_deparse_context_plan(es->deparse_cxt,
(Node *) planstate, planstate->plan,
ancestors); ancestors);
useprefix = (list_length(es->rtable) > 1 || es->verbose); useprefix = (list_length(es->rtable) > 1 || es->verbose);
ExplainOpenGroup("Grouping Sets", "Grouping Sets", false, es); 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; Group *plan = (Group *) gstate->ss.ps.plan;
/* The key columns refer to the tlist of the child 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", show_sort_group_keys(outerPlanState(gstate), "Group Key",
plan->numCols, plan->grpColIdx, plan->numCols, plan->grpColIdx,
NULL, NULL, NULL, NULL, NULL, NULL,
@ -2371,9 +2379,9 @@ show_sort_group_keys(PlanState *planstate, const char *qlabel,
initStringInfo(&sortkeybuf); initStringInfo(&sortkeybuf);
/* Set up deparsing context */ /* Set up deparsing context */
context = set_deparse_context_planstate(es->deparse_cxt, context = set_deparse_context_plan(es->deparse_cxt,
(Node *) planstate, plan,
ancestors); ancestors);
useprefix = (list_length(es->rtable) > 1 || es->verbose); useprefix = (list_length(es->rtable) > 1 || es->verbose);
for (keyno = 0; keyno < nkeys; keyno++) for (keyno = 0; keyno < nkeys; keyno++)
@ -2479,9 +2487,9 @@ show_tablesample(TableSampleClause *tsc, PlanState *planstate,
ListCell *lc; ListCell *lc;
/* Set up deparsing context */ /* Set up deparsing context */
context = set_deparse_context_planstate(es->deparse_cxt, context = set_deparse_context_plan(es->deparse_cxt,
(Node *) planstate, planstate->plan,
ancestors); ancestors);
useprefix = list_length(es->rtable) > 1; useprefix = list_length(es->rtable) > 1;
/* Get the tablesample method name */ /* 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). * Explain a list of SubPlans (or initPlans, which also use SubPlan nodes).
* *
* The ancestors list should already contain the immediate parent of these * The ancestors list should already contain the immediate parent of these
* SubPlanStates. * SubPlans.
*/ */
static void static void
ExplainSubPlans(List *plans, List *ancestors, ExplainSubPlans(List *plans, List *ancestors,
@ -3372,8 +3380,17 @@ ExplainSubPlans(List *plans, List *ancestors,
es->printed_subplans = bms_add_member(es->printed_subplans, es->printed_subplans = bms_add_member(es->printed_subplans,
sp->plan_id); 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, ExplainNode(sps->planstate, ancestors,
relationship, sp->plan_name, es); relationship, sp->plan_name, es);
ancestors = list_delete_first(ancestors);
} }
} }

View File

@ -181,6 +181,8 @@ ExecSerializePlan(Plan *plan, EState *estate)
pstmt->planTree = plan; pstmt->planTree = plan;
pstmt->rtable = estate->es_range_table; pstmt->rtable = estate->es_range_table;
pstmt->resultRelations = NIL; pstmt->resultRelations = NIL;
pstmt->rootResultRelations = NIL;
pstmt->appendRelations = NIL;
/* /*
* Transfer only parallel-safe subplans, leaving a NULL "hole" in the list * Transfer only parallel-safe subplans, leaving a NULL "hole" in the list

View File

@ -2526,9 +2526,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
econtext = mtstate->ps.ps_ExprContext; econtext = mtstate->ps.ps_ExprContext;
relationDesc = resultRelInfo->ri_RelationDesc->rd_att; 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 */ /* create state for DO UPDATE SET operation */
resultRelInfo->ri_onConflict = makeNode(OnConflictSetState); resultRelInfo->ri_onConflict = makeNode(OnConflictSetState);

View File

@ -92,6 +92,7 @@ _copyPlannedStmt(const PlannedStmt *from)
COPY_NODE_FIELD(rtable); COPY_NODE_FIELD(rtable);
COPY_NODE_FIELD(resultRelations); COPY_NODE_FIELD(resultRelations);
COPY_NODE_FIELD(rootResultRelations); COPY_NODE_FIELD(rootResultRelations);
COPY_NODE_FIELD(appendRelations);
COPY_NODE_FIELD(subplans); COPY_NODE_FIELD(subplans);
COPY_BITMAPSET_FIELD(rewindPlanIDs); COPY_BITMAPSET_FIELD(rewindPlanIDs);
COPY_NODE_FIELD(rowMarks); COPY_NODE_FIELD(rowMarks);
@ -241,6 +242,7 @@ _copyAppend(const Append *from)
/* /*
* copy remainder of node * copy remainder of node
*/ */
COPY_BITMAPSET_FIELD(apprelids);
COPY_NODE_FIELD(appendplans); COPY_NODE_FIELD(appendplans);
COPY_SCALAR_FIELD(first_partial_plan); COPY_SCALAR_FIELD(first_partial_plan);
COPY_NODE_FIELD(part_prune_info); COPY_NODE_FIELD(part_prune_info);
@ -264,6 +266,7 @@ _copyMergeAppend(const MergeAppend *from)
/* /*
* copy remainder of node * copy remainder of node
*/ */
COPY_BITMAPSET_FIELD(apprelids);
COPY_NODE_FIELD(mergeplans); COPY_NODE_FIELD(mergeplans);
COPY_SCALAR_FIELD(numCols); COPY_SCALAR_FIELD(numCols);
COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber)); COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber));

View File

@ -310,6 +310,7 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node)
WRITE_NODE_FIELD(rtable); WRITE_NODE_FIELD(rtable);
WRITE_NODE_FIELD(resultRelations); WRITE_NODE_FIELD(resultRelations);
WRITE_NODE_FIELD(rootResultRelations); WRITE_NODE_FIELD(rootResultRelations);
WRITE_NODE_FIELD(appendRelations);
WRITE_NODE_FIELD(subplans); WRITE_NODE_FIELD(subplans);
WRITE_BITMAPSET_FIELD(rewindPlanIDs); WRITE_BITMAPSET_FIELD(rewindPlanIDs);
WRITE_NODE_FIELD(rowMarks); WRITE_NODE_FIELD(rowMarks);
@ -431,6 +432,7 @@ _outAppend(StringInfo str, const Append *node)
_outPlanInfo(str, (const Plan *) node); _outPlanInfo(str, (const Plan *) node);
WRITE_BITMAPSET_FIELD(apprelids);
WRITE_NODE_FIELD(appendplans); WRITE_NODE_FIELD(appendplans);
WRITE_INT_FIELD(first_partial_plan); WRITE_INT_FIELD(first_partial_plan);
WRITE_NODE_FIELD(part_prune_info); WRITE_NODE_FIELD(part_prune_info);
@ -443,6 +445,7 @@ _outMergeAppend(StringInfo str, const MergeAppend *node)
_outPlanInfo(str, (const Plan *) node); _outPlanInfo(str, (const Plan *) node);
WRITE_BITMAPSET_FIELD(apprelids);
WRITE_NODE_FIELD(mergeplans); WRITE_NODE_FIELD(mergeplans);
WRITE_INT_FIELD(numCols); WRITE_INT_FIELD(numCols);
WRITE_ATTRNUMBER_ARRAY(sortColIdx, node->numCols); WRITE_ATTRNUMBER_ARRAY(sortColIdx, node->numCols);
@ -2167,6 +2170,7 @@ _outPlannerGlobal(StringInfo str, const PlannerGlobal *node)
WRITE_NODE_FIELD(finalrowmarks); WRITE_NODE_FIELD(finalrowmarks);
WRITE_NODE_FIELD(resultRelations); WRITE_NODE_FIELD(resultRelations);
WRITE_NODE_FIELD(rootResultRelations); WRITE_NODE_FIELD(rootResultRelations);
WRITE_NODE_FIELD(appendRelations);
WRITE_NODE_FIELD(relationOids); WRITE_NODE_FIELD(relationOids);
WRITE_NODE_FIELD(invalItems); WRITE_NODE_FIELD(invalItems);
WRITE_NODE_FIELD(paramExecTypes); WRITE_NODE_FIELD(paramExecTypes);

View File

@ -1512,6 +1512,7 @@ _readPlannedStmt(void)
READ_NODE_FIELD(rtable); READ_NODE_FIELD(rtable);
READ_NODE_FIELD(resultRelations); READ_NODE_FIELD(resultRelations);
READ_NODE_FIELD(rootResultRelations); READ_NODE_FIELD(rootResultRelations);
READ_NODE_FIELD(appendRelations);
READ_NODE_FIELD(subplans); READ_NODE_FIELD(subplans);
READ_BITMAPSET_FIELD(rewindPlanIDs); READ_BITMAPSET_FIELD(rewindPlanIDs);
READ_NODE_FIELD(rowMarks); READ_NODE_FIELD(rowMarks);
@ -1636,6 +1637,7 @@ _readAppend(void)
ReadCommonPlan(&local_node->plan); ReadCommonPlan(&local_node->plan);
READ_BITMAPSET_FIELD(apprelids);
READ_NODE_FIELD(appendplans); READ_NODE_FIELD(appendplans);
READ_INT_FIELD(first_partial_plan); READ_INT_FIELD(first_partial_plan);
READ_NODE_FIELD(part_prune_info); READ_NODE_FIELD(part_prune_info);
@ -1653,6 +1655,7 @@ _readMergeAppend(void)
ReadCommonPlan(&local_node->plan); ReadCommonPlan(&local_node->plan);
READ_BITMAPSET_FIELD(apprelids);
READ_NODE_FIELD(mergeplans); READ_NODE_FIELD(mergeplans);
READ_INT_FIELD(numCols); READ_INT_FIELD(numCols);
READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols); READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols);

View File

@ -1118,6 +1118,7 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
plan->plan.qual = NIL; plan->plan.qual = NIL;
plan->plan.lefttree = NULL; plan->plan.lefttree = NULL;
plan->plan.righttree = NULL; plan->plan.righttree = NULL;
plan->apprelids = rel->relids;
if (pathkeys != NIL) if (pathkeys != NIL)
{ {
@ -1295,6 +1296,7 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
plan->qual = NIL; plan->qual = NIL;
plan->lefttree = NULL; plan->lefttree = NULL;
plan->righttree = NULL; plan->righttree = NULL;
node->apprelids = rel->relids;
/* /*
* Compute sort column info, and adjust MergeAppend's tlist as needed. * Compute sort column info, and adjust MergeAppend's tlist as needed.

View File

@ -304,6 +304,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
glob->finalrowmarks = NIL; glob->finalrowmarks = NIL;
glob->resultRelations = NIL; glob->resultRelations = NIL;
glob->rootResultRelations = NIL; glob->rootResultRelations = NIL;
glob->appendRelations = NIL;
glob->relationOids = NIL; glob->relationOids = NIL;
glob->invalItems = NIL; glob->invalItems = NIL;
glob->paramExecTypes = NIL; glob->paramExecTypes = NIL;
@ -494,6 +495,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
Assert(glob->finalrowmarks == NIL); Assert(glob->finalrowmarks == NIL);
Assert(glob->resultRelations == NIL); Assert(glob->resultRelations == NIL);
Assert(glob->rootResultRelations == NIL); Assert(glob->rootResultRelations == NIL);
Assert(glob->appendRelations == NIL);
top_plan = set_plan_references(root, top_plan); top_plan = set_plan_references(root, top_plan);
/* ... and the subplans (both regular subplans and initplans) */ /* ... and the subplans (both regular subplans and initplans) */
Assert(list_length(glob->subplans) == list_length(glob->subroots)); 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->rtable = glob->finalrtable;
result->resultRelations = glob->resultRelations; result->resultRelations = glob->resultRelations;
result->rootResultRelations = glob->rootResultRelations; result->rootResultRelations = glob->rootResultRelations;
result->appendRelations = glob->appendRelations;
result->subplans = glob->subplans; result->subplans = glob->subplans;
result->rewindPlanIDs = glob->rewindPlanIDs; result->rewindPlanIDs = glob->rewindPlanIDs;
result->rowMarks = glob->finalrowmarks; result->rowMarks = glob->finalrowmarks;
@ -1219,6 +1222,7 @@ inheritance_planner(PlannerInfo *root)
Index rootRelation = 0; Index rootRelation = 0;
List *final_rtable = NIL; List *final_rtable = NIL;
List *final_rowmarks = NIL; List *final_rowmarks = NIL;
List *final_appendrels = NIL;
int save_rel_array_size = 0; int save_rel_array_size = 0;
RelOptInfo **save_rel_array = NULL; RelOptInfo **save_rel_array = NULL;
AppendRelInfo **save_append_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 * modified subquery RTEs into final_rtable, to ensure we have sane
* copies of those. Also save the first non-excluded child's version * copies of those. Also save the first non-excluded child's version
* of the rowmarks list; we assume all children will end up with * 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) if (final_rtable == NIL)
{ {
final_rtable = subroot->parse->rtable; final_rtable = subroot->parse->rtable;
final_rowmarks = subroot->rowMarks; final_rowmarks = subroot->rowMarks;
final_appendrels = subroot->append_rel_list;
} }
else else
{ {
@ -1764,8 +1769,9 @@ inheritance_planner(PlannerInfo *root)
root->simple_rte_array[rti++] = rte; root->simple_rte_array[rti++] = rte;
} }
/* Put back adjusted rowmarks, too */ /* Put back adjusted rowmarks and appendrels, too */
root->rowMarks = final_rowmarks; root->rowMarks = final_rowmarks;
root->append_rel_list = final_appendrels;
} }
/* /*

View File

@ -108,6 +108,7 @@ static Plan *set_mergeappend_references(PlannerInfo *root,
MergeAppend *mplan, MergeAppend *mplan,
int rtoffset); int rtoffset);
static void set_hash_references(PlannerInfo *root, Plan *plan, 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(PlannerInfo *root, Node *node, int rtoffset);
static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context); 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); 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. * The flattened rangetable entries are appended to root->glob->finalrtable.
* Also, rowmarks entries are appended to root->glob->finalrowmarks, and the * 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) * Plan dependencies are appended to root->glob->relationOids (for relations)
* and root->glob->invalItems (for everything else). * and root->glob->invalItems (for everything else).
* *
@ -250,6 +252,28 @@ set_plan_references(PlannerInfo *root, Plan *plan)
glob->finalrowmarks = lappend(glob->finalrowmarks, newrc); 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 */ /* Now fix the Plan tree */
return set_plan_refs(root, plan, rtoffset); 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); fix_scan_list(root, fscan->fdw_recheck_quals, rtoffset);
} }
/* Adjust fs_relids if needed */ fscan->fs_relids = offset_relid_set(fscan->fs_relids, rtoffset);
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;
}
} }
/* /*
@ -1287,16 +1302,7 @@ set_customscan_references(PlannerInfo *root,
lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset); lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
} }
/* Adjust custom_relids if needed */ cscan->custom_relids = offset_relid_set(cscan->custom_relids, rtoffset);
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;
}
} }
/* /*
@ -1338,6 +1344,8 @@ set_append_references(PlannerInfo *root,
*/ */
set_dummy_tlist_references((Plan *) aplan, rtoffset); set_dummy_tlist_references((Plan *) aplan, rtoffset);
aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
if (aplan->part_prune_info) if (aplan->part_prune_info)
{ {
foreach(l, aplan->part_prune_info->prune_infos) foreach(l, aplan->part_prune_info->prune_infos)
@ -1400,6 +1408,8 @@ set_mergeappend_references(PlannerInfo *root,
*/ */
set_dummy_tlist_references((Plan *) mplan, rtoffset); set_dummy_tlist_references((Plan *) mplan, rtoffset);
mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
if (mplan->part_prune_info) if (mplan->part_prune_info)
{ {
foreach(l, mplan->part_prune_info->prune_infos) 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); 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 * copyVar
* Copy a Var node. * Copy a Var node.

View File

@ -49,6 +49,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h" #include "nodes/nodeFuncs.h"
#include "nodes/pathnodes.h"
#include "optimizer/optimizer.h" #include "optimizer/optimizer.h"
#include "parser/parse_agg.h" #include "parser/parse_agg.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
@ -118,6 +119,8 @@ typedef struct
bool varprefix; /* true to print prefixes on Vars */ bool varprefix; /* true to print prefixes on Vars */
ParseExprKind special_exprkind; /* set only for exprkinds needing special ParseExprKind special_exprkind; /* set only for exprkinds needing special
* handling */ * handling */
Bitmapset *appendparents; /* if not null, map child Vars of these relids
* back to the parent rel */
} deparse_context; } deparse_context;
/* /*
@ -125,13 +128,18 @@ typedef struct
* A Var having varlevelsup=N refers to the N'th item (counting from 0) in * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
* the current context's namespaces list. * the current context's namespaces list.
* *
* The rangetable is the list of actual RTEs from the query tree, and the * rtable is the list of actual RTEs from the Query or PlannedStmt.
* cte list is the list of actual CTEs.
*
* rtable_names holds the alias name to be used for each RTE (either a C * rtable_names holds the alias name to be used for each RTE (either a C
* string, or NULL for nameless RTEs such as unnamed joins). * string, or NULL for nameless RTEs such as unnamed joins).
* rtable_columns holds the column alias names to be used for each RTE. * rtable_columns holds the column alias names to be used for each RTE.
* *
* subplans is a list of Plan trees for SubPlans and CTEs (it's only used
* in the PlannedStmt case).
* ctes is a list of CommonTableExpr nodes (only used in the Query case).
* appendrels, if not null (it's only used in the PlannedStmt case), is an
* array of AppendRelInfo nodes, indexed by child relid. We use that to map
* child-table Vars to their inheritance parents.
*
* In some cases we need to make names of merged JOIN USING columns unique * In some cases we need to make names of merged JOIN USING columns unique
* across the whole query, not only per-RTE. If so, unique_using is true * across the whole query, not only per-RTE. If so, unique_using is true
* and using_names is a list of C strings representing names already assigned * and using_names is a list of C strings representing names already assigned
@ -139,28 +147,30 @@ typedef struct
* *
* When deparsing plan trees, there is always just a single item in the * When deparsing plan trees, there is always just a single item in the
* deparse_namespace list (since a plan tree never contains Vars with * deparse_namespace list (since a plan tree never contains Vars with
* varlevelsup > 0). We store the PlanState node that is the immediate * varlevelsup > 0). We store the Plan node that is the immediate
* parent of the expression to be deparsed, as well as a list of that * parent of the expression to be deparsed, as well as a list of that
* PlanState's ancestors. In addition, we store its outer and inner subplan * Plan's ancestors. In addition, we store its outer and inner subplan nodes,
* state nodes, as well as their plan nodes' targetlists, and the index tlist * as well as their targetlists, and the index tlist if the current plan node
* if the current plan node might contain INDEX_VAR Vars. (These fields could * might contain INDEX_VAR Vars. (These fields could be derived on-the-fly
* be derived on-the-fly from the current PlanState, but it seems notationally * from the current Plan node, but it seems notationally clearer to set them
* clearer to set them up as separate fields.) * up as separate fields.)
*/ */
typedef struct typedef struct
{ {
List *rtable; /* List of RangeTblEntry nodes */ List *rtable; /* List of RangeTblEntry nodes */
List *rtable_names; /* Parallel list of names for RTEs */ List *rtable_names; /* Parallel list of names for RTEs */
List *rtable_columns; /* Parallel list of deparse_columns structs */ List *rtable_columns; /* Parallel list of deparse_columns structs */
List *subplans; /* List of Plan trees for SubPlans */
List *ctes; /* List of CommonTableExpr nodes */ List *ctes; /* List of CommonTableExpr nodes */
AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */
/* Workspace for column alias assignment: */ /* Workspace for column alias assignment: */
bool unique_using; /* Are we making USING names globally unique */ bool unique_using; /* Are we making USING names globally unique */
List *using_names; /* List of assigned names for USING columns */ List *using_names; /* List of assigned names for USING columns */
/* Remaining fields are used only when deparsing a Plan tree: */ /* Remaining fields are used only when deparsing a Plan tree: */
PlanState *planstate; /* immediate parent of current expression */ Plan *plan; /* immediate parent of current expression */
List *ancestors; /* ancestors of planstate */ List *ancestors; /* ancestors of plan */
PlanState *outer_planstate; /* outer subplan state, or NULL if none */ Plan *outer_plan; /* outer subnode, or NULL if none */
PlanState *inner_planstate; /* inner subplan state, or NULL if none */ Plan *inner_plan; /* inner subnode, or NULL if none */
List *outer_tlist; /* referent for OUTER_VAR Vars */ List *outer_tlist; /* referent for OUTER_VAR Vars */
List *inner_tlist; /* referent for INNER_VAR Vars */ List *inner_tlist; /* referent for INNER_VAR Vars */
List *index_tlist; /* referent for INDEX_VAR Vars */ List *index_tlist; /* referent for INDEX_VAR Vars */
@ -287,6 +297,10 @@ typedef struct
int counter; /* Largest addition used so far for name */ int counter; /* Largest addition used so far for name */
} NameHashEntry; } NameHashEntry;
/* Callback signature for resolve_special_varno() */
typedef void (*rsv_callback) (Node *node, deparse_context *context,
void *callback_arg);
/* ---------- /* ----------
* Global data * Global data
@ -357,8 +371,8 @@ static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
static void flatten_join_using_qual(Node *qual, static void flatten_join_using_qual(Node *qual,
List **leftvars, List **rightvars); List **leftvars, List **rightvars);
static char *get_rtable_name(int rtindex, deparse_context *context); static char *get_rtable_name(int rtindex, deparse_context *context);
static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps); static void set_deparse_plan(deparse_namespace *dpns, Plan *plan);
static void push_child_plan(deparse_namespace *dpns, PlanState *ps, static void push_child_plan(deparse_namespace *dpns, Plan *plan,
deparse_namespace *save_dpns); deparse_namespace *save_dpns);
static void pop_child_plan(deparse_namespace *dpns, static void pop_child_plan(deparse_namespace *dpns,
deparse_namespace *save_dpns); deparse_namespace *save_dpns);
@ -404,10 +418,9 @@ static void get_rule_windowspec(WindowClause *wc, List *targetList,
static char *get_variable(Var *var, int levelsup, bool istoplevel, static char *get_variable(Var *var, int levelsup, bool istoplevel,
deparse_context *context); deparse_context *context);
static void get_special_variable(Node *node, deparse_context *context, static void get_special_variable(Node *node, deparse_context *context,
void *private); void *callback_arg);
static void resolve_special_varno(Node *node, deparse_context *context, static void resolve_special_varno(Node *node, deparse_context *context,
void *private, rsv_callback callback, void *callback_arg);
void (*callback) (Node *, deparse_context *, void *));
static Node *find_param_referent(Param *param, deparse_context *context, static Node *find_param_referent(Param *param, deparse_context *context,
deparse_namespace **dpns_p, ListCell **ancestor_cell_p); deparse_namespace **dpns_p, ListCell **ancestor_cell_p);
static void get_parameter(Param *param, deparse_context *context); static void get_parameter(Param *param, deparse_context *context);
@ -429,7 +442,7 @@ static void get_func_expr(FuncExpr *expr, deparse_context *context,
static void get_agg_expr(Aggref *aggref, deparse_context *context, static void get_agg_expr(Aggref *aggref, deparse_context *context,
Aggref *original_aggref); Aggref *original_aggref);
static void get_agg_combine_expr(Node *node, deparse_context *context, static void get_agg_combine_expr(Node *node, deparse_context *context,
void *private); void *callback_arg);
static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context); static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
static void get_coercion_expr(Node *arg, deparse_context *context, static void get_coercion_expr(Node *arg, deparse_context *context,
Oid resulttype, int32 resulttypmod, Oid resulttype, int32 resulttypmod,
@ -1022,7 +1035,9 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
/* Build two-element rtable */ /* Build two-element rtable */
memset(&dpns, 0, sizeof(dpns)); memset(&dpns, 0, sizeof(dpns));
dpns.rtable = list_make2(oldrte, newrte); dpns.rtable = list_make2(oldrte, newrte);
dpns.subplans = NIL;
dpns.ctes = NIL; dpns.ctes = NIL;
dpns.appendrels = NULL;
set_rtable_names(&dpns, NIL, NULL); set_rtable_names(&dpns, NIL, NULL);
set_simple_column_names(&dpns); set_simple_column_names(&dpns);
@ -1036,6 +1051,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
context.wrapColumn = WRAP_COLUMN_DEFAULT; context.wrapColumn = WRAP_COLUMN_DEFAULT;
context.indentLevel = PRETTYINDENT_STD; context.indentLevel = PRETTYINDENT_STD;
context.special_exprkind = EXPR_KIND_NONE; context.special_exprkind = EXPR_KIND_NONE;
context.appendparents = NULL;
get_rule_expr(qual, &context, false); get_rule_expr(qual, &context, false);
@ -3238,6 +3254,7 @@ deparse_expression_pretty(Node *expr, List *dpcontext,
context.wrapColumn = WRAP_COLUMN_DEFAULT; context.wrapColumn = WRAP_COLUMN_DEFAULT;
context.indentLevel = startIndent; context.indentLevel = startIndent;
context.special_exprkind = EXPR_KIND_NONE; context.special_exprkind = EXPR_KIND_NONE;
context.appendparents = NULL;
get_rule_expr(expr, &context, showimplicit); get_rule_expr(expr, &context, showimplicit);
@ -3274,7 +3291,9 @@ deparse_context_for(const char *aliasname, Oid relid)
/* Build one-element rtable */ /* Build one-element rtable */
dpns->rtable = list_make1(rte); dpns->rtable = list_make1(rte);
dpns->subplans = NIL;
dpns->ctes = NIL; dpns->ctes = NIL;
dpns->appendrels = NULL;
set_rtable_names(dpns, NIL, NULL); set_rtable_names(dpns, NIL, NULL);
set_simple_column_names(dpns); set_simple_column_names(dpns);
@ -3283,29 +3302,50 @@ deparse_context_for(const char *aliasname, Oid relid)
} }
/* /*
* deparse_context_for_plan_rtable - Build deparse context for a plan's rtable * deparse_context_for_plan_tree - Build deparse context for a Plan tree
* *
* When deparsing an expression in a Plan tree, we use the plan's rangetable * When deparsing an expression in a Plan tree, we use the plan's rangetable
* to resolve names of simple Vars. The initialization of column names for * to resolve names of simple Vars. The initialization of column names for
* this is rather expensive if the rangetable is large, and it'll be the same * this is rather expensive if the rangetable is large, and it'll be the same
* for every expression in the Plan tree; so we do it just once and re-use * for every expression in the Plan tree; so we do it just once and re-use
* the result of this function for each expression. (Note that the result * the result of this function for each expression. (Note that the result
* is not usable until set_deparse_context_planstate() is applied to it.) * is not usable until set_deparse_context_plan() is applied to it.)
* *
* In addition to the plan's rangetable list, pass the per-RTE alias names * In addition to the PlannedStmt, pass the per-RTE alias names
* assigned by a previous call to select_rtable_names_for_explain. * assigned by a previous call to select_rtable_names_for_explain.
*/ */
List * List *
deparse_context_for_plan_rtable(List *rtable, List *rtable_names) deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
{ {
deparse_namespace *dpns; deparse_namespace *dpns;
dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace)); dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
/* Initialize fields that stay the same across the whole plan tree */ /* Initialize fields that stay the same across the whole plan tree */
dpns->rtable = rtable; dpns->rtable = pstmt->rtable;
dpns->rtable_names = rtable_names; dpns->rtable_names = rtable_names;
dpns->subplans = pstmt->subplans;
dpns->ctes = NIL; dpns->ctes = NIL;
if (pstmt->appendRelations)
{
/* Set up the array, indexed by child relid */
int ntables = list_length(dpns->rtable);
ListCell *lc;
dpns->appendrels = (AppendRelInfo **)
palloc0((ntables + 1) * sizeof(AppendRelInfo *));
foreach(lc, pstmt->appendRelations)
{
AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
Index crelid = appinfo->child_relid;
Assert(crelid > 0 && crelid <= ntables);
Assert(dpns->appendrels[crelid] == NULL);
dpns->appendrels[crelid] = appinfo;
}
}
else
dpns->appendrels = NULL; /* don't need it */
/* /*
* Set up column name aliases. We will get rather bogus results for join * Set up column name aliases. We will get rather bogus results for join
@ -3319,11 +3359,11 @@ deparse_context_for_plan_rtable(List *rtable, List *rtable_names)
} }
/* /*
* set_deparse_context_planstate - Specify Plan node containing expression * set_deparse_context_plan - Specify Plan node containing expression
* *
* When deparsing an expression in a Plan tree, we might have to resolve * When deparsing an expression in a Plan tree, we might have to resolve
* OUTER_VAR, INNER_VAR, or INDEX_VAR references. To do this, the caller must * OUTER_VAR, INNER_VAR, or INDEX_VAR references. To do this, the caller must
* provide the parent PlanState node. Then OUTER_VAR and INNER_VAR references * provide the parent Plan node. Then OUTER_VAR and INNER_VAR references
* can be resolved by drilling down into the left and right child plans. * can be resolved by drilling down into the left and right child plans.
* Similarly, INDEX_VAR references can be resolved by reference to the * Similarly, INDEX_VAR references can be resolved by reference to the
* indextlist given in a parent IndexOnlyScan node, or to the scan tlist in * indextlist given in a parent IndexOnlyScan node, or to the scan tlist in
@ -3332,23 +3372,19 @@ deparse_context_for_plan_rtable(List *rtable, List *rtable_names)
* for those, we can only deparse the indexqualorig fields, which won't * for those, we can only deparse the indexqualorig fields, which won't
* contain INDEX_VAR Vars.) * contain INDEX_VAR Vars.)
* *
* Note: planstate really ought to be declared as "PlanState *", but we use * The ancestors list is a list of the Plan's parent Plan and SubPlan nodes,
* "Node *" to avoid having to include execnodes.h in ruleutils.h. * the most-closely-nested first. This is needed to resolve PARAM_EXEC
* * Params. Note we assume that all the Plan nodes share the same rtable.
* The ancestors list is a list of the PlanState's parent PlanStates, the
* most-closely-nested first. This is needed to resolve PARAM_EXEC Params.
* Note we assume that all the PlanStates share the same rtable.
* *
* Once this function has been called, deparse_expression() can be called on * Once this function has been called, deparse_expression() can be called on
* subsidiary expression(s) of the specified PlanState node. To deparse * subsidiary expression(s) of the specified Plan node. To deparse
* expressions of a different Plan node in the same Plan tree, re-call this * expressions of a different Plan node in the same Plan tree, re-call this
* function to identify the new parent Plan node. * function to identify the new parent Plan node.
* *
* The result is the same List passed in; this is a notational convenience. * The result is the same List passed in; this is a notational convenience.
*/ */
List * List *
set_deparse_context_planstate(List *dpcontext, set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors)
Node *planstate, List *ancestors)
{ {
deparse_namespace *dpns; deparse_namespace *dpns;
@ -3357,7 +3393,7 @@ set_deparse_context_planstate(List *dpcontext,
dpns = (deparse_namespace *) linitial(dpcontext); dpns = (deparse_namespace *) linitial(dpcontext);
/* Set our attention on the specific plan node passed in */ /* Set our attention on the specific plan node passed in */
set_deparse_planstate(dpns, (PlanState *) planstate); set_deparse_plan(dpns, plan);
dpns->ancestors = ancestors; dpns->ancestors = ancestors;
return dpcontext; return dpcontext;
@ -3377,7 +3413,9 @@ select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
memset(&dpns, 0, sizeof(dpns)); memset(&dpns, 0, sizeof(dpns));
dpns.rtable = rtable; dpns.rtable = rtable;
dpns.subplans = NIL;
dpns.ctes = NIL; dpns.ctes = NIL;
dpns.appendrels = NULL;
set_rtable_names(&dpns, NIL, rels_used); set_rtable_names(&dpns, NIL, rels_used);
/* We needn't bother computing column aliases yet */ /* We needn't bother computing column aliases yet */
@ -3557,7 +3595,9 @@ set_deparse_for_query(deparse_namespace *dpns, Query *query,
/* Initialize *dpns and fill rtable/ctes links */ /* Initialize *dpns and fill rtable/ctes links */
memset(dpns, 0, sizeof(deparse_namespace)); memset(dpns, 0, sizeof(deparse_namespace));
dpns->rtable = query->rtable; dpns->rtable = query->rtable;
dpns->subplans = NIL;
dpns->ctes = query->cteList; dpns->ctes = query->cteList;
dpns->appendrels = NULL;
/* Assign a unique relation alias to each RTE */ /* Assign a unique relation alias to each RTE */
set_rtable_names(dpns, parent_namespaces, NULL); set_rtable_names(dpns, parent_namespaces, NULL);
@ -4625,19 +4665,19 @@ get_rtable_name(int rtindex, deparse_context *context)
} }
/* /*
* set_deparse_planstate: set up deparse_namespace to parse subexpressions * set_deparse_plan: set up deparse_namespace to parse subexpressions
* of a given PlanState node * of a given Plan node
* *
* This sets the planstate, outer_planstate, inner_planstate, outer_tlist, * This sets the plan, outer_plan, inner_plan, outer_tlist, inner_tlist,
* inner_tlist, and index_tlist fields. Caller is responsible for adjusting * and index_tlist fields. Caller is responsible for adjusting the ancestors
* the ancestors list if necessary. Note that the rtable and ctes fields do * list if necessary. Note that the rtable, subplans, and ctes fields do
* not need to change when shifting attention to different plan nodes in a * not need to change when shifting attention to different plan nodes in a
* single plan tree. * single plan tree.
*/ */
static void static void
set_deparse_planstate(deparse_namespace *dpns, PlanState *ps) set_deparse_plan(deparse_namespace *dpns, Plan *plan)
{ {
dpns->planstate = ps; dpns->plan = plan;
/* /*
* We special-case Append and MergeAppend to pretend that the first child * We special-case Append and MergeAppend to pretend that the first child
@ -4647,17 +4687,17 @@ set_deparse_planstate(deparse_namespace *dpns, PlanState *ps)
* first child plan is the OUTER referent; this is to support RETURNING * first child plan is the OUTER referent; this is to support RETURNING
* lists containing references to non-target relations. * lists containing references to non-target relations.
*/ */
if (IsA(ps, AppendState)) if (IsA(plan, Append))
dpns->outer_planstate = ((AppendState *) ps)->appendplans[0]; dpns->outer_plan = linitial(((Append *) plan)->appendplans);
else if (IsA(ps, MergeAppendState)) else if (IsA(plan, MergeAppend))
dpns->outer_planstate = ((MergeAppendState *) ps)->mergeplans[0]; dpns->outer_plan = linitial(((MergeAppend *) plan)->mergeplans);
else if (IsA(ps, ModifyTableState)) else if (IsA(plan, ModifyTable))
dpns->outer_planstate = ((ModifyTableState *) ps)->mt_plans[0]; dpns->outer_plan = linitial(((ModifyTable *) plan)->plans);
else else
dpns->outer_planstate = outerPlanState(ps); dpns->outer_plan = outerPlan(plan);
if (dpns->outer_planstate) if (dpns->outer_plan)
dpns->outer_tlist = dpns->outer_planstate->plan->targetlist; dpns->outer_tlist = dpns->outer_plan->targetlist;
else else
dpns->outer_tlist = NIL; dpns->outer_tlist = NIL;
@ -4670,29 +4710,30 @@ set_deparse_planstate(deparse_namespace *dpns, PlanState *ps)
* to reuse OUTER, it's used for RETURNING in some modify table cases, * to reuse OUTER, it's used for RETURNING in some modify table cases,
* although not INSERT .. CONFLICT). * although not INSERT .. CONFLICT).
*/ */
if (IsA(ps, SubqueryScanState)) if (IsA(plan, SubqueryScan))
dpns->inner_planstate = ((SubqueryScanState *) ps)->subplan; dpns->inner_plan = ((SubqueryScan *) plan)->subplan;
else if (IsA(ps, CteScanState)) else if (IsA(plan, CteScan))
dpns->inner_planstate = ((CteScanState *) ps)->cteplanstate; dpns->inner_plan = list_nth(dpns->subplans,
else if (IsA(ps, ModifyTableState)) ((CteScan *) plan)->ctePlanId - 1);
dpns->inner_planstate = ps; else if (IsA(plan, ModifyTable))
dpns->inner_plan = plan;
else else
dpns->inner_planstate = innerPlanState(ps); dpns->inner_plan = innerPlan(plan);
if (IsA(ps, ModifyTableState)) if (IsA(plan, ModifyTable))
dpns->inner_tlist = ((ModifyTableState *) ps)->mt_excludedtlist; dpns->inner_tlist = ((ModifyTable *) plan)->exclRelTlist;
else if (dpns->inner_planstate) else if (dpns->inner_plan)
dpns->inner_tlist = dpns->inner_planstate->plan->targetlist; dpns->inner_tlist = dpns->inner_plan->targetlist;
else else
dpns->inner_tlist = NIL; dpns->inner_tlist = NIL;
/* Set up referent for INDEX_VAR Vars, if needed */ /* Set up referent for INDEX_VAR Vars, if needed */
if (IsA(ps->plan, IndexOnlyScan)) if (IsA(plan, IndexOnlyScan))
dpns->index_tlist = ((IndexOnlyScan *) ps->plan)->indextlist; dpns->index_tlist = ((IndexOnlyScan *) plan)->indextlist;
else if (IsA(ps->plan, ForeignScan)) else if (IsA(plan, ForeignScan))
dpns->index_tlist = ((ForeignScan *) ps->plan)->fdw_scan_tlist; dpns->index_tlist = ((ForeignScan *) plan)->fdw_scan_tlist;
else if (IsA(ps->plan, CustomScan)) else if (IsA(plan, CustomScan))
dpns->index_tlist = ((CustomScan *) ps->plan)->custom_scan_tlist; dpns->index_tlist = ((CustomScan *) plan)->custom_scan_tlist;
else else
dpns->index_tlist = NIL; dpns->index_tlist = NIL;
} }
@ -4710,17 +4751,17 @@ set_deparse_planstate(deparse_namespace *dpns, PlanState *ps)
* previous state for pop_child_plan. * previous state for pop_child_plan.
*/ */
static void static void
push_child_plan(deparse_namespace *dpns, PlanState *ps, push_child_plan(deparse_namespace *dpns, Plan *plan,
deparse_namespace *save_dpns) deparse_namespace *save_dpns)
{ {
/* Save state for restoration later */ /* Save state for restoration later */
*save_dpns = *dpns; *save_dpns = *dpns;
/* Link current plan node into ancestors list */ /* Link current plan node into ancestors list */
dpns->ancestors = lcons(dpns->planstate, dpns->ancestors); dpns->ancestors = lcons(dpns->plan, dpns->ancestors);
/* Set attention on selected child */ /* Set attention on selected child */
set_deparse_planstate(dpns, ps); set_deparse_plan(dpns, plan);
} }
/* /*
@ -4760,7 +4801,7 @@ static void
push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
deparse_namespace *save_dpns) deparse_namespace *save_dpns)
{ {
PlanState *ps = (PlanState *) lfirst(ancestor_cell); Plan *plan = (Plan *) lfirst(ancestor_cell);
/* Save state for restoration later */ /* Save state for restoration later */
*save_dpns = *dpns; *save_dpns = *dpns;
@ -4771,7 +4812,7 @@ push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
list_cell_number(dpns->ancestors, ancestor_cell) + 1); list_cell_number(dpns->ancestors, ancestor_cell) + 1);
/* Set attention on selected ancestor */ /* Set attention on selected ancestor */
set_deparse_planstate(dpns, ps); set_deparse_plan(dpns, plan);
} }
/* /*
@ -4931,6 +4972,7 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
context.wrapColumn = WRAP_COLUMN_DEFAULT; context.wrapColumn = WRAP_COLUMN_DEFAULT;
context.indentLevel = PRETTYINDENT_STD; context.indentLevel = PRETTYINDENT_STD;
context.special_exprkind = EXPR_KIND_NONE; context.special_exprkind = EXPR_KIND_NONE;
context.appendparents = NULL;
set_deparse_for_query(&dpns, query, NIL); set_deparse_for_query(&dpns, query, NIL);
@ -5093,6 +5135,7 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace,
context.wrapColumn = wrapColumn; context.wrapColumn = wrapColumn;
context.indentLevel = startIndent; context.indentLevel = startIndent;
context.special_exprkind = EXPR_KIND_NONE; context.special_exprkind = EXPR_KIND_NONE;
context.appendparents = NULL;
set_deparse_for_query(&dpns, query, parentnamespace); set_deparse_for_query(&dpns, query, parentnamespace);
@ -6694,15 +6737,62 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
*/ */
if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
{ {
rte = rt_fetch(var->varno, dpns->rtable); Index varno = var->varno;
refname = (char *) list_nth(dpns->rtable_names, var->varno - 1); AttrNumber varattno = var->varattno;
colinfo = deparse_columns_fetch(var->varno, dpns);
attnum = var->varattno; /*
* We might have been asked to map child Vars to some parent relation.
*/
if (context->appendparents && dpns->appendrels)
{
Index pvarno = varno;
AttrNumber pvarattno = varattno;
AppendRelInfo *appinfo = dpns->appendrels[pvarno];
bool found = false;
/* Only map up to inheritance parents, not UNION ALL appendrels */
while (appinfo &&
rt_fetch(appinfo->parent_relid,
dpns->rtable)->rtekind == RTE_RELATION)
{
found = false;
if (pvarattno > 0) /* system columns stay as-is */
{
if (pvarattno > appinfo->num_child_cols)
break; /* safety check */
pvarattno = appinfo->parent_colnos[pvarattno - 1];
if (pvarattno == 0)
break; /* Var is local to child */
}
pvarno = appinfo->parent_relid;
found = true;
/* If the parent is itself a child, continue up. */
Assert(pvarno > 0 && pvarno <= list_length(dpns->rtable));
appinfo = dpns->appendrels[pvarno];
}
/*
* If we found an ancestral rel, and that rel is included in
* appendparents, print that column not the original one.
*/
if (found && bms_is_member(pvarno, context->appendparents))
{
varno = pvarno;
varattno = pvarattno;
}
}
rte = rt_fetch(varno, dpns->rtable);
refname = (char *) list_nth(dpns->rtable_names, varno - 1);
colinfo = deparse_columns_fetch(varno, dpns);
attnum = varattno;
} }
else else
{ {
resolve_special_varno((Node *) var, context, NULL, resolve_special_varno((Node *) var, context,
get_special_variable); get_special_variable, NULL);
return NULL; return NULL;
} }
@ -6715,22 +6805,22 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
* no alias. So in that case, drill down to the subplan and print the * no alias. So in that case, drill down to the subplan and print the
* contents of the referenced tlist item. This works because in a plan * contents of the referenced tlist item. This works because in a plan
* tree, such Vars can only occur in a SubqueryScan or CteScan node, and * tree, such Vars can only occur in a SubqueryScan or CteScan node, and
* we'll have set dpns->inner_planstate to reference the child plan node. * we'll have set dpns->inner_plan to reference the child plan node.
*/ */
if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) && if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
attnum > list_length(rte->eref->colnames) && attnum > list_length(rte->eref->colnames) &&
dpns->inner_planstate) dpns->inner_plan)
{ {
TargetEntry *tle; TargetEntry *tle;
deparse_namespace save_dpns; deparse_namespace save_dpns;
tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); tle = get_tle_by_resno(dpns->inner_tlist, attnum);
if (!tle) if (!tle)
elog(ERROR, "invalid attnum %d for relation \"%s\"", elog(ERROR, "invalid attnum %d for relation \"%s\"",
var->varattno, rte->eref->aliasname); attnum, rte->eref->aliasname);
Assert(netlevelsup == 0); Assert(netlevelsup == 0);
push_child_plan(dpns, dpns->inner_planstate, &save_dpns); push_child_plan(dpns, dpns->inner_plan, &save_dpns);
/* /*
* Force parentheses because our caller probably assumed a Var is a * Force parentheses because our caller probably assumed a Var is a
@ -6829,13 +6919,13 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
* get_rule_expr. * get_rule_expr.
*/ */
static void static void
get_special_variable(Node *node, deparse_context *context, void *private) get_special_variable(Node *node, deparse_context *context, void *callback_arg)
{ {
StringInfo buf = context->buf; StringInfo buf = context->buf;
/* /*
* Force parentheses because our caller probably assumed a Var is a simple * For a non-Var referent, force parentheses because our caller probably
* expression. * assumed a Var is a simple expression.
*/ */
if (!IsA(node, Var)) if (!IsA(node, Var))
appendStringInfoChar(buf, '('); appendStringInfoChar(buf, '(');
@ -6850,16 +6940,19 @@ get_special_variable(Node *node, deparse_context *context, void *private)
* invoke the callback provided. * invoke the callback provided.
*/ */
static void static void
resolve_special_varno(Node *node, deparse_context *context, void *private, resolve_special_varno(Node *node, deparse_context *context,
void (*callback) (Node *, deparse_context *, void *)) rsv_callback callback, void *callback_arg)
{ {
Var *var; Var *var;
deparse_namespace *dpns; deparse_namespace *dpns;
/* This function is recursive, so let's be paranoid. */
check_stack_depth();
/* If it's not a Var, invoke the callback. */ /* If it's not a Var, invoke the callback. */
if (!IsA(node, Var)) if (!IsA(node, Var))
{ {
callback(node, context, private); (*callback) (node, context, callback_arg);
return; return;
} }
@ -6869,20 +6962,37 @@ resolve_special_varno(Node *node, deparse_context *context, void *private,
var->varlevelsup); var->varlevelsup);
/* /*
* It's a special RTE, so recurse. * If varno is special, recurse.
*/ */
if (var->varno == OUTER_VAR && dpns->outer_tlist) if (var->varno == OUTER_VAR && dpns->outer_tlist)
{ {
TargetEntry *tle; TargetEntry *tle;
deparse_namespace save_dpns; deparse_namespace save_dpns;
Bitmapset *save_appendparents;
tle = get_tle_by_resno(dpns->outer_tlist, var->varattno); tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
if (!tle) if (!tle)
elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno); elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
push_child_plan(dpns, dpns->outer_planstate, &save_dpns); /*
resolve_special_varno((Node *) tle->expr, context, private, callback); * If we're descending to the first child of an Append or MergeAppend,
* update appendparents. This will affect deparsing of all Vars
* appearing within the eventually-resolved subexpression.
*/
save_appendparents = context->appendparents;
if (IsA(dpns->plan, Append))
context->appendparents = bms_union(context->appendparents,
((Append *) dpns->plan)->apprelids);
else if (IsA(dpns->plan, MergeAppend))
context->appendparents = bms_union(context->appendparents,
((MergeAppend *) dpns->plan)->apprelids);
push_child_plan(dpns, dpns->outer_plan, &save_dpns);
resolve_special_varno((Node *) tle->expr, context,
callback, callback_arg);
pop_child_plan(dpns, &save_dpns); pop_child_plan(dpns, &save_dpns);
context->appendparents = save_appendparents;
return; return;
} }
else if (var->varno == INNER_VAR && dpns->inner_tlist) else if (var->varno == INNER_VAR && dpns->inner_tlist)
@ -6894,8 +7004,9 @@ resolve_special_varno(Node *node, deparse_context *context, void *private,
if (!tle) if (!tle)
elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno); elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
push_child_plan(dpns, dpns->inner_planstate, &save_dpns); push_child_plan(dpns, dpns->inner_plan, &save_dpns);
resolve_special_varno((Node *) tle->expr, context, private, callback); resolve_special_varno((Node *) tle->expr, context,
callback, callback_arg);
pop_child_plan(dpns, &save_dpns); pop_child_plan(dpns, &save_dpns);
return; return;
} }
@ -6907,14 +7018,15 @@ resolve_special_varno(Node *node, deparse_context *context, void *private,
if (!tle) if (!tle)
elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno); elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
resolve_special_varno((Node *) tle->expr, context, private, callback); resolve_special_varno((Node *) tle->expr, context,
callback, callback_arg);
return; return;
} }
else if (var->varno < 1 || var->varno > list_length(dpns->rtable)) else if (var->varno < 1 || var->varno > list_length(dpns->rtable))
elog(ERROR, "bogus varno: %d", var->varno); elog(ERROR, "bogus varno: %d", var->varno);
/* Not special. Just invoke the callback. */ /* Not special. Just invoke the callback. */
callback(node, context, private); (*callback) (node, context, callback_arg);
} }
/* /*
@ -7005,6 +7117,10 @@ get_name_for_var_field(Var *var, int fieldno,
* Try to find the relevant RTE in this rtable. In a plan tree, it's * Try to find the relevant RTE in this rtable. In a plan tree, it's
* likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
* down into the subplans, or INDEX_VAR, which is resolved similarly. * down into the subplans, or INDEX_VAR, which is resolved similarly.
*
* Note: unlike get_variable and resolve_special_varno, we need not worry
* about inheritance mapping: a child Var should have the same datatype as
* its parent, and here we're really only interested in the Var's type.
*/ */
if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
{ {
@ -7022,7 +7138,7 @@ get_name_for_var_field(Var *var, int fieldno,
elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno); elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
Assert(netlevelsup == 0); Assert(netlevelsup == 0);
push_child_plan(dpns, dpns->outer_planstate, &save_dpns); push_child_plan(dpns, dpns->outer_plan, &save_dpns);
result = get_name_for_var_field((Var *) tle->expr, fieldno, result = get_name_for_var_field((Var *) tle->expr, fieldno,
levelsup, context); levelsup, context);
@ -7041,7 +7157,7 @@ get_name_for_var_field(Var *var, int fieldno,
elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno); elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
Assert(netlevelsup == 0); Assert(netlevelsup == 0);
push_child_plan(dpns, dpns->inner_planstate, &save_dpns); push_child_plan(dpns, dpns->inner_plan, &save_dpns);
result = get_name_for_var_field((Var *) tle->expr, fieldno, result = get_name_for_var_field((Var *) tle->expr, fieldno,
levelsup, context); levelsup, context);
@ -7151,7 +7267,7 @@ get_name_for_var_field(Var *var, int fieldno,
deparse_namespace save_dpns; deparse_namespace save_dpns;
const char *result; const char *result;
if (!dpns->inner_planstate) if (!dpns->inner_plan)
elog(ERROR, "failed to find plan for subquery %s", elog(ERROR, "failed to find plan for subquery %s",
rte->eref->aliasname); rte->eref->aliasname);
tle = get_tle_by_resno(dpns->inner_tlist, attnum); tle = get_tle_by_resno(dpns->inner_tlist, attnum);
@ -7159,7 +7275,7 @@ get_name_for_var_field(Var *var, int fieldno,
elog(ERROR, "bogus varattno for subquery var: %d", elog(ERROR, "bogus varattno for subquery var: %d",
attnum); attnum);
Assert(netlevelsup == 0); Assert(netlevelsup == 0);
push_child_plan(dpns, dpns->inner_planstate, &save_dpns); push_child_plan(dpns, dpns->inner_plan, &save_dpns);
result = get_name_for_var_field((Var *) tle->expr, fieldno, result = get_name_for_var_field((Var *) tle->expr, fieldno,
levelsup, context); levelsup, context);
@ -7269,7 +7385,7 @@ get_name_for_var_field(Var *var, int fieldno,
deparse_namespace save_dpns; deparse_namespace save_dpns;
const char *result; const char *result;
if (!dpns->inner_planstate) if (!dpns->inner_plan)
elog(ERROR, "failed to find plan for CTE %s", elog(ERROR, "failed to find plan for CTE %s",
rte->eref->aliasname); rte->eref->aliasname);
tle = get_tle_by_resno(dpns->inner_tlist, attnum); tle = get_tle_by_resno(dpns->inner_tlist, attnum);
@ -7277,7 +7393,7 @@ get_name_for_var_field(Var *var, int fieldno,
elog(ERROR, "bogus varattno for subquery var: %d", elog(ERROR, "bogus varattno for subquery var: %d",
attnum); attnum);
Assert(netlevelsup == 0); Assert(netlevelsup == 0);
push_child_plan(dpns, dpns->inner_planstate, &save_dpns); push_child_plan(dpns, dpns->inner_plan, &save_dpns);
result = get_name_for_var_field((Var *) tle->expr, fieldno, result = get_name_for_var_field((Var *) tle->expr, fieldno,
levelsup, context); levelsup, context);
@ -7318,22 +7434,22 @@ find_param_referent(Param *param, deparse_context *context,
/* /*
* If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
* SubPlan argument. This will necessarily be in some ancestor of the * SubPlan argument. This will necessarily be in some ancestor of the
* current expression's PlanState. * current expression's Plan node.
*/ */
if (param->paramkind == PARAM_EXEC) if (param->paramkind == PARAM_EXEC)
{ {
deparse_namespace *dpns; deparse_namespace *dpns;
PlanState *child_ps; Plan *child_plan;
bool in_same_plan_level; bool in_same_plan_level;
ListCell *lc; ListCell *lc;
dpns = (deparse_namespace *) linitial(context->namespaces); dpns = (deparse_namespace *) linitial(context->namespaces);
child_ps = dpns->planstate; child_plan = dpns->plan;
in_same_plan_level = true; in_same_plan_level = true;
foreach(lc, dpns->ancestors) foreach(lc, dpns->ancestors)
{ {
PlanState *ps = (PlanState *) lfirst(lc); Node *ancestor = (Node *) lfirst(lc);
ListCell *lc2; ListCell *lc2;
/* /*
@ -7341,11 +7457,11 @@ find_param_referent(Param *param, deparse_context *context,
* we've crawled up out of a subplan, this couldn't possibly be * we've crawled up out of a subplan, this couldn't possibly be
* the right match. * the right match.
*/ */
if (IsA(ps, NestLoopState) && if (IsA(ancestor, NestLoop) &&
child_ps == innerPlanState(ps) && child_plan == innerPlan(ancestor) &&
in_same_plan_level) in_same_plan_level)
{ {
NestLoop *nl = (NestLoop *) ps->plan; NestLoop *nl = (NestLoop *) ancestor;
foreach(lc2, nl->nestParams) foreach(lc2, nl->nestParams)
{ {
@ -7362,19 +7478,14 @@ find_param_referent(Param *param, deparse_context *context,
} }
/* /*
* Check to see if we're crawling up from a subplan. * If ancestor is a SubPlan, check the arguments it provides.
*/ */
foreach(lc2, ps->subPlan) if (IsA(ancestor, SubPlan))
{ {
SubPlanState *sstate = (SubPlanState *) lfirst(lc2); SubPlan *subplan = (SubPlan *) ancestor;
SubPlan *subplan = sstate->subplan;
ListCell *lc3; ListCell *lc3;
ListCell *lc4; ListCell *lc4;
if (child_ps != sstate->planstate)
continue;
/* Matched subplan, so check its arguments */
forboth(lc3, subplan->parParam, lc4, subplan->args) forboth(lc3, subplan->parParam, lc4, subplan->args)
{ {
int paramid = lfirst_int(lc3); int paramid = lfirst_int(lc3);
@ -7382,41 +7493,61 @@ find_param_referent(Param *param, deparse_context *context,
if (paramid == param->paramid) if (paramid == param->paramid)
{ {
/* Found a match, so return it */ /*
*dpns_p = dpns; * Found a match, so return it. But, since Vars in
*ancestor_cell_p = lc; * the arg are to be evaluated in the surrounding
return arg; * context, we have to point to the next ancestor item
* that is *not* a SubPlan.
*/
ListCell *rest;
for_each_cell(rest, dpns->ancestors,
lnext(dpns->ancestors, lc))
{
Node *ancestor2 = (Node *) lfirst(rest);
if (!IsA(ancestor2, SubPlan))
{
*dpns_p = dpns;
*ancestor_cell_p = rest;
return arg;
}
}
elog(ERROR, "SubPlan cannot be outermost ancestor");
} }
} }
/* Keep looking, but we are emerging from a subplan. */ /* We have emerged from a subplan. */
in_same_plan_level = false; in_same_plan_level = false;
break;
/* SubPlan isn't a kind of Plan, so skip the rest */
continue;
} }
/* /*
* Likewise check to see if we're emerging from an initplan. * Check to see if we're emerging from an initplan of the current
* Initplans never have any parParams, so no need to search that * ancestor plan. Initplans never have any parParams, so no need
* list, but we need to know if we should reset * to search that list, but we need to know if we should reset
* in_same_plan_level. * in_same_plan_level.
*/ */
foreach(lc2, ps->initPlan) foreach(lc2, ((Plan *) ancestor)->initPlan)
{ {
SubPlanState *sstate = (SubPlanState *) lfirst(lc2); SubPlan *subplan = castNode(SubPlan, lfirst(lc2));
if (child_ps != sstate->planstate) if (child_plan != (Plan *) list_nth(dpns->subplans,
subplan->plan_id - 1))
continue; continue;
/* No parameters to be had here. */ /* No parameters to be had here. */
Assert(sstate->subplan->parParam == NIL); Assert(subplan->parParam == NIL);
/* Keep looking, but we are emerging from an initplan. */ /* We have emerged from an initplan. */
in_same_plan_level = false; in_same_plan_level = false;
break; break;
} }
/* No luck, crawl up to next ancestor */ /* No luck, crawl up to next ancestor */
child_ps = ps; child_plan = (Plan *) ancestor;
} }
} }
@ -9269,11 +9400,12 @@ get_agg_expr(Aggref *aggref, deparse_context *context,
*/ */
if (DO_AGGSPLIT_COMBINE(aggref->aggsplit)) if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
{ {
TargetEntry *tle = linitial_node(TargetEntry, aggref->args); TargetEntry *tle;
Assert(list_length(aggref->args) == 1); Assert(list_length(aggref->args) == 1);
resolve_special_varno((Node *) tle->expr, context, original_aggref, tle = linitial_node(TargetEntry, aggref->args);
get_agg_combine_expr); resolve_special_varno((Node *) tle->expr, context,
get_agg_combine_expr, original_aggref);
return; return;
} }
@ -9358,10 +9490,10 @@ get_agg_expr(Aggref *aggref, deparse_context *context,
* Aggref and then calls this. * Aggref and then calls this.
*/ */
static void static void
get_agg_combine_expr(Node *node, deparse_context *context, void *private) get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
{ {
Aggref *aggref; Aggref *aggref;
Aggref *original_aggref = private; Aggref *original_aggref = callback_arg;
if (!IsA(node, Aggref)) if (!IsA(node, Aggref))
elog(ERROR, "combining Aggref does not point to an Aggref"); elog(ERROR, "combining Aggref does not point to an Aggref");

View File

@ -1171,7 +1171,6 @@ typedef struct ModifyTableState
List **mt_arowmarks; /* per-subplan ExecAuxRowMark lists */ List **mt_arowmarks; /* per-subplan ExecAuxRowMark lists */
EPQState mt_epqstate; /* for evaluating EvalPlanQual rechecks */ EPQState mt_epqstate; /* for evaluating EvalPlanQual rechecks */
bool fireBSTriggers; /* do we need to fire stmt triggers? */ 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 * Slot for storing tuples in the root partitioned table's rowtype during

View File

@ -122,6 +122,8 @@ typedef struct PlannerGlobal
List *rootResultRelations; /* "flat" list of integer RT indexes */ List *rootResultRelations; /* "flat" list of integer RT indexes */
List *appendRelations; /* "flat" list of AppendRelInfos */
List *relationOids; /* OIDs of relations the plan depends on */ List *relationOids; /* OIDs of relations the plan depends on */
List *invalItems; /* other dependencies, as PlanInvalItems */ List *invalItems; /* other dependencies, as PlanInvalItems */

View File

@ -74,6 +74,8 @@ typedef struct PlannedStmt
*/ */
List *rootResultRelations; List *rootResultRelations;
List *appendRelations; /* list of AppendRelInfo nodes */
List *subplans; /* Plan trees for SubPlan expressions; note List *subplans; /* Plan trees for SubPlan expressions; note
* that some could be NULL */ * that some could be NULL */
@ -249,6 +251,7 @@ struct PartitionPruneInfo; /* forward reference to struct below */
typedef struct Append typedef struct Append
{ {
Plan plan; Plan plan;
Bitmapset *apprelids; /* RTIs of appendrel(s) formed by this node */
List *appendplans; List *appendplans;
/* /*
@ -269,6 +272,7 @@ typedef struct Append
typedef struct MergeAppend typedef struct MergeAppend
{ {
Plan plan; Plan plan;
Bitmapset *apprelids; /* RTIs of appendrel(s) formed by this node */
List *mergeplans; List *mergeplans;
/* these fields are just like the sort-key info in struct Sort: */ /* these fields are just like the sort-key info in struct Sort: */
int numCols; /* number of sort-key columns */ int numCols; /* number of sort-key columns */

View File

@ -17,6 +17,9 @@
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "nodes/pg_list.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_string(Oid indexrelid);
extern char *pg_get_indexdef_columns(Oid indexrelid, bool pretty); 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, extern char *deparse_expression(Node *expr, List *dpcontext,
bool forceprefix, bool showimplicit); bool forceprefix, bool showimplicit);
extern List *deparse_context_for(const char *aliasname, Oid relid); extern List *deparse_context_for(const char *aliasname, Oid relid);
extern List *deparse_context_for_plan_rtable(List *rtable, List *rtable_names); extern List *deparse_context_for_plan_tree(struct PlannedStmt *pstmt,
extern List *set_deparse_context_planstate(List *dpcontext, List *rtable_names);
Node *planstate, List *ancestors); extern List *set_deparse_context_plan(List *dpcontext,
struct Plan *plan, List *ancestors);
extern List *select_rtable_names_for_explain(List *rtable, extern List *select_rtable_names_for_explain(List *rtable,
Bitmapset *rels_used); Bitmapset *rels_used);
extern char *generate_collation_name(Oid collid); extern char *generate_collation_name(Oid collid);

View File

@ -1005,24 +1005,24 @@ explain (costs off)
-> Limit -> Limit
-> Merge Append -> Merge Append
Sort Key: minmaxtest.f1 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 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 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 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) InitPlan 2 (returns $1)
-> Limit -> Limit
-> Merge Append -> Merge Append
Sort Key: minmaxtest_4.f1 DESC Sort Key: minmaxtest_5.f1 DESC
-> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_4 -> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_6
Index Cond: (f1 IS NOT NULL) 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 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 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) (23 rows)
select min(f1), max(f1) from minmaxtest; select min(f1), max(f1) from minmaxtest;
@ -1041,24 +1041,24 @@ explain (costs off)
-> Limit -> Limit
-> Merge Append -> Merge Append
Sort Key: minmaxtest.f1 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 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 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 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) InitPlan 2 (returns $1)
-> Limit -> Limit
-> Merge Append -> Merge Append
Sort Key: minmaxtest_4.f1 DESC Sort Key: minmaxtest_5.f1 DESC
-> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_4 -> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_6
Index Cond: (f1 IS NOT NULL) 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 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 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
Sort Key: ($0), ($1) Sort Key: ($0), ($1)
-> Result -> Result
@ -1155,8 +1155,8 @@ explain (costs off) select * from t1 group by a,b,c,d;
HashAggregate HashAggregate
Group Key: t1.a, t1.b, t1.c, t1.d Group Key: t1.a, t1.b, t1.c, t1.d
-> Append -> Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
-> Seq Scan on t1c t1_1 -> Seq Scan on t1c t1_2
(5 rows) (5 rows)
-- Okay to remove columns if we're only querying the parent. -- 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); create temp table p_t1_2 partition of p_t1 for values in(2);
-- Ensure we can remove non-PK columns for partitioned tables. -- Ensure we can remove non-PK columns for partitioned tables.
explain (costs off) select * from p_t1 group by a,b,c,d; explain (costs off) select * from p_t1 group by a,b,c,d;
QUERY PLAN QUERY PLAN
--------------------------------------- --------------------------------
HashAggregate HashAggregate
Group Key: p_t1.a, p_t1.b Group Key: p_t1.a, p_t1.b
-> Append -> Append
-> Seq Scan on p_t1_1 p_t1 -> Seq Scan on p_t1_1
-> Seq Scan on p_t1_2 p_t1_1 -> Seq Scan on p_t1_2
(5 rows) (5 rows)
drop table t1 cascade; drop table t1 cascade;

View File

@ -540,11 +540,11 @@ explain (costs off) select * from nv_parent where d between '2011-08-01' and '20
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Append 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)) 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)) 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)) Filter: ((d >= '08-01-2011'::date) AND (d <= '08-31-2011'::date))
(7 rows) (7 rows)
@ -553,11 +553,11 @@ explain (costs off) select * from nv_parent where d between '2011-08-01'::date a
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Append 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)) 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)) 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)) Filter: ((d >= '08-01-2011'::date) AND (d <= '08-31-2011'::date))
(7 rows) (7 rows)
@ -565,13 +565,13 @@ explain (costs off) select * from nv_parent where d between '2009-08-01'::date a
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Append 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)) 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)) 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)) 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)) Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date))
(9 rows) (9 rows)
@ -581,11 +581,11 @@ explain (costs off) select * from nv_parent where d between '2009-08-01'::date a
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Append 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)) 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)) 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)) Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date))
(7 rows) (7 rows)

View File

@ -1338,11 +1338,11 @@ select * from patest0 join (select f1 from int4_tbl limit 1) ss on id = f1;
-> Limit -> Limit
-> Seq Scan on int4_tbl -> Seq Scan on int4_tbl
-> Append -> Append
-> Index Scan using patest0i on patest0 -> Index Scan using patest0i on patest0 patest0_1
Index Cond: (id = int4_tbl.f1) Index Cond: (id = int4_tbl.f1)
-> Index Scan using patest1i on patest1 patest0_1 -> Index Scan using patest1i on patest1 patest0_2
Index Cond: (id = int4_tbl.f1) Index Cond: (id = int4_tbl.f1)
-> Index Scan using patest2i on patest2 patest0_2 -> Index Scan using patest2i on patest2 patest0_3
Index Cond: (id = int4_tbl.f1) Index Cond: (id = int4_tbl.f1)
(10 rows) (10 rows)
@ -1363,11 +1363,11 @@ select * from patest0 join (select f1 from int4_tbl limit 1) ss on id = f1;
-> Limit -> Limit
-> Seq Scan on int4_tbl -> Seq Scan on int4_tbl
-> Append -> Append
-> Index Scan using patest0i on patest0 -> Index Scan using patest0i on patest0 patest0_1
Index Cond: (id = int4_tbl.f1) Index Cond: (id = int4_tbl.f1)
-> Index Scan using patest1i on patest1 patest0_1 -> Index Scan using patest1i on patest1 patest0_2
Index Cond: (id = int4_tbl.f1) Index Cond: (id = int4_tbl.f1)
-> Seq Scan on patest2 patest0_2 -> Seq Scan on patest2 patest0_3
Filter: (int4_tbl.f1 = id) Filter: (int4_tbl.f1 = id)
(10 rows) (10 rows)
@ -1413,14 +1413,14 @@ explain (verbose, costs off) select * from matest0 order by 1-id;
-> Result -> Result
Output: matest0.id, matest0.name, (1 - matest0.id) Output: matest0.id, matest0.name, (1 - matest0.id)
-> Append -> Append
-> Seq Scan on public.matest0 -> Seq Scan on public.matest0 matest0_1
Output: matest0.id, matest0.name
-> Seq Scan on public.matest1 matest0_1
Output: matest0_1.id, matest0_1.name Output: matest0_1.id, matest0_1.name
-> Seq Scan on public.matest2 matest0_2 -> Seq Scan on public.matest1 matest0_2
Output: matest0_2.id, matest0_2.name Output: matest0_2.id, matest0_2.name
-> Seq Scan on public.matest3 matest0_3 -> Seq Scan on public.matest2 matest0_3
Output: matest0_3.id, matest0_3.name Output: matest0_3.id, matest0_3.name
-> Seq Scan on public.matest3 matest0_4
Output: matest0_4.id, matest0_4.name
(14 rows) (14 rows)
select * from matest0 order by 1-id; select * from matest0 order by 1-id;
@ -1440,14 +1440,14 @@ explain (verbose, costs off) select min(1-id) from matest0;
Aggregate Aggregate
Output: min((1 - matest0.id)) Output: min((1 - matest0.id))
-> Append -> Append
-> Seq Scan on public.matest0 -> Seq Scan on public.matest0 matest0_1
Output: matest0.id
-> Seq Scan on public.matest1 matest0_1
Output: matest0_1.id Output: matest0_1.id
-> Seq Scan on public.matest2 matest0_2 -> Seq Scan on public.matest1 matest0_2
Output: matest0_2.id Output: matest0_2.id
-> Seq Scan on public.matest3 matest0_3 -> Seq Scan on public.matest2 matest0_3
Output: matest0_3.id Output: matest0_3.id
-> Seq Scan on public.matest3 matest0_4
Output: matest0_4.id
(11 rows) (11 rows)
select min(1-id) from matest0; select min(1-id) from matest0;
@ -1464,17 +1464,17 @@ explain (verbose, costs off) select * from matest0 order by 1-id;
------------------------------------------------------------------------ ------------------------------------------------------------------------
Merge Append Merge Append
Sort Key: ((1 - matest0.id)) Sort Key: ((1 - matest0.id))
-> Index Scan using matest0i on public.matest0 -> Index Scan using matest0i on public.matest0 matest0_1
Output: matest0.id, matest0.name, (1 - matest0.id)
-> Index Scan using matest1i on public.matest1 matest0_1
Output: matest0_1.id, matest0_1.name, (1 - matest0_1.id) Output: matest0_1.id, matest0_1.name, (1 - matest0_1.id)
-> Index Scan using matest1i on public.matest1 matest0_2
Output: matest0_2.id, matest0_2.name, (1 - matest0_2.id)
-> Sort -> Sort
Output: matest0_2.id, matest0_2.name, ((1 - matest0_2.id)) Output: matest0_3.id, matest0_3.name, ((1 - matest0_3.id))
Sort Key: ((1 - matest0_2.id)) Sort Key: ((1 - matest0_3.id))
-> Seq Scan on public.matest2 matest0_2 -> Seq Scan on public.matest2 matest0_3
Output: matest0_2.id, matest0_2.name, (1 - matest0_2.id) Output: matest0_3.id, matest0_3.name, (1 - matest0_3.id)
-> Index Scan using matest3i on public.matest3 matest0_3 -> Index Scan using matest3i on public.matest3 matest0_4
Output: matest0_3.id, matest0_3.name, (1 - matest0_3.id) Output: matest0_4.id, matest0_4.name, (1 - matest0_4.id)
(13 rows) (13 rows)
select * from matest0 order by 1-id; select * from matest0 order by 1-id;
@ -1500,22 +1500,22 @@ explain (verbose, costs off) select min(1-id) from matest0;
Output: ((1 - matest0.id)) Output: ((1 - matest0.id))
-> Merge Append -> Merge Append
Sort Key: ((1 - matest0.id)) Sort Key: ((1 - matest0.id))
-> Index Scan using matest0i on public.matest0 -> Index Scan using matest0i on public.matest0 matest0_1
Output: matest0.id, (1 - matest0.id)
Index Cond: ((1 - matest0.id) IS NOT NULL)
-> Index Scan using matest1i on public.matest1 matest0_1
Output: matest0_1.id, (1 - matest0_1.id) Output: matest0_1.id, (1 - matest0_1.id)
Index Cond: ((1 - matest0_1.id) IS NOT NULL) Index Cond: ((1 - matest0_1.id) IS NOT NULL)
-> Index Scan using matest1i on public.matest1 matest0_2
Output: matest0_2.id, (1 - matest0_2.id)
Index Cond: ((1 - matest0_2.id) IS NOT NULL)
-> Sort -> Sort
Output: matest0_2.id, ((1 - matest0_2.id)) Output: matest0_3.id, ((1 - matest0_3.id))
Sort Key: ((1 - matest0_2.id)) Sort Key: ((1 - matest0_3.id))
-> Bitmap Heap Scan on public.matest2 matest0_2 -> Bitmap Heap Scan on public.matest2 matest0_3
Output: matest0_2.id, (1 - matest0_2.id) Output: matest0_3.id, (1 - matest0_3.id)
Filter: ((1 - matest0_2.id) IS NOT NULL) Filter: ((1 - matest0_3.id) IS NOT NULL)
-> Bitmap Index Scan on matest2_pkey -> Bitmap Index Scan on matest2_pkey
-> Index Scan using matest3i on public.matest3 matest0_3 -> Index Scan using matest3i on public.matest3 matest0_4
Output: matest0_3.id, (1 - matest0_3.id) Output: matest0_4.id, (1 - matest0_4.id)
Index Cond: ((1 - matest0_3.id) IS NOT NULL) Index Cond: ((1 - matest0_4.id) IS NOT NULL)
(25 rows) (25 rows)
select min(1-id) from matest0; select min(1-id) from matest0;
@ -1551,14 +1551,14 @@ order by t1.b limit 10;
Merge Cond: (t1.b = t2.b) Merge Cond: (t1.b = t2.b)
-> Merge Append -> Merge Append
Sort Key: t1.b Sort Key: t1.b
-> Index Scan using matest0i on matest0 t1 -> Index Scan using matest0i on matest0 t1_1
-> Index Scan using matest1i on matest1 t1_1 -> Index Scan using matest1i on matest1 t1_2
-> Materialize -> Materialize
-> Merge Append -> Merge Append
Sort Key: t2.b Sort Key: t2.b
-> Index Scan using matest0i on matest0 t2 -> Index Scan using matest0i on matest0 t2_1
Filter: (c = d) Filter: (c = d)
-> Index Scan using matest1i on matest1 t2_1 -> Index Scan using matest1i on matest1 t2_2
Filter: (c = d) Filter: (c = d)
(14 rows) (14 rows)
@ -1783,9 +1783,9 @@ explain (costs off) select * from list_parted;
QUERY PLAN QUERY PLAN
---------------------------------------------- ----------------------------------------------
Append Append
-> Seq Scan on part_ab_cd list_parted -> Seq Scan on part_ab_cd list_parted_1
-> Seq Scan on part_ef_gh list_parted_1 -> Seq Scan on part_ef_gh list_parted_2
-> Seq Scan on part_null_xy list_parted_2 -> Seq Scan on part_null_xy list_parted_3
(4 rows) (4 rows)
explain (costs off) select * from list_parted where a is null; explain (costs off) select * from list_parted where a is null;
@ -1799,11 +1799,11 @@ explain (costs off) select * from list_parted where a is not null;
QUERY PLAN QUERY PLAN
---------------------------------------------- ----------------------------------------------
Append Append
-> Seq Scan on part_ab_cd list_parted -> Seq Scan on part_ab_cd list_parted_1
Filter: (a IS NOT NULL) Filter: (a IS NOT NULL)
-> Seq Scan on part_ef_gh list_parted_1 -> Seq Scan on part_ef_gh list_parted_2
Filter: (a IS NOT NULL) Filter: (a IS NOT NULL)
-> Seq Scan on part_null_xy list_parted_2 -> Seq Scan on part_null_xy list_parted_3
Filter: (a IS NOT NULL) Filter: (a IS NOT NULL)
(7 rows) (7 rows)
@ -1811,9 +1811,9 @@ explain (costs off) select * from list_parted where a in ('ab', 'cd', 'ef');
QUERY PLAN QUERY PLAN
---------------------------------------------------------- ----------------------------------------------------------
Append Append
-> Seq Scan on part_ab_cd list_parted -> Seq Scan on part_ab_cd list_parted_1
Filter: ((a)::text = ANY ('{ab,cd,ef}'::text[])) Filter: ((a)::text = ANY ('{ab,cd,ef}'::text[]))
-> Seq Scan on part_ef_gh list_parted_1 -> Seq Scan on part_ef_gh list_parted_2
Filter: ((a)::text = ANY ('{ab,cd,ef}'::text[])) Filter: ((a)::text = ANY ('{ab,cd,ef}'::text[]))
(5 rows) (5 rows)
@ -1852,24 +1852,24 @@ explain (costs off) select * from range_list_parted;
QUERY PLAN QUERY PLAN
-------------------------------------------------------- --------------------------------------------------------
Append Append
-> Seq Scan on part_1_10_ab range_list_parted -> Seq Scan on part_1_10_ab range_list_parted_1
-> Seq Scan on part_1_10_cd range_list_parted_1 -> Seq Scan on part_1_10_cd range_list_parted_2
-> Seq Scan on part_10_20_ab range_list_parted_2 -> Seq Scan on part_10_20_ab range_list_parted_3
-> Seq Scan on part_10_20_cd range_list_parted_3 -> Seq Scan on part_10_20_cd range_list_parted_4
-> Seq Scan on part_21_30_ab range_list_parted_4 -> Seq Scan on part_21_30_ab range_list_parted_5
-> Seq Scan on part_21_30_cd range_list_parted_5 -> Seq Scan on part_21_30_cd range_list_parted_6
-> Seq Scan on part_40_inf_ab range_list_parted_6 -> Seq Scan on part_40_inf_ab range_list_parted_7
-> Seq Scan on part_40_inf_cd range_list_parted_7 -> Seq Scan on part_40_inf_cd range_list_parted_8
-> Seq Scan on part_40_inf_null range_list_parted_8 -> Seq Scan on part_40_inf_null range_list_parted_9
(10 rows) (10 rows)
explain (costs off) select * from range_list_parted where a = 5; explain (costs off) select * from range_list_parted where a = 5;
QUERY PLAN QUERY PLAN
---------------------------------------------------- ----------------------------------------------------
Append Append
-> Seq Scan on part_1_10_ab range_list_parted -> Seq Scan on part_1_10_ab range_list_parted_1
Filter: (a = 5) Filter: (a = 5)
-> Seq Scan on part_1_10_cd range_list_parted_1 -> Seq Scan on part_1_10_cd range_list_parted_2
Filter: (a = 5) Filter: (a = 5)
(5 rows) (5 rows)
@ -1877,13 +1877,13 @@ explain (costs off) select * from range_list_parted where b = 'ab';
QUERY PLAN QUERY PLAN
------------------------------------------------------ ------------------------------------------------------
Append Append
-> Seq Scan on part_1_10_ab range_list_parted -> Seq Scan on part_1_10_ab range_list_parted_1
Filter: (b = 'ab'::bpchar) Filter: (b = 'ab'::bpchar)
-> Seq Scan on part_10_20_ab range_list_parted_1 -> Seq Scan on part_10_20_ab range_list_parted_2
Filter: (b = 'ab'::bpchar) Filter: (b = 'ab'::bpchar)
-> Seq Scan on part_21_30_ab range_list_parted_2 -> Seq Scan on part_21_30_ab range_list_parted_3
Filter: (b = 'ab'::bpchar) Filter: (b = 'ab'::bpchar)
-> Seq Scan on part_40_inf_ab range_list_parted_3 -> Seq Scan on part_40_inf_ab range_list_parted_4
Filter: (b = 'ab'::bpchar) Filter: (b = 'ab'::bpchar)
(9 rows) (9 rows)
@ -1891,11 +1891,11 @@ explain (costs off) select * from range_list_parted where a between 3 and 23 and
QUERY PLAN QUERY PLAN
----------------------------------------------------------------- -----------------------------------------------------------------
Append Append
-> Seq Scan on part_1_10_ab range_list_parted -> Seq Scan on part_1_10_ab range_list_parted_1
Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar)) Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
-> Seq Scan on part_10_20_ab range_list_parted_1 -> Seq Scan on part_10_20_ab range_list_parted_2
Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar)) Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
-> Seq Scan on part_21_30_ab range_list_parted_2 -> Seq Scan on part_21_30_ab range_list_parted_3
Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar)) Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
(7 rows) (7 rows)
@ -1919,23 +1919,23 @@ explain (costs off) select * from range_list_parted where a is not null and a <
QUERY PLAN QUERY PLAN
-------------------------------------------------------- --------------------------------------------------------
Append Append
-> Seq Scan on part_1_10_ab range_list_parted -> Seq Scan on part_1_10_ab range_list_parted_1
Filter: ((a IS NOT NULL) AND (a < 67)) Filter: ((a IS NOT NULL) AND (a < 67))
-> Seq Scan on part_1_10_cd range_list_parted_1 -> Seq Scan on part_1_10_cd range_list_parted_2
Filter: ((a IS NOT NULL) AND (a < 67)) Filter: ((a IS NOT NULL) AND (a < 67))
-> Seq Scan on part_10_20_ab range_list_parted_2 -> Seq Scan on part_10_20_ab range_list_parted_3
Filter: ((a IS NOT NULL) AND (a < 67)) Filter: ((a IS NOT NULL) AND (a < 67))
-> Seq Scan on part_10_20_cd range_list_parted_3 -> Seq Scan on part_10_20_cd range_list_parted_4
Filter: ((a IS NOT NULL) AND (a < 67)) Filter: ((a IS NOT NULL) AND (a < 67))
-> Seq Scan on part_21_30_ab range_list_parted_4 -> Seq Scan on part_21_30_ab range_list_parted_5
Filter: ((a IS NOT NULL) AND (a < 67)) Filter: ((a IS NOT NULL) AND (a < 67))
-> Seq Scan on part_21_30_cd range_list_parted_5 -> Seq Scan on part_21_30_cd range_list_parted_6
Filter: ((a IS NOT NULL) AND (a < 67)) Filter: ((a IS NOT NULL) AND (a < 67))
-> Seq Scan on part_40_inf_ab range_list_parted_6 -> Seq Scan on part_40_inf_ab range_list_parted_7
Filter: ((a IS NOT NULL) AND (a < 67)) Filter: ((a IS NOT NULL) AND (a < 67))
-> Seq Scan on part_40_inf_cd range_list_parted_7 -> Seq Scan on part_40_inf_cd range_list_parted_8
Filter: ((a IS NOT NULL) AND (a < 67)) Filter: ((a IS NOT NULL) AND (a < 67))
-> Seq Scan on part_40_inf_null range_list_parted_8 -> Seq Scan on part_40_inf_null range_list_parted_9
Filter: ((a IS NOT NULL) AND (a < 67)) Filter: ((a IS NOT NULL) AND (a < 67))
(19 rows) (19 rows)
@ -1943,11 +1943,11 @@ explain (costs off) select * from range_list_parted where a >= 30;
QUERY PLAN QUERY PLAN
-------------------------------------------------------- --------------------------------------------------------
Append Append
-> Seq Scan on part_40_inf_ab range_list_parted -> Seq Scan on part_40_inf_ab range_list_parted_1
Filter: (a >= 30) Filter: (a >= 30)
-> Seq Scan on part_40_inf_cd range_list_parted_1 -> Seq Scan on part_40_inf_cd range_list_parted_2
Filter: (a >= 30) Filter: (a >= 30)
-> Seq Scan on part_40_inf_null range_list_parted_2 -> Seq Scan on part_40_inf_null range_list_parted_3
Filter: (a >= 30) Filter: (a >= 30)
(7 rows) (7 rows)
@ -1967,9 +1967,9 @@ explain (costs off) select * from mcrparted where a = 0; -- scans mcrparted0, mc
QUERY PLAN QUERY PLAN
--------------------------------------------- ---------------------------------------------
Append Append
-> Seq Scan on mcrparted0 mcrparted -> Seq Scan on mcrparted0 mcrparted_1
Filter: (a = 0) Filter: (a = 0)
-> Seq Scan on mcrparted_def mcrparted_1 -> Seq Scan on mcrparted_def mcrparted_2
Filter: (a = 0) Filter: (a = 0)
(5 rows) (5 rows)
@ -1977,9 +1977,9 @@ explain (costs off) select * from mcrparted where a = 10 and abs(b) < 5; -- scan
QUERY PLAN QUERY PLAN
--------------------------------------------- ---------------------------------------------
Append Append
-> Seq Scan on mcrparted1 mcrparted -> Seq Scan on mcrparted1 mcrparted_1
Filter: ((a = 10) AND (abs(b) < 5)) Filter: ((a = 10) AND (abs(b) < 5))
-> Seq Scan on mcrparted_def mcrparted_1 -> Seq Scan on mcrparted_def mcrparted_2
Filter: ((a = 10) AND (abs(b) < 5)) Filter: ((a = 10) AND (abs(b) < 5))
(5 rows) (5 rows)
@ -1987,11 +1987,11 @@ explain (costs off) select * from mcrparted where a = 10 and abs(b) = 5; -- scan
QUERY PLAN QUERY PLAN
--------------------------------------------- ---------------------------------------------
Append Append
-> Seq Scan on mcrparted1 mcrparted -> Seq Scan on mcrparted1 mcrparted_1
Filter: ((a = 10) AND (abs(b) = 5)) Filter: ((a = 10) AND (abs(b) = 5))
-> Seq Scan on mcrparted2 mcrparted_1 -> Seq Scan on mcrparted2 mcrparted_2
Filter: ((a = 10) AND (abs(b) = 5)) Filter: ((a = 10) AND (abs(b) = 5))
-> Seq Scan on mcrparted_def mcrparted_2 -> Seq Scan on mcrparted_def mcrparted_3
Filter: ((a = 10) AND (abs(b) = 5)) Filter: ((a = 10) AND (abs(b) = 5))
(7 rows) (7 rows)
@ -1999,19 +1999,19 @@ explain (costs off) select * from mcrparted where abs(b) = 5; -- scans all parti
QUERY PLAN QUERY PLAN
--------------------------------------------- ---------------------------------------------
Append Append
-> Seq Scan on mcrparted0 mcrparted -> Seq Scan on mcrparted0 mcrparted_1
Filter: (abs(b) = 5) Filter: (abs(b) = 5)
-> Seq Scan on mcrparted1 mcrparted_1 -> Seq Scan on mcrparted1 mcrparted_2
Filter: (abs(b) = 5) Filter: (abs(b) = 5)
-> Seq Scan on mcrparted2 mcrparted_2 -> Seq Scan on mcrparted2 mcrparted_3
Filter: (abs(b) = 5) Filter: (abs(b) = 5)
-> Seq Scan on mcrparted3 mcrparted_3 -> Seq Scan on mcrparted3 mcrparted_4
Filter: (abs(b) = 5) Filter: (abs(b) = 5)
-> Seq Scan on mcrparted4 mcrparted_4 -> Seq Scan on mcrparted4 mcrparted_5
Filter: (abs(b) = 5) Filter: (abs(b) = 5)
-> Seq Scan on mcrparted5 mcrparted_5 -> Seq Scan on mcrparted5 mcrparted_6
Filter: (abs(b) = 5) Filter: (abs(b) = 5)
-> Seq Scan on mcrparted_def mcrparted_6 -> Seq Scan on mcrparted_def mcrparted_7
Filter: (abs(b) = 5) Filter: (abs(b) = 5)
(15 rows) (15 rows)
@ -2019,19 +2019,19 @@ explain (costs off) select * from mcrparted where a > -1; -- scans all partition
QUERY PLAN QUERY PLAN
--------------------------------------------- ---------------------------------------------
Append Append
-> Seq Scan on mcrparted0 mcrparted -> Seq Scan on mcrparted0 mcrparted_1
Filter: (a > '-1'::integer) Filter: (a > '-1'::integer)
-> Seq Scan on mcrparted1 mcrparted_1 -> Seq Scan on mcrparted1 mcrparted_2
Filter: (a > '-1'::integer) Filter: (a > '-1'::integer)
-> Seq Scan on mcrparted2 mcrparted_2 -> Seq Scan on mcrparted2 mcrparted_3
Filter: (a > '-1'::integer) Filter: (a > '-1'::integer)
-> Seq Scan on mcrparted3 mcrparted_3 -> Seq Scan on mcrparted3 mcrparted_4
Filter: (a > '-1'::integer) Filter: (a > '-1'::integer)
-> Seq Scan on mcrparted4 mcrparted_4 -> Seq Scan on mcrparted4 mcrparted_5
Filter: (a > '-1'::integer) Filter: (a > '-1'::integer)
-> Seq Scan on mcrparted5 mcrparted_5 -> Seq Scan on mcrparted5 mcrparted_6
Filter: (a > '-1'::integer) Filter: (a > '-1'::integer)
-> Seq Scan on mcrparted_def mcrparted_6 -> Seq Scan on mcrparted_def mcrparted_7
Filter: (a > '-1'::integer) Filter: (a > '-1'::integer)
(15 rows) (15 rows)
@ -2046,13 +2046,13 @@ explain (costs off) select * from mcrparted where a = 20 and c > 20; -- scans mc
QUERY PLAN QUERY PLAN
--------------------------------------------- ---------------------------------------------
Append Append
-> Seq Scan on mcrparted3 mcrparted -> Seq Scan on mcrparted3 mcrparted_1
Filter: ((c > 20) AND (a = 20)) Filter: ((c > 20) AND (a = 20))
-> Seq Scan on mcrparted4 mcrparted_1 -> Seq Scan on mcrparted4 mcrparted_2
Filter: ((c > 20) AND (a = 20)) Filter: ((c > 20) AND (a = 20))
-> Seq Scan on mcrparted5 mcrparted_2 -> Seq Scan on mcrparted5 mcrparted_3
Filter: ((c > 20) AND (a = 20)) Filter: ((c > 20) AND (a = 20))
-> Seq Scan on mcrparted_def mcrparted_3 -> Seq Scan on mcrparted_def mcrparted_4
Filter: ((c > 20) AND (a = 20)) Filter: ((c > 20) AND (a = 20))
(9 rows) (9 rows)
@ -2092,13 +2092,13 @@ explain (costs off) select * from mcrparted order by a, abs(b), c;
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Merge Append Merge Append
Sort Key: mcrparted.a, (abs(mcrparted.b)), mcrparted.c Sort Key: mcrparted.a, (abs(mcrparted.b)), mcrparted.c
-> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted -> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
-> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_1 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
-> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_2 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
-> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_3 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
-> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_4 -> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_5
-> Index Scan using mcrparted5_a_abs_c_idx on mcrparted5 mcrparted_5 -> Index Scan using mcrparted5_a_abs_c_idx on mcrparted5 mcrparted_6
-> Index Scan using mcrparted_def_a_abs_c_idx on mcrparted_def mcrparted_6 -> Index Scan using mcrparted_def_a_abs_c_idx on mcrparted_def mcrparted_7
(9 rows) (9 rows)
drop table mcrparted_def; drop table mcrparted_def;
@ -2108,12 +2108,12 @@ explain (costs off) select * from mcrparted order by a, abs(b), c;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------- -------------------------------------------------------------------------
Append Append
-> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted -> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
-> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_1 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
-> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_2 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
-> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_3 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
-> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_4 -> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_5
-> Index Scan using mcrparted5_a_abs_c_idx on mcrparted5 mcrparted_5 -> Index Scan using mcrparted5_a_abs_c_idx on mcrparted5 mcrparted_6
(7 rows) (7 rows)
-- Append is used with subpaths in reverse order with backwards index scans -- Append is used with subpaths in reverse order with backwards index scans
@ -2121,12 +2121,12 @@ explain (costs off) select * from mcrparted order by a desc, abs(b) desc, c desc
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
Append Append
-> Index Scan Backward using mcrparted5_a_abs_c_idx on mcrparted5 mcrparted_5 -> Index Scan Backward using mcrparted5_a_abs_c_idx on mcrparted5 mcrparted_6
-> Index Scan Backward using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_4 -> Index Scan Backward using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_5
-> Index Scan Backward using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_3 -> Index Scan Backward using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
-> Index Scan Backward using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_2 -> Index Scan Backward using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
-> Index Scan Backward using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_1 -> Index Scan Backward using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
-> Index Scan Backward using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted -> Index Scan Backward using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
(7 rows) (7 rows)
-- check that Append plan is used containing a MergeAppend for sub-partitions -- check that Append plan is used containing a MergeAppend for sub-partitions
@ -2139,15 +2139,15 @@ explain (costs off) select * from mcrparted order by a, abs(b), c;
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------
Append Append
-> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted -> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
-> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_1 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
-> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_2 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
-> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_3 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
-> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_4 -> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_5
-> Merge Append -> Merge Append
Sort Key: mcrparted_5.a, (abs(mcrparted_5.b)), mcrparted_5.c Sort Key: mcrparted_7.a, (abs(mcrparted_7.b)), mcrparted_7.c
-> Index Scan using mcrparted5a_a_abs_c_idx on mcrparted5a mcrparted_5 -> Index Scan using mcrparted5a_a_abs_c_idx on mcrparted5a mcrparted_7
-> Index Scan using mcrparted5_def_a_abs_c_idx on mcrparted5_def mcrparted_6 -> Index Scan using mcrparted5_def_a_abs_c_idx on mcrparted5_def mcrparted_8
(10 rows) (10 rows)
drop table mcrparted5_def; drop table mcrparted5_def;
@ -2158,12 +2158,12 @@ explain (costs off) select a, abs(b) from mcrparted order by a, abs(b), c;
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Append Append
-> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted -> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
-> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_1 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
-> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_2 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
-> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_3 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
-> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_4 -> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_5
-> Index Scan using mcrparted5a_a_abs_c_idx on mcrparted5a mcrparted_5 -> Index Scan using mcrparted5a_a_abs_c_idx on mcrparted5a mcrparted_6
(7 rows) (7 rows)
-- check that Append is used when the sub-partitioned tables are pruned -- check that Append is used when the sub-partitioned tables are pruned
@ -2172,13 +2172,13 @@ explain (costs off) select * from mcrparted where a < 20 order by a, abs(b), c;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------- -------------------------------------------------------------------------
Append Append
-> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted -> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
Index Cond: (a < 20) Index Cond: (a < 20)
-> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_1 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
Index Cond: (a < 20) Index Cond: (a < 20)
-> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_2 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
Index Cond: (a < 20) Index Cond: (a < 20)
-> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_3 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
Index Cond: (a < 20) Index Cond: (a < 20)
(9 rows) (9 rows)
@ -2191,8 +2191,8 @@ explain (costs off) select * from mclparted order by a;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------ ------------------------------------------------------------------------
Append Append
-> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted -> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
-> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_1 -> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
(3 rows) (3 rows)
-- Ensure a MergeAppend is used when a partition exists with interleaved -- Ensure a MergeAppend is used when a partition exists with interleaved
@ -2204,10 +2204,10 @@ explain (costs off) select * from mclparted order by a;
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
Merge Append Merge Append
Sort Key: mclparted.a Sort Key: mclparted.a
-> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted -> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
-> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_1 -> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
-> Index Only Scan using mclparted3_5_a_idx on mclparted3_5 mclparted_2 -> Index Only Scan using mclparted3_5_a_idx on mclparted3_5 mclparted_3
-> Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_3 -> Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_4
(6 rows) (6 rows)
drop table mclparted; drop table mclparted;
@ -2224,14 +2224,14 @@ explain (costs off) select * from mcrparted where a < 20 order by a, abs(b), c l
Limit Limit
-> Append -> Append
-> Sort -> Sort
Sort Key: mcrparted.a, (abs(mcrparted.b)), mcrparted.c Sort Key: mcrparted_1.a, (abs(mcrparted_1.b)), mcrparted_1.c
-> Seq Scan on mcrparted0 mcrparted -> Seq Scan on mcrparted0 mcrparted_1
Filter: (a < 20) Filter: (a < 20)
-> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_1 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
Index Cond: (a < 20) Index Cond: (a < 20)
-> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_2 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
Index Cond: (a < 20) Index Cond: (a < 20)
-> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_3 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
Index Cond: (a < 20) Index Cond: (a < 20)
(12 rows) (12 rows)
@ -2242,9 +2242,9 @@ explain (costs off) select * from mcrparted where a = 10 order by a, abs(b), c;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------- -------------------------------------------------------------------------
Append Append
-> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_1
Index Cond: (a = 10) Index Cond: (a = 10)
-> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_1 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_2
Index Cond: (a = 10) Index Cond: (a = 10)
(5 rows) (5 rows)
@ -2256,11 +2256,11 @@ create table bool_lp_true partition of bool_lp for values in(true);
create table bool_lp_false partition of bool_lp for values in(false); create table bool_lp_false partition of bool_lp for values in(false);
create index on bool_lp (b); create index on bool_lp (b);
explain (costs off) select * from bool_lp order by b; explain (costs off) select * from bool_lp order by b;
QUERY PLAN QUERY PLAN
-------------------------------------------------------------------------- ----------------------------------------------------------------------------
Append Append
-> Index Only Scan using bool_lp_false_b_idx on bool_lp_false bool_lp -> Index Only Scan using bool_lp_false_b_idx on bool_lp_false bool_lp_1
-> Index Only Scan using bool_lp_true_b_idx on bool_lp_true bool_lp_1 -> Index Only Scan using bool_lp_true_b_idx on bool_lp_true bool_lp_2
(3 rows) (3 rows)
drop table bool_lp; drop table bool_lp;
@ -2275,9 +2275,9 @@ explain (costs off) select * from bool_rp where b = true order by b,a;
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
Append Append
-> Index Only Scan using bool_rp_true_1k_b_a_idx on bool_rp_true_1k bool_rp -> Index Only Scan using bool_rp_true_1k_b_a_idx on bool_rp_true_1k bool_rp_1
Index Cond: (b = true) Index Cond: (b = true)
-> Index Only Scan using bool_rp_true_2k_b_a_idx on bool_rp_true_2k bool_rp_1 -> Index Only Scan using bool_rp_true_2k_b_a_idx on bool_rp_true_2k bool_rp_2
Index Cond: (b = true) Index Cond: (b = true)
(5 rows) (5 rows)
@ -2285,9 +2285,9 @@ explain (costs off) select * from bool_rp where b = false order by b,a;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------
Append Append
-> Index Only Scan using bool_rp_false_1k_b_a_idx on bool_rp_false_1k bool_rp -> Index Only Scan using bool_rp_false_1k_b_a_idx on bool_rp_false_1k bool_rp_1
Index Cond: (b = false) Index Cond: (b = false)
-> Index Only Scan using bool_rp_false_2k_b_a_idx on bool_rp_false_2k bool_rp_1 -> Index Only Scan using bool_rp_false_2k_b_a_idx on bool_rp_false_2k bool_rp_2
Index Cond: (b = false) Index Cond: (b = false)
(5 rows) (5 rows)
@ -2295,9 +2295,9 @@ explain (costs off) select * from bool_rp where b = true order by a;
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
Append Append
-> Index Only Scan using bool_rp_true_1k_b_a_idx on bool_rp_true_1k bool_rp -> Index Only Scan using bool_rp_true_1k_b_a_idx on bool_rp_true_1k bool_rp_1
Index Cond: (b = true) Index Cond: (b = true)
-> Index Only Scan using bool_rp_true_2k_b_a_idx on bool_rp_true_2k bool_rp_1 -> Index Only Scan using bool_rp_true_2k_b_a_idx on bool_rp_true_2k bool_rp_2
Index Cond: (b = true) Index Cond: (b = true)
(5 rows) (5 rows)
@ -2305,9 +2305,9 @@ explain (costs off) select * from bool_rp where b = false order by a;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------
Append Append
-> Index Only Scan using bool_rp_false_1k_b_a_idx on bool_rp_false_1k bool_rp -> Index Only Scan using bool_rp_false_1k_b_a_idx on bool_rp_false_1k bool_rp_1
Index Cond: (b = false) Index Cond: (b = false)
-> Index Only Scan using bool_rp_false_2k_b_a_idx on bool_rp_false_2k bool_rp_1 -> Index Only Scan using bool_rp_false_2k_b_a_idx on bool_rp_false_2k bool_rp_2
Index Cond: (b = false) Index Cond: (b = false)
(5 rows) (5 rows)
@ -2322,16 +2322,16 @@ explain (costs off) select * from range_parted order by a,b,c;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------
Append Append
-> Index Only Scan using range_parted1_a_b_c_idx on range_parted1 range_parted -> Index Only Scan using range_parted1_a_b_c_idx on range_parted1 range_parted_1
-> Index Only Scan using range_parted2_a_b_c_idx on range_parted2 range_parted_1 -> Index Only Scan using range_parted2_a_b_c_idx on range_parted2 range_parted_2
(3 rows) (3 rows)
explain (costs off) select * from range_parted order by a desc,b desc,c desc; explain (costs off) select * from range_parted order by a desc,b desc,c desc;
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------
Append Append
-> Index Only Scan Backward using range_parted2_a_b_c_idx on range_parted2 range_parted_1 -> Index Only Scan Backward using range_parted2_a_b_c_idx on range_parted2 range_parted_2
-> Index Only Scan Backward using range_parted1_a_b_c_idx on range_parted1 range_parted -> Index Only Scan Backward using range_parted1_a_b_c_idx on range_parted1 range_parted_1
(3 rows) (3 rows)
drop table range_parted; drop table range_parted;

View File

@ -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 (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 from join_pt1 t2 join join_ut1 t3 on t2.a = t3.b) ss
on t1.a = ss.t2a order by t1.a; on t1.a = ss.t2a order by t1.a;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------ --------------------------------------------------------------------
Sort Sort
Output: t1.b, (LEAST(t1.a, t2.a, t3.a)), t1.a Output: t1.b, (LEAST(t1.a, t2.a, t3.a)), t1.a
Sort Key: t1.a Sort Key: t1.a
@ -5796,12 +5796,12 @@ select t1.b, ss.phv from join_ut1 t1 left join lateral
-> Hash -> Hash
Output: t2.a Output: t2.a
-> Append -> Append
-> Seq Scan on public.join_pt1p1p1 t2 -> Seq Scan on public.join_pt1p1p1 t2_1
Output: t2.a
Filter: (t1.a = t2.a)
-> Seq Scan on public.join_pt1p2 t2_1
Output: t2_1.a Output: t2_1.a
Filter: (t1.a = 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) (21 rows)
select t1.b, ss.phv from join_ut1 t1 left join lateral select t1.b, ss.phv from join_ut1 t1 left join lateral

View File

@ -343,9 +343,9 @@ SELECT c, sum(a) FROM pagg_tab GROUP BY rollup(c) ORDER BY 1, 2;
Hash Key: pagg_tab.c Hash Key: pagg_tab.c
Group Key: () Group Key: ()
-> Append -> Append
-> Seq Scan on pagg_tab_p1 pagg_tab -> Seq Scan on pagg_tab_p1 pagg_tab_1
-> Seq Scan on pagg_tab_p2 pagg_tab_1 -> Seq Scan on pagg_tab_p2 pagg_tab_2
-> Seq Scan on pagg_tab_p3 pagg_tab_2 -> Seq Scan on pagg_tab_p3 pagg_tab_3
(9 rows) (9 rows)
-- ORDERED SET within the aggregate. -- ORDERED SET within the aggregate.
@ -390,9 +390,9 @@ SELECT a, sum(b order by a) FROM pagg_tab GROUP BY a ORDER BY 1, 2;
-> Sort -> Sort
Sort Key: pagg_tab.a Sort Key: pagg_tab.a
-> Append -> Append
-> Seq Scan on pagg_tab_p1 pagg_tab -> Seq Scan on pagg_tab_p1 pagg_tab_1
-> Seq Scan on pagg_tab_p2 pagg_tab_1 -> Seq Scan on pagg_tab_p2 pagg_tab_2
-> Seq Scan on pagg_tab_p3 pagg_tab_2 -> Seq Scan on pagg_tab_p3 pagg_tab_3
(10 rows) (10 rows)
-- JOIN query -- JOIN query
@ -461,14 +461,14 @@ SELECT t1.x, sum(t1.y), count(t1) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t
-> Hash Join -> Hash Join
Hash Cond: (t1.x = t2.y) Hash Cond: (t1.x = t2.y)
-> Append -> Append
-> Seq Scan on pagg_tab1_p1 t1 -> Seq Scan on pagg_tab1_p1 t1_1
-> Seq Scan on pagg_tab1_p2 t1_1 -> Seq Scan on pagg_tab1_p2 t1_2
-> Seq Scan on pagg_tab1_p3 t1_2 -> Seq Scan on pagg_tab1_p3 t1_3
-> Hash -> Hash
-> Append -> Append
-> Seq Scan on pagg_tab2_p1 t2 -> Seq Scan on pagg_tab2_p1 t2_1
-> Seq Scan on pagg_tab2_p2 t2_1 -> Seq Scan on pagg_tab2_p2 t2_2
-> Seq Scan on pagg_tab2_p3 t2_2 -> Seq Scan on pagg_tab2_p3 t2_3
(15 rows) (15 rows)
SELECT t1.x, sum(t1.y), count(t1) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2.y GROUP BY t1.x ORDER BY 1, 2, 3; SELECT t1.x, sum(t1.y), count(t1) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2.y GROUP BY t1.x ORDER BY 1, 2, 3;
@ -732,15 +732,15 @@ SELECT a.x, b.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x < 20) a LEFT JOI
Hash Cond: (pagg_tab1.x = pagg_tab2.y) Hash Cond: (pagg_tab1.x = pagg_tab2.y)
Filter: ((pagg_tab1.x > 5) OR (pagg_tab2.y < 20)) Filter: ((pagg_tab1.x > 5) OR (pagg_tab2.y < 20))
-> Append -> Append
-> Seq Scan on pagg_tab1_p1 pagg_tab1 -> Seq Scan on pagg_tab1_p1 pagg_tab1_1
Filter: (x < 20) Filter: (x < 20)
-> Seq Scan on pagg_tab1_p2 pagg_tab1_1 -> Seq Scan on pagg_tab1_p2 pagg_tab1_2
Filter: (x < 20) Filter: (x < 20)
-> Hash -> Hash
-> Append -> Append
-> Seq Scan on pagg_tab2_p2 pagg_tab2 -> Seq Scan on pagg_tab2_p2 pagg_tab2_1
Filter: (y > 10) Filter: (y > 10)
-> Seq Scan on pagg_tab2_p3 pagg_tab2_1 -> Seq Scan on pagg_tab2_p3 pagg_tab2_2
Filter: (y > 10) Filter: (y > 10)
(18 rows) (18 rows)
@ -772,15 +772,15 @@ SELECT a.x, b.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x < 20) a FULL JOI
Hash Cond: (pagg_tab1.x = pagg_tab2.y) Hash Cond: (pagg_tab1.x = pagg_tab2.y)
Filter: ((pagg_tab1.x > 5) OR (pagg_tab2.y < 20)) Filter: ((pagg_tab1.x > 5) OR (pagg_tab2.y < 20))
-> Append -> Append
-> Seq Scan on pagg_tab1_p1 pagg_tab1 -> Seq Scan on pagg_tab1_p1 pagg_tab1_1
Filter: (x < 20) Filter: (x < 20)
-> Seq Scan on pagg_tab1_p2 pagg_tab1_1 -> Seq Scan on pagg_tab1_p2 pagg_tab1_2
Filter: (x < 20) Filter: (x < 20)
-> Hash -> Hash
-> Append -> Append
-> Seq Scan on pagg_tab2_p2 pagg_tab2 -> Seq Scan on pagg_tab2_p2 pagg_tab2_1
Filter: (y > 10) Filter: (y > 10)
-> Seq Scan on pagg_tab2_p3 pagg_tab2_1 -> Seq Scan on pagg_tab2_p3 pagg_tab2_2
Filter: (y > 10) Filter: (y > 10)
(18 rows) (18 rows)
@ -946,26 +946,26 @@ SELECT a, sum(b), array_agg(distinct c), count(*) FROM pagg_tab_ml GROUP BY a HA
QUERY PLAN QUERY PLAN
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
Sort Sort
Sort Key: pagg_tab_ml_1.a, (sum(pagg_tab_ml_1.b)), (array_agg(DISTINCT pagg_tab_ml_1.c)) Sort Key: pagg_tab_ml_2.a, (sum(pagg_tab_ml_2.b)), (array_agg(DISTINCT pagg_tab_ml_2.c))
-> Gather -> Gather
Workers Planned: 2 Workers Planned: 2
-> Parallel Append -> Parallel Append
-> GroupAggregate -> GroupAggregate
Group Key: pagg_tab_ml_1.a Group Key: pagg_tab_ml_2.a
Filter: (avg(pagg_tab_ml_1.b) < '3'::numeric) Filter: (avg(pagg_tab_ml_2.b) < '3'::numeric)
-> Sort -> Sort
Sort Key: pagg_tab_ml_1.a Sort Key: pagg_tab_ml_2.a
-> Append -> Append
-> Seq Scan on pagg_tab_ml_p2_s1 pagg_tab_ml_1 -> Seq Scan on pagg_tab_ml_p2_s1 pagg_tab_ml_2
-> Seq Scan on pagg_tab_ml_p2_s2 pagg_tab_ml_2 -> Seq Scan on pagg_tab_ml_p2_s2 pagg_tab_ml_3
-> GroupAggregate -> GroupAggregate
Group Key: pagg_tab_ml_3.a Group Key: pagg_tab_ml_5.a
Filter: (avg(pagg_tab_ml_3.b) < '3'::numeric) Filter: (avg(pagg_tab_ml_5.b) < '3'::numeric)
-> Sort -> Sort
Sort Key: pagg_tab_ml_3.a Sort Key: pagg_tab_ml_5.a
-> Append -> Append
-> Seq Scan on pagg_tab_ml_p3_s1 pagg_tab_ml_3 -> Seq Scan on pagg_tab_ml_p3_s1 pagg_tab_ml_5
-> Seq Scan on pagg_tab_ml_p3_s2 pagg_tab_ml_4 -> Seq Scan on pagg_tab_ml_p3_s2 pagg_tab_ml_6
-> GroupAggregate -> GroupAggregate
Group Key: pagg_tab_ml.a Group Key: pagg_tab_ml.a
Filter: (avg(pagg_tab_ml.b) < '3'::numeric) Filter: (avg(pagg_tab_ml.b) < '3'::numeric)
@ -997,21 +997,21 @@ SELECT a, sum(b), array_agg(distinct c), count(*) FROM pagg_tab_ml GROUP BY a HA
Workers Planned: 2 Workers Planned: 2
-> Parallel Append -> Parallel Append
-> GroupAggregate -> GroupAggregate
Group Key: pagg_tab_ml_1.a Group Key: pagg_tab_ml_2.a
Filter: (avg(pagg_tab_ml_1.b) < '3'::numeric) Filter: (avg(pagg_tab_ml_2.b) < '3'::numeric)
-> Sort -> Sort
Sort Key: pagg_tab_ml_1.a Sort Key: pagg_tab_ml_2.a
-> Append -> Append
-> Seq Scan on pagg_tab_ml_p2_s1 pagg_tab_ml_1 -> Seq Scan on pagg_tab_ml_p2_s1 pagg_tab_ml_2
-> Seq Scan on pagg_tab_ml_p2_s2 pagg_tab_ml_2 -> Seq Scan on pagg_tab_ml_p2_s2 pagg_tab_ml_3
-> GroupAggregate -> GroupAggregate
Group Key: pagg_tab_ml_3.a Group Key: pagg_tab_ml_5.a
Filter: (avg(pagg_tab_ml_3.b) < '3'::numeric) Filter: (avg(pagg_tab_ml_5.b) < '3'::numeric)
-> Sort -> Sort
Sort Key: pagg_tab_ml_3.a Sort Key: pagg_tab_ml_5.a
-> Append -> Append
-> Seq Scan on pagg_tab_ml_p3_s1 pagg_tab_ml_3 -> Seq Scan on pagg_tab_ml_p3_s1 pagg_tab_ml_5
-> Seq Scan on pagg_tab_ml_p3_s2 pagg_tab_ml_4 -> Seq Scan on pagg_tab_ml_p3_s2 pagg_tab_ml_6
-> GroupAggregate -> GroupAggregate
Group Key: pagg_tab_ml.a Group Key: pagg_tab_ml.a
Filter: (avg(pagg_tab_ml.b) < '3'::numeric) Filter: (avg(pagg_tab_ml.b) < '3'::numeric)
@ -1035,29 +1035,29 @@ SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER B
Filter: (avg(pagg_tab_ml.b) < '3'::numeric) Filter: (avg(pagg_tab_ml.b) < '3'::numeric)
-> Seq Scan on pagg_tab_ml_p1 pagg_tab_ml -> Seq Scan on pagg_tab_ml_p1 pagg_tab_ml
-> Finalize GroupAggregate -> Finalize GroupAggregate
Group Key: pagg_tab_ml_1.a Group Key: pagg_tab_ml_2.a
Filter: (avg(pagg_tab_ml_1.b) < '3'::numeric) Filter: (avg(pagg_tab_ml_2.b) < '3'::numeric)
-> Sort -> Sort
Sort Key: pagg_tab_ml_1.a Sort Key: pagg_tab_ml_2.a
-> Append -> Append
-> Partial HashAggregate
Group Key: pagg_tab_ml_1.a
-> Seq Scan on pagg_tab_ml_p2_s1 pagg_tab_ml_1
-> Partial HashAggregate -> Partial HashAggregate
Group Key: pagg_tab_ml_2.a Group Key: pagg_tab_ml_2.a
-> Seq Scan on pagg_tab_ml_p2_s2 pagg_tab_ml_2 -> Seq Scan on pagg_tab_ml_p2_s1 pagg_tab_ml_2
-> Finalize GroupAggregate
Group Key: pagg_tab_ml_3.a
Filter: (avg(pagg_tab_ml_3.b) < '3'::numeric)
-> Sort
Sort Key: pagg_tab_ml_3.a
-> Append
-> Partial HashAggregate -> Partial HashAggregate
Group Key: pagg_tab_ml_3.a Group Key: pagg_tab_ml_3.a
-> Seq Scan on pagg_tab_ml_p3_s1 pagg_tab_ml_3 -> Seq Scan on pagg_tab_ml_p2_s2 pagg_tab_ml_3
-> Finalize GroupAggregate
Group Key: pagg_tab_ml_5.a
Filter: (avg(pagg_tab_ml_5.b) < '3'::numeric)
-> Sort
Sort Key: pagg_tab_ml_5.a
-> Append
-> Partial HashAggregate -> Partial HashAggregate
Group Key: pagg_tab_ml_4.a Group Key: pagg_tab_ml_5.a
-> Seq Scan on pagg_tab_ml_p3_s2 pagg_tab_ml_4 -> Seq Scan on pagg_tab_ml_p3_s1 pagg_tab_ml_5
-> Partial HashAggregate
Group Key: pagg_tab_ml_6.a
-> Seq Scan on pagg_tab_ml_p3_s2 pagg_tab_ml_6
(31 rows) (31 rows)
SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER BY 1, 2, 3; SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER BY 1, 2, 3;
@ -1185,33 +1185,33 @@ SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER B
Group Key: pagg_tab_ml.a Group Key: pagg_tab_ml.a
-> Parallel Seq Scan on pagg_tab_ml_p1 pagg_tab_ml -> Parallel Seq Scan on pagg_tab_ml_p1 pagg_tab_ml
-> Finalize GroupAggregate -> Finalize GroupAggregate
Group Key: pagg_tab_ml_1.a Group Key: pagg_tab_ml_2.a
Filter: (avg(pagg_tab_ml_1.b) < '3'::numeric) Filter: (avg(pagg_tab_ml_2.b) < '3'::numeric)
-> Gather Merge -> Gather Merge
Workers Planned: 2 Workers Planned: 2
-> Sort -> Sort
Sort Key: pagg_tab_ml_1.a Sort Key: pagg_tab_ml_2.a
-> Parallel Append -> Parallel Append
-> Partial HashAggregate
Group Key: pagg_tab_ml_1.a
-> Parallel Seq Scan on pagg_tab_ml_p2_s1 pagg_tab_ml_1
-> Partial HashAggregate -> Partial HashAggregate
Group Key: pagg_tab_ml_2.a Group Key: pagg_tab_ml_2.a
-> Parallel Seq Scan on pagg_tab_ml_p2_s2 pagg_tab_ml_2 -> Parallel Seq Scan on pagg_tab_ml_p2_s1 pagg_tab_ml_2
-> Partial HashAggregate
Group Key: pagg_tab_ml_3.a
-> Parallel Seq Scan on pagg_tab_ml_p2_s2 pagg_tab_ml_3
-> Finalize GroupAggregate -> Finalize GroupAggregate
Group Key: pagg_tab_ml_3.a Group Key: pagg_tab_ml_5.a
Filter: (avg(pagg_tab_ml_3.b) < '3'::numeric) Filter: (avg(pagg_tab_ml_5.b) < '3'::numeric)
-> Gather Merge -> Gather Merge
Workers Planned: 2 Workers Planned: 2
-> Sort -> Sort
Sort Key: pagg_tab_ml_3.a Sort Key: pagg_tab_ml_5.a
-> Parallel Append -> Parallel Append
-> Partial HashAggregate -> Partial HashAggregate
Group Key: pagg_tab_ml_3.a Group Key: pagg_tab_ml_5.a
-> Parallel Seq Scan on pagg_tab_ml_p3_s1 pagg_tab_ml_3 -> Parallel Seq Scan on pagg_tab_ml_p3_s1 pagg_tab_ml_5
-> Partial HashAggregate -> Partial HashAggregate
Group Key: pagg_tab_ml_4.a Group Key: pagg_tab_ml_6.a
-> Parallel Seq Scan on pagg_tab_ml_p3_s2 pagg_tab_ml_4 -> Parallel Seq Scan on pagg_tab_ml_p3_s2 pagg_tab_ml_6
(41 rows) (41 rows)
SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER BY 1, 2, 3; SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER BY 1, 2, 3;
@ -1426,9 +1426,9 @@ SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) <
-> Partial HashAggregate -> Partial HashAggregate
Group Key: pagg_tab_para.x Group Key: pagg_tab_para.x
-> Parallel Append -> Parallel Append
-> Seq Scan on pagg_tab_para_p1 pagg_tab_para -> Seq Scan on pagg_tab_para_p1 pagg_tab_para_1
-> Seq Scan on pagg_tab_para_p3 pagg_tab_para_2 -> Seq Scan on pagg_tab_para_p3 pagg_tab_para_3
-> Parallel Seq Scan on pagg_tab_para_p2 pagg_tab_para_1 -> Parallel Seq Scan on pagg_tab_para_p2 pagg_tab_para_2
(15 rows) (15 rows)
SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3; SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3;
@ -1460,9 +1460,9 @@ SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) <
-> Partial HashAggregate -> Partial HashAggregate
Group Key: pagg_tab_para.x Group Key: pagg_tab_para.x
-> Parallel Append -> Parallel Append
-> Seq Scan on pagg_tab_para_p1 pagg_tab_para -> Seq Scan on pagg_tab_para_p1 pagg_tab_para_1
-> Seq Scan on pagg_tab_para_p2 pagg_tab_para_1 -> Seq Scan on pagg_tab_para_p2 pagg_tab_para_2
-> Seq Scan on pagg_tab_para_p3 pagg_tab_para_2 -> Seq Scan on pagg_tab_para_p3 pagg_tab_para_3
(15 rows) (15 rows)
SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3; SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -662,11 +662,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1;
QUERY PLAN QUERY PLAN
------------------------------- -------------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
(7 rows) (7 rows)
@ -689,11 +689,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
QUERY PLAN QUERY PLAN
----------------------------------------------- -----------------------------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: (((a % 2) = 0) AND f_leak(b)) Filter: (((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: (((a % 2) = 0) AND f_leak(b)) Filter: (((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: (((a % 2) = 0) AND f_leak(b)) Filter: (((a % 2) = 0) AND f_leak(b))
(7 rows) (7 rows)
@ -712,11 +712,11 @@ EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1;
QUERY PLAN QUERY PLAN
------------------------------- -------------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
(7 rows) (7 rows)
@ -735,11 +735,11 @@ EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1;
QUERY PLAN QUERY PLAN
------------------------------- -------------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
(7 rows) (7 rows)
@ -759,11 +759,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 FOR SHARE;
------------------------------------- -------------------------------------
LockRows LockRows
-> Append -> Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
(8 rows) (8 rows)
@ -787,11 +787,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE;
----------------------------------------------------- -----------------------------------------------------
LockRows LockRows
-> Append -> Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: (((a % 2) = 0) AND f_leak(b)) Filter: (((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: (((a % 2) = 0) AND f_leak(b)) Filter: (((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: (((a % 2) = 0) AND f_leak(b)) Filter: (((a % 2) = 0) AND f_leak(b))
(8 rows) (8 rows)
@ -849,11 +849,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
QUERY PLAN QUERY PLAN
--------------------------- ---------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: f_leak(b) Filter: f_leak(b)
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: f_leak(b) Filter: f_leak(b)
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: f_leak(b) Filter: f_leak(b)
(7 rows) (7 rows)
@ -891,11 +891,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
QUERY PLAN QUERY PLAN
--------------------------- ---------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: f_leak(b) Filter: f_leak(b)
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: f_leak(b) Filter: f_leak(b)
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: f_leak(b) Filter: f_leak(b)
(7 rows) (7 rows)
@ -991,11 +991,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
InitPlan 1 (returns $0) InitPlan 1 (returns $0)
-> Index Scan using uaccount_pkey on uaccount -> Index Scan using uaccount_pkey on uaccount
Index Cond: (pguser = CURRENT_USER) Index Cond: (pguser = CURRENT_USER)
-> Seq Scan on part_document_fiction part_document -> Seq Scan on part_document_fiction part_document_1
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= $0) AND f_leak(dtitle))
-> Seq Scan on part_document_satire part_document_1 -> Seq Scan on part_document_satire part_document_2
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= $0) AND f_leak(dtitle))
-> Seq Scan on part_document_nonfiction part_document_2 -> Seq Scan on part_document_nonfiction part_document_3
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= $0) AND f_leak(dtitle))
(10 rows) (10 rows)
@ -1033,11 +1033,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
InitPlan 1 (returns $0) InitPlan 1 (returns $0)
-> Index Scan using uaccount_pkey on uaccount -> Index Scan using uaccount_pkey on uaccount
Index Cond: (pguser = CURRENT_USER) Index Cond: (pguser = CURRENT_USER)
-> Seq Scan on part_document_fiction part_document -> Seq Scan on part_document_fiction part_document_1
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= $0) AND f_leak(dtitle))
-> Seq Scan on part_document_satire part_document_1 -> Seq Scan on part_document_satire part_document_2
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= $0) AND f_leak(dtitle))
-> Seq Scan on part_document_nonfiction part_document_2 -> Seq Scan on part_document_nonfiction part_document_3
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= $0) AND f_leak(dtitle))
(10 rows) (10 rows)
@ -1180,11 +1180,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
InitPlan 1 (returns $0) InitPlan 1 (returns $0)
-> Index Scan using uaccount_pkey on uaccount -> Index Scan using uaccount_pkey on uaccount
Index Cond: (pguser = CURRENT_USER) Index Cond: (pguser = CURRENT_USER)
-> Seq Scan on part_document_fiction part_document -> Seq Scan on part_document_fiction part_document_1
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= $0) AND f_leak(dtitle))
-> Seq Scan on part_document_satire part_document_1 -> Seq Scan on part_document_satire part_document_2
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= $0) AND f_leak(dtitle))
-> Seq Scan on part_document_nonfiction part_document_2 -> Seq Scan on part_document_nonfiction part_document_3
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= $0) AND f_leak(dtitle))
(10 rows) (10 rows)
@ -1229,11 +1229,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
QUERY PLAN QUERY PLAN
--------------------------------------------------------------- ---------------------------------------------------------------
Append Append
-> Seq Scan on part_document_fiction part_document -> Seq Scan on part_document_fiction part_document_1
Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle)) Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle))
-> Seq Scan on part_document_satire part_document_1 -> Seq Scan on part_document_satire part_document_2
Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle)) Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle))
-> Seq Scan on part_document_nonfiction part_document_2 -> Seq Scan on part_document_nonfiction part_document_3
Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle)) Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle))
(7 rows) (7 rows)
@ -1509,11 +1509,11 @@ EXPLAIN (COSTS OFF) EXECUTE p1(2);
QUERY PLAN QUERY PLAN
---------------------------------------------- ----------------------------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: ((a <= 2) AND ((a % 2) = 0)) Filter: ((a <= 2) AND ((a % 2) = 0))
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: ((a <= 2) AND ((a % 2) = 0)) Filter: ((a <= 2) AND ((a % 2) = 0))
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: ((a <= 2) AND ((a % 2) = 0)) Filter: ((a <= 2) AND ((a % 2) = 0))
(7 rows) (7 rows)
@ -1551,11 +1551,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
QUERY PLAN QUERY PLAN
--------------------------- ---------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: f_leak(b) Filter: f_leak(b)
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: f_leak(b) Filter: f_leak(b)
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: f_leak(b) Filter: f_leak(b)
(7 rows) (7 rows)
@ -1575,11 +1575,11 @@ EXPLAIN (COSTS OFF) EXECUTE p1(2);
QUERY PLAN QUERY PLAN
--------------------------- ---------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: (a <= 2) Filter: (a <= 2)
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: (a <= 2) Filter: (a <= 2)
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: (a <= 2) Filter: (a <= 2)
(7 rows) (7 rows)
@ -1596,11 +1596,11 @@ EXPLAIN (COSTS OFF) EXECUTE p2(2);
QUERY PLAN QUERY PLAN
--------------------------- ---------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: (a = 2) Filter: (a = 2)
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: (a = 2) Filter: (a = 2)
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: (a = 2) Filter: (a = 2)
(7 rows) (7 rows)
@ -1619,11 +1619,11 @@ EXPLAIN (COSTS OFF) EXECUTE p2(2);
QUERY PLAN QUERY PLAN
--------------------------------------------- ---------------------------------------------
Append Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: ((a = 2) AND ((a % 2) = 0)) Filter: ((a = 2) AND ((a % 2) = 0))
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: ((a = 2) AND ((a % 2) = 0)) Filter: ((a = 2) AND ((a % 2) = 0))
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: ((a = 2) AND ((a % 2) = 0)) Filter: ((a = 2) AND ((a % 2) = 0))
(7 rows) (7 rows)
@ -1756,11 +1756,11 @@ WHERE t1.a = 3 and t2.a = 3 AND f_leak(t1.b) AND f_leak(t2.b);
-> Seq Scan on t2 -> Seq Scan on t2
Filter: ((a = 3) AND ((a % 2) = 1) AND f_leak(b)) Filter: ((a = 3) AND ((a % 2) = 1) AND f_leak(b))
-> Append -> Append
-> Seq Scan on t1 -> Seq Scan on t1 t1_1
Filter: ((a = 3) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 3) AND ((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t2 t1_1 -> Seq Scan on t2 t1_2
Filter: ((a = 3) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 3) AND ((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t3 t1_2 -> Seq Scan on t3 t1_3
Filter: ((a = 3) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 3) AND ((a % 2) = 0) AND f_leak(b))
(11 rows) (11 rows)
@ -1806,33 +1806,33 @@ AND f_leak(t1_1.b) AND f_leak(t1_2.b) RETURNING *, t1_1, t1_2;
-> Seq Scan on t1 t1_1 -> Seq Scan on t1 t1_1
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Append -> Append
-> Seq Scan on t1 t1_2 -> Seq Scan on t1 t1_2_1
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t2 t1_2_1 -> Seq Scan on t2 t1_2_2
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t3 t1_2_2 -> Seq Scan on t3 t1_2_3
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Nested Loop -> Nested Loop
Join Filter: (t1_1_1.b = t1_2.b) Join Filter: (t1_1_1.b = t1_2.b)
-> Seq Scan on t2 t1_1_1 -> Seq Scan on t2 t1_1_1
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Append -> Append
-> Seq Scan on t1 t1_2 -> Seq Scan on t1 t1_2_1
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t2 t1_2_1 -> Seq Scan on t2 t1_2_2
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t3 t1_2_2 -> Seq Scan on t3 t1_2_3
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Nested Loop -> Nested Loop
Join Filter: (t1_1_2.b = t1_2.b) Join Filter: (t1_1_2.b = t1_2.b)
-> Seq Scan on t3 t1_1_2 -> Seq Scan on t3 t1_1_2
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Append -> Append
-> Seq Scan on t1 t1_2 -> Seq Scan on t1 t1_2_1
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t2 t1_2_1 -> Seq Scan on t2 t1_2_2
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Seq Scan on t3 t1_2_2 -> Seq Scan on t3 t1_2_3
Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b))
(37 rows) (37 rows)

View File

@ -21,12 +21,12 @@ explain (costs off)
Workers Planned: 3 Workers Planned: 3
-> Partial Aggregate -> Partial Aggregate
-> Parallel Append -> Parallel Append
-> Parallel Seq Scan on d_star a_star_3 -> Parallel Seq Scan on d_star a_star_4
-> Parallel Seq Scan on f_star a_star_5 -> Parallel Seq Scan on f_star a_star_6
-> Parallel Seq Scan on e_star a_star_4 -> Parallel Seq Scan on e_star a_star_5
-> Parallel Seq Scan on b_star a_star_1 -> Parallel Seq Scan on b_star a_star_2
-> Parallel Seq Scan on c_star a_star_2 -> Parallel Seq Scan on c_star a_star_3
-> Parallel Seq Scan on a_star -> Parallel Seq Scan on a_star a_star_1
(11 rows) (11 rows)
select round(avg(aa)), sum(aa) from a_star a1; select round(avg(aa)), sum(aa) from a_star a1;
@ -47,12 +47,12 @@ explain (costs off)
Workers Planned: 3 Workers Planned: 3
-> Partial Aggregate -> Partial Aggregate
-> Parallel Append -> Parallel Append
-> Seq Scan on d_star a_star_3 -> Seq Scan on d_star a_star_4
-> Seq Scan on c_star a_star_2 -> Seq Scan on c_star a_star_3
-> Parallel Seq Scan on f_star a_star_5 -> Parallel Seq Scan on f_star a_star_6
-> Parallel Seq Scan on e_star a_star_4 -> Parallel Seq Scan on e_star a_star_5
-> Parallel Seq Scan on b_star a_star_1 -> Parallel Seq Scan on b_star a_star_2
-> Parallel Seq Scan on a_star -> Parallel Seq Scan on a_star a_star_1
(11 rows) (11 rows)
select round(avg(aa)), sum(aa) from a_star a2; select round(avg(aa)), sum(aa) from a_star a2;
@ -75,12 +75,12 @@ explain (costs off)
Workers Planned: 3 Workers Planned: 3
-> Partial Aggregate -> Partial Aggregate
-> Parallel Append -> Parallel Append
-> Seq Scan on d_star a_star_3 -> Seq Scan on d_star a_star_4
-> Seq Scan on f_star a_star_5 -> Seq Scan on f_star a_star_6
-> Seq Scan on e_star a_star_4 -> Seq Scan on e_star a_star_5
-> Seq Scan on b_star a_star_1 -> Seq Scan on b_star a_star_2
-> Seq Scan on c_star a_star_2 -> Seq Scan on c_star a_star_3
-> Seq Scan on a_star -> Seq Scan on a_star a_star_1
(11 rows) (11 rows)
select round(avg(aa)), sum(aa) from a_star a3; select round(avg(aa)), sum(aa) from a_star a3;
@ -106,12 +106,12 @@ explain (costs off)
Workers Planned: 1 Workers Planned: 1
-> Partial Aggregate -> Partial Aggregate
-> Append -> Append
-> Parallel Seq Scan on a_star -> Parallel Seq Scan on a_star a_star_1
-> Parallel Seq Scan on b_star a_star_1 -> Parallel Seq Scan on b_star a_star_2
-> Parallel Seq Scan on c_star a_star_2 -> Parallel Seq Scan on c_star a_star_3
-> Parallel Seq Scan on d_star a_star_3 -> Parallel Seq Scan on d_star a_star_4
-> Parallel Seq Scan on e_star a_star_4 -> Parallel Seq Scan on e_star a_star_5
-> Parallel Seq Scan on f_star a_star_5 -> Parallel Seq Scan on f_star a_star_6
(11 rows) (11 rows)
select round(avg(aa)), sum(aa) from a_star a4; select round(avg(aa)), sum(aa) from a_star a4;
@ -145,15 +145,15 @@ explain (costs off)
-> Gather -> Gather
Workers Planned: 3 Workers Planned: 3
-> Parallel Append -> Parallel Append
-> Parallel Seq Scan on part_pa_test_p1 pa2 -> Parallel Seq Scan on part_pa_test_p1 pa2_1
-> Parallel Seq Scan on part_pa_test_p2 pa2_1 -> Parallel Seq Scan on part_pa_test_p2 pa2_2
SubPlan 2 SubPlan 2
-> Result -> Result
SubPlan 1 SubPlan 1
-> Append -> Append
-> Seq Scan on part_pa_test_p1 pa1 -> Seq Scan on part_pa_test_p1 pa1_1
Filter: (a = pa2.a) 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) Filter: (a = pa2.a)
(14 rows) (14 rows)

View File

@ -198,13 +198,13 @@ explain (costs off)
------------------------------------------------- -------------------------------------------------
Aggregate Aggregate
-> Append -> Append
-> Sample Scan on person -> Sample Scan on person person_1
Sampling: bernoulli ('100'::real) Sampling: bernoulli ('100'::real)
-> Sample Scan on emp person_1 -> Sample Scan on emp person_2
Sampling: bernoulli ('100'::real) Sampling: bernoulli ('100'::real)
-> Sample Scan on student person_2 -> Sample Scan on student person_3
Sampling: bernoulli ('100'::real) Sampling: bernoulli ('100'::real)
-> Sample Scan on stud_emp person_3 -> Sample Scan on stud_emp person_4
Sampling: bernoulli ('100'::real) Sampling: bernoulli ('100'::real)
(10 rows) (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); create table parted_sample_2 partition of parted_sample for values in (2);
explain (costs off) explain (costs off)
select * from parted_sample tablesample bernoulli (100); select * from parted_sample tablesample bernoulli (100);
QUERY PLAN QUERY PLAN
------------------------------------------------------ -------------------------------------------
Append Append
-> Sample Scan on parted_sample_1 parted_sample -> Sample Scan on parted_sample_1
Sampling: bernoulli ('100'::real) Sampling: bernoulli ('100'::real)
-> Sample Scan on parted_sample_2 parted_sample_1 -> Sample Scan on parted_sample_2
Sampling: bernoulli ('100'::real) Sampling: bernoulli ('100'::real)
(5 rows) (5 rows)

View File

@ -1548,16 +1548,16 @@ INSERT INTO other_tbl_parent VALUES (7),(200);
INSERT INTO other_tbl_child VALUES (8),(100); INSERT INTO other_tbl_child VALUES (8),(100);
EXPLAIN (costs off) EXPLAIN (costs off)
UPDATE rw_view1 SET a = a + 1000 FROM other_tbl_parent WHERE a = id; 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_parent Update on base_tbl_parent
Update on base_tbl_child base_tbl_parent_1 Update on base_tbl_child base_tbl_parent_1
-> Hash Join -> Hash Join
Hash Cond: (other_tbl_parent.id = base_tbl_parent.a) Hash Cond: (other_tbl_parent.id = base_tbl_parent.a)
-> Append -> Append
-> Seq Scan on other_tbl_parent -> Seq Scan on other_tbl_parent other_tbl_parent_1
-> Seq Scan on other_tbl_child other_tbl_parent_1 -> Seq Scan on other_tbl_child other_tbl_parent_2
-> Hash -> Hash
-> Seq Scan on base_tbl_parent -> Seq Scan on base_tbl_parent
-> Merge Join -> Merge Join
@ -1568,8 +1568,8 @@ UPDATE rw_view1 SET a = a + 1000 FROM other_tbl_parent WHERE a = id;
-> Sort -> Sort
Sort Key: other_tbl_parent.id Sort Key: other_tbl_parent.id
-> Append -> Append
-> Seq Scan on other_tbl_parent -> Seq Scan on other_tbl_parent other_tbl_parent_1
-> Seq Scan on other_tbl_child other_tbl_parent_1 -> Seq Scan on other_tbl_child other_tbl_parent_2
(20 rows) (20 rows)
UPDATE rw_view1 SET a = a + 1000 FROM other_tbl_parent WHERE a = id; 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)) Filter: ((t1.a <> 6) AND (alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t1.a) AND leakproof(t1.a))
SubPlan 1 SubPlan 1
-> Append -> Append
-> Seq Scan on public.t12 -> Seq Scan on public.t12 t12_1
Filter: (t12.a = t1.a)
-> Seq Scan on public.t111 t12_1
Filter: (t12_1.a = t1.a) Filter: (t12_1.a = t1.a)
-> Seq Scan on public.t111 t12_2
Filter: (t12_2.a = t1.a)
SubPlan 2 SubPlan 2
-> Append -> Append
-> Seq Scan on public.t12 t12_2 -> Seq Scan on public.t12 t12_4
Output: t12_2.a Output: t12_4.a
-> Seq Scan on public.t111 t12_3 -> Seq Scan on public.t111 t12_5
Output: t12_3.a Output: t12_5.a
-> Index Scan using t11_a_idx on public.t11 t1_1 -> 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 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)) 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)) Filter: ((alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t1.a) AND leakproof(t1.a))
SubPlan 1 SubPlan 1
-> Append -> Append
-> Seq Scan on public.t12 -> Seq Scan on public.t12 t12_1
Filter: (t12.a = t1.a)
-> Seq Scan on public.t111 t12_1
Filter: (t12_1.a = t1.a) Filter: (t12_1.a = t1.a)
-> Seq Scan on public.t111 t12_2
Filter: (t12_2.a = t1.a)
SubPlan 2 SubPlan 2
-> Append -> Append
-> Seq Scan on public.t12 t12_2 -> Seq Scan on public.t12 t12_4
Output: t12_2.a Output: t12_4.a
-> Seq Scan on public.t111 t12_3 -> Seq Scan on public.t111 t12_5
Output: t12_3.a Output: t12_5.a
-> Index Scan using t11_a_idx on public.t11 t1_1 -> 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 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)) Index Cond: ((t1_1.a > 5) AND (t1_1.a = 8))