1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +03:00

Improve EXPLAIN's display of SubPlan nodes and output parameters.

Historically we've printed SubPlan expression nodes as "(SubPlan N)",
which is pretty uninformative.  Trying to reproduce the original SQL
for the subquery is still as impractical as before, and would be
mighty verbose as well.  However, we can still do better than that.
Displaying the "testexpr" when present, and adding a keyword to
indicate the SubLinkType, goes a long way toward showing what's
really going on.

In addition, this patch gets rid of EXPLAIN's use of "$n" to represent
subplan and initplan output Params.  Instead we now print "(SubPlan
N).colX" or "(InitPlan N).colX" to represent the X'th output column
of that subplan.  This eliminates confusion with the use of "$n" to
represent PARAM_EXTERN Params, and it's useful for the first part of
this change because it eliminates needing some other indication of
which subplan is referenced by a SubPlan that has a testexpr.

In passing, this adds simple regression test coverage of the
ROWCOMPARE_SUBLINK code paths, which were entirely unburdened
by testing before.

Tom Lane and Dean Rasheed, reviewed by Aleksander Alekseev.
Thanks to Chantal Keller for raising the question of whether
this area couldn't be improved.

Discussion: https://postgr.es/m/2838538.1705692747@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2024-03-19 18:19:24 -04:00
parent cc4826dd5e
commit fd0398fcb0
24 changed files with 793 additions and 464 deletions

View File

@ -3062,10 +3062,10 @@ select exists(select 1 from pg_enum), sum(c1) from ft1;
QUERY PLAN QUERY PLAN
-------------------------------------------------- --------------------------------------------------
Foreign Scan Foreign Scan
Output: $0, (sum(ft1.c1)) Output: (InitPlan 1).col1, (sum(ft1.c1))
Relations: Aggregate on (public.ft1) Relations: Aggregate on (public.ft1)
Remote SQL: SELECT sum("C 1") FROM "S 1"."T 1" Remote SQL: SELECT sum("C 1") FROM "S 1"."T 1"
InitPlan 1 (returns $0) InitPlan 1
-> Seq Scan on pg_catalog.pg_enum -> Seq Scan on pg_catalog.pg_enum
(6 rows) (6 rows)
@ -3080,8 +3080,8 @@ select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1;
QUERY PLAN QUERY PLAN
--------------------------------------------------- ---------------------------------------------------
GroupAggregate GroupAggregate
Output: $0, sum(ft1.c1) Output: (InitPlan 1).col1, sum(ft1.c1)
InitPlan 1 (returns $0) InitPlan 1
-> Seq Scan on pg_catalog.pg_enum -> Seq Scan on pg_catalog.pg_enum
-> Foreign Scan on public.ft1 -> Foreign Scan on public.ft1
Output: ft1.c1 Output: ft1.c1
@ -3306,9 +3306,9 @@ select sum(c1) filter (where (c1 / c1) * random() <= 1) from ft1 group by c2 ord
explain (verbose, costs off) explain (verbose, costs off)
select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1; select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------- -------------------------------------------------------------------------------
Aggregate Aggregate
Output: sum(ft1.c2) FILTER (WHERE (hashed SubPlan 1)) Output: sum(ft1.c2) FILTER (WHERE (ANY (ft1.c2 = (hashed SubPlan 1).col1)))
-> Foreign Scan on public.ft1 -> Foreign Scan on public.ft1
Output: ft1.c2 Output: ft1.c2
Remote SQL: SELECT c2 FROM "S 1"."T 1" Remote SQL: SELECT c2 FROM "S 1"."T 1"
@ -6171,9 +6171,9 @@ UPDATE ft2 AS target SET (c2, c7) = (
Update on public.ft2 target Update on public.ft2 target
Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c7 = $3 WHERE ctid = $1 Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c7 = $3 WHERE ctid = $1
-> Foreign Scan on public.ft2 target -> Foreign Scan on public.ft2 target
Output: $1, $2, (SubPlan 1 (returns $1,$2)), target.ctid, target.* Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), target.ctid, target.*
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 1100)) FOR UPDATE Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 1100)) FOR UPDATE
SubPlan 1 (returns $1,$2) SubPlan 1
-> Foreign Scan on public.ft2 src -> Foreign Scan on public.ft2 src
Output: (src.c2 * 10), src.c7 Output: (src.c2 * 10), src.c7
Remote SQL: SELECT c2, c7 FROM "S 1"."T 1" WHERE (($1::integer = "C 1")) Remote SQL: SELECT c2, c7 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
@ -11685,9 +11685,9 @@ SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt W
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------
Nested Loop Left Join Nested Loop Left Join
Output: t1.a, t1.b, t1.c, async_pt.a, async_pt.b, async_pt.c, ($0) Output: t1.a, t1.b, t1.c, async_pt.a, async_pt.b, async_pt.c, ((InitPlan 1).col1)
Join Filter: (t1.a = async_pt.a) Join Filter: (t1.a = async_pt.a)
InitPlan 1 (returns $0) InitPlan 1
-> Aggregate -> Aggregate
Output: count(*) Output: count(*)
-> Append -> Append
@ -11699,10 +11699,10 @@ SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt W
Output: t1.a, t1.b, t1.c Output: t1.a, t1.b, t1.c
-> Append -> Append
-> Async Foreign Scan on public.async_p1 async_pt_1 -> Async Foreign Scan on public.async_p1 async_pt_1
Output: async_pt_1.a, async_pt_1.b, async_pt_1.c, $0 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c, (InitPlan 1).col1
Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < 3000)) Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < 3000))
-> Async Foreign Scan on public.async_p2 async_pt_2 -> Async Foreign Scan on public.async_p2 async_pt_2
Output: async_pt_2.a, async_pt_2.b, async_pt_2.c, $0 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c, (InitPlan 1).col1
Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a < 3000)) Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a < 3000))
(20 rows) (20 rows)
@ -11713,7 +11713,7 @@ SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt W
Nested Loop Left Join (actual rows=1 loops=1) Nested Loop Left Join (actual rows=1 loops=1)
Join Filter: (t1.a = async_pt.a) Join Filter: (t1.a = async_pt.a)
Rows Removed by Join Filter: 399 Rows Removed by Join Filter: 399
InitPlan 1 (returns $0) InitPlan 1
-> Aggregate (actual rows=1 loops=1) -> Aggregate (actual rows=1 loops=1)
-> Append (actual rows=400 loops=1) -> Append (actual rows=400 loops=1)
-> Async Foreign Scan on async_p1 async_pt_4 (actual rows=200 loops=1) -> Async Foreign Scan on async_p1 async_pt_4 (actual rows=200 loops=1)
@ -11937,10 +11937,10 @@ CREATE FOREIGN TABLE foreign_tbl2 () INHERITS (foreign_tbl)
EXPLAIN (VERBOSE, COSTS OFF) EXPLAIN (VERBOSE, COSTS OFF)
SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl); SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl);
QUERY PLAN QUERY PLAN
----------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------
Seq Scan on public.base_tbl Seq Scan on public.base_tbl
Output: base_tbl.a Output: base_tbl.a
Filter: (SubPlan 1) Filter: (ANY ((base_tbl.a = (SubPlan 1).col1) AND ((random() > '0'::double precision) = (SubPlan 1).col2)))
SubPlan 1 SubPlan 1
-> Result -> Result
Output: base_tbl.a, (random() > '0'::double precision) Output: base_tbl.a, (random() > '0'::double precision)

View File

@ -573,8 +573,106 @@ WHERE t1.unique1 &lt; 100 AND t1.unique2 = t2.unique2;
which shows that the planner thinks that sorting <literal>onek</literal> by which shows that the planner thinks that sorting <literal>onek</literal> by
index-scanning is about 12% more expensive than sequential-scan-and-sort. index-scanning is about 12% more expensive than sequential-scan-and-sort.
Of course, the next question is whether it's right about that. Of course, the next question is whether it's right about that.
We can investigate that using <command>EXPLAIN ANALYZE</command>, as discussed We can investigate that using <command>EXPLAIN ANALYZE</command>, as
below. discussed <link linkend="using-explain-analyze">below</link>.
</para>
<para>
<indexterm>
<primary>subplan</primary>
</indexterm>
Some query plans involve <firstterm>subplans</firstterm>, which arise
from sub-<literal>SELECT</literal>s in the original query. Such
queries can sometimes be transformed into ordinary join plans, but
when they cannot be, we get plans like:
<screen>
EXPLAIN VERBOSE SELECT unique1
FROM tenk1 t
WHERE t.ten &lt; ALL (SELECT o.ten FROM onek o WHERE o.four = t.four);
QUERY PLAN
-------------------------------------------------------------------&zwsp;------
Seq Scan on public.tenk1 t (cost=0.00..586095.00 rows=5000 width=4)
Output: t.unique1
Filter: (ALL (t.ten &lt; (SubPlan 1).col1))
SubPlan 1
-&gt; Seq Scan on public.onek o (cost=0.00..116.50 rows=250 width=4)
Output: o.ten
Filter: (o.four = t.four)
</screen>
This rather artificial example serves to illustrate a couple of
points: values from the outer plan level can be passed down into a
subplan (here, <literal>t.four</literal> is passed down) and the
results of the sub-select are available to the outer plan. Those
result values are shown by <command>EXPLAIN</command> with notations
like
<literal>(<replaceable>subplan_name</replaceable>).col<replaceable>N</replaceable></literal>,
which refers to the <replaceable>N</replaceable>'th output column of
the sub-<literal>SELECT</literal>.
</para>
<para>
<indexterm>
<primary>subplan</primary>
<secondary>hashed</secondary>
</indexterm>
In the example above, the <literal>ALL</literal> operator runs the
subplan again for each row of the outer query (which accounts for the
high estimated cost). Some queries can use a <firstterm>hashed
subplan</firstterm> to avoid that:
<screen>
EXPLAIN SELECT *
FROM tenk1 t
WHERE t.unique1 NOT IN (SELECT o.unique1 FROM onek o);
QUERY PLAN
-------------------------------------------------------------------&zwsp;-------------------------
Seq Scan on tenk1 t (cost=61.77..531.77 rows=5000 width=244)
Filter: (NOT (ANY (unique1 = (hashed SubPlan 1).col1)))
SubPlan 1
-&gt; Index Only Scan using onek_unique1 on onek o (cost=0.28..59.27 rows=1000 width=4)
(4 rows)
</screen>
Here, the subplan is run a single time and its output is loaded into
an in-memory hash table, which is then probed by the
outer <literal>ANY</literal> operator. This requires that the
sub-<literal>SELECT</literal> not reference any variables of the outer
query, and that the <literal>ANY</literal>'s comparison operator be
amenable to hashing.
</para>
<para>
<indexterm>
<primary>initplan</primary>
</indexterm>
If, in addition to not referencing any variables of the outer query,
the sub-<literal>SELECT</literal> cannot return more than one row,
it may instead be implemented as an <firstterm>initplan</firstterm>:
<screen>
EXPLAIN VERBOSE SELECT unique1
FROM tenk1 t1 WHERE t1.ten = (SELECT (random() * 10)::integer);
QUERY PLAN
------------------------------------------------------------&zwsp;--------
Seq Scan on public.tenk1 t1 (cost=0.02..470.02 rows=1000 width=4)
Output: t1.unique1
Filter: (t1.ten = (InitPlan 1).col1)
InitPlan 1
-&gt; Result (cost=0.00..0.02 rows=1 width=4)
Output: ((random() * '10'::double precision))::integer
</screen>
An initplan is run only once per execution of the outer plan, and its
results are saved for re-use in later rows of the outer plan. So in
this example <literal>random()</literal> is evaluated only once and
all the values of <literal>t1.ten</literal> are compared to the same
randomly-chosen integer. That's quite different from what would
happen without the sub-<literal>SELECT</literal> construct.
</para> </para>
</sect2> </sect2>

View File

@ -116,7 +116,6 @@ static void show_tidbitmap_info(BitmapHeapScanState *planstate,
static void show_instrumentation_count(const char *qlabel, int which, static void show_instrumentation_count(const char *qlabel, int which,
PlanState *planstate, ExplainState *es); PlanState *planstate, ExplainState *es);
static void show_foreignscan_info(ForeignScanState *fsstate, ExplainState *es); static void show_foreignscan_info(ForeignScanState *fsstate, ExplainState *es);
static void show_eval_params(Bitmapset *bms_params, ExplainState *es);
static const char *explain_get_index_name(Oid indexId); static const char *explain_get_index_name(Oid indexId);
static bool peek_buffer_usage(ExplainState *es, const BufferUsage *usage); static bool peek_buffer_usage(ExplainState *es, const BufferUsage *usage);
static void show_buffer_usage(ExplainState *es, const BufferUsage *usage); static void show_buffer_usage(ExplainState *es, const BufferUsage *usage);
@ -1914,10 +1913,6 @@ ExplainNode(PlanState *planstate, List *ancestors,
ExplainPropertyInteger("Workers Planned", NULL, ExplainPropertyInteger("Workers Planned", NULL,
gather->num_workers, es); gather->num_workers, es);
/* Show params evaluated at gather node */
if (gather->initParam)
show_eval_params(gather->initParam, es);
if (es->analyze) if (es->analyze)
{ {
int nworkers; int nworkers;
@ -1942,10 +1937,6 @@ ExplainNode(PlanState *planstate, List *ancestors,
ExplainPropertyInteger("Workers Planned", NULL, ExplainPropertyInteger("Workers Planned", NULL,
gm->num_workers, es); gm->num_workers, es);
/* Show params evaluated at gather-merge node */
if (gm->initParam)
show_eval_params(gm->initParam, es);
if (es->analyze) if (es->analyze)
{ {
int nworkers; int nworkers;
@ -3550,29 +3541,6 @@ show_foreignscan_info(ForeignScanState *fsstate, ExplainState *es)
} }
} }
/*
* Show initplan params evaluated at Gather or Gather Merge node.
*/
static void
show_eval_params(Bitmapset *bms_params, ExplainState *es)
{
int paramid = -1;
List *params = NIL;
Assert(bms_params);
while ((paramid = bms_next_member(bms_params, paramid)) >= 0)
{
char param[32];
snprintf(param, sizeof(param), "$%d", paramid);
params = lappend(params, pstrdup(param));
}
if (params)
ExplainPropertyList("Params Evaluated", params, es);
}
/* /*
* Fetch the name of an index in an EXPLAIN * Fetch the name of an index in an EXPLAIN
* *

View File

@ -560,22 +560,9 @@ build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
splan->plan_id); splan->plan_id);
/* Label the subplan for EXPLAIN purposes */ /* Label the subplan for EXPLAIN purposes */
splan->plan_name = palloc(32 + 12 * list_length(splan->setParam)); splan->plan_name = psprintf("%s %d",
sprintf(splan->plan_name, "%s %d",
isInitPlan ? "InitPlan" : "SubPlan", isInitPlan ? "InitPlan" : "SubPlan",
splan->plan_id); splan->plan_id);
if (splan->setParam)
{
char *ptr = splan->plan_name + strlen(splan->plan_name);
ptr += sprintf(ptr, " (returns ");
foreach(lc, splan->setParam)
{
ptr += sprintf(ptr, "$%d%s",
lfirst_int(lc),
lnext(splan->setParam, lc) ? "," : ")");
}
}
/* Lastly, fill in the cost estimates for use later */ /* Lastly, fill in the cost estimates for use later */
cost_subplan(root, splan, plan); cost_subplan(root, splan, plan);
@ -3047,8 +3034,7 @@ SS_make_initplan_from_plan(PlannerInfo *root,
node = makeNode(SubPlan); node = makeNode(SubPlan);
node->subLinkType = EXPR_SUBLINK; node->subLinkType = EXPR_SUBLINK;
node->plan_id = list_length(root->glob->subplans); node->plan_id = list_length(root->glob->subplans);
node->plan_name = psprintf("InitPlan %d (returns $%d)", node->plan_name = psprintf("InitPlan %d", node->plan_id);
node->plan_id, prm->paramid);
get_first_col_type(plan, &node->firstColType, &node->firstColTypmod, get_first_col_type(plan, &node->firstColType, &node->firstColTypmod,
&node->firstColCollation); &node->firstColCollation);
node->parallel_safe = plan->parallel_safe; node->parallel_safe = plan->parallel_safe;

View File

@ -437,6 +437,10 @@ static void resolve_special_varno(Node *node, deparse_context *context,
rsv_callback callback, void *callback_arg); rsv_callback callback, void *callback_arg);
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 SubPlan *find_param_generator(Param *param, deparse_context *context,
int *column_p);
static SubPlan *find_param_generator_initplan(Param *param, Plan *plan,
int *column_p);
static void get_parameter(Param *param, deparse_context *context); static void get_parameter(Param *param, deparse_context *context);
static const char *get_simple_binary_op_name(OpExpr *expr); static const char *get_simple_binary_op_name(OpExpr *expr);
static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags); static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
@ -8134,6 +8138,128 @@ find_param_referent(Param *param, deparse_context *context,
return NULL; return NULL;
} }
/*
* Try to find a subplan/initplan that emits the value for a PARAM_EXEC Param.
*
* If successful, return the generating subplan/initplan and set *column_p
* to the subplan's 0-based output column number.
* Otherwise, return NULL.
*/
static SubPlan *
find_param_generator(Param *param, deparse_context *context, int *column_p)
{
/* Initialize output parameter to prevent compiler warnings */
*column_p = 0;
/*
* If it's a PARAM_EXEC parameter, search the current plan node as well as
* ancestor nodes looking for a subplan or initplan that emits the value
* for the Param. It could appear in the setParams of an initplan or
* MULTIEXPR_SUBLINK subplan, or in the paramIds of an ancestral SubPlan.
*/
if (param->paramkind == PARAM_EXEC)
{
SubPlan *result;
deparse_namespace *dpns;
ListCell *lc;
dpns = (deparse_namespace *) linitial(context->namespaces);
/* First check the innermost plan node's initplans */
result = find_param_generator_initplan(param, dpns->plan, column_p);
if (result)
return result;
/*
* The plan's targetlist might contain MULTIEXPR_SUBLINK SubPlans,
* which can be referenced by Params elsewhere in the targetlist.
* (Such Params should always be in the same targetlist, so there's no
* need to do this work at upper plan nodes.)
*/
foreach_node(TargetEntry, tle, dpns->plan->targetlist)
{
if (tle->expr && IsA(tle->expr, SubPlan))
{
SubPlan *subplan = (SubPlan *) tle->expr;
if (subplan->subLinkType == MULTIEXPR_SUBLINK)
{
foreach_int(paramid, subplan->setParam)
{
if (paramid == param->paramid)
{
/* Found a match, so return it. */
*column_p = foreach_current_index(paramid);
return subplan;
}
}
}
}
}
/* No luck, so check the ancestor nodes */
foreach(lc, dpns->ancestors)
{
Node *ancestor = (Node *) lfirst(lc);
/*
* If ancestor is a SubPlan, check the paramIds it provides.
*/
if (IsA(ancestor, SubPlan))
{
SubPlan *subplan = (SubPlan *) ancestor;
foreach_int(paramid, subplan->paramIds)
{
if (paramid == param->paramid)
{
/* Found a match, so return it. */
*column_p = foreach_current_index(paramid);
return subplan;
}
}
/* SubPlan isn't a kind of Plan, so skip the rest */
continue;
}
/*
* Otherwise, it's some kind of Plan node, so check its initplans.
*/
result = find_param_generator_initplan(param, (Plan *) ancestor,
column_p);
if (result)
return result;
/* No luck, crawl up to next ancestor */
}
}
/* No generator found */
return NULL;
}
/*
* Subroutine for find_param_generator: search one Plan node's initplans
*/
static SubPlan *
find_param_generator_initplan(Param *param, Plan *plan, int *column_p)
{
foreach_node(SubPlan, subplan, plan->initPlan)
{
foreach_int(paramid, subplan->setParam)
{
if (paramid == param->paramid)
{
/* Found a match, so return it. */
*column_p = foreach_current_index(paramid);
return subplan;
}
}
}
return NULL;
}
/* /*
* Display a Param appropriately. * Display a Param appropriately.
*/ */
@ -8143,12 +8269,13 @@ get_parameter(Param *param, deparse_context *context)
Node *expr; Node *expr;
deparse_namespace *dpns; deparse_namespace *dpns;
ListCell *ancestor_cell; ListCell *ancestor_cell;
SubPlan *subplan;
int column;
/* /*
* If it's a PARAM_EXEC parameter, try to locate the expression from which * If it's a PARAM_EXEC parameter, try to locate the expression from which
* the parameter was computed. Note that failing to find a referent isn't * the parameter was computed. This stanza handles only cases in which
* an error, since the Param might well be a subplan output rather than an * the Param represents an input to the subplan we are currently in.
* input.
*/ */
expr = find_param_referent(param, context, &dpns, &ancestor_cell); expr = find_param_referent(param, context, &dpns, &ancestor_cell);
if (expr) if (expr)
@ -8192,6 +8319,24 @@ get_parameter(Param *param, deparse_context *context)
return; return;
} }
/*
* Alternatively, maybe it's a subplan output, which we print as a
* reference to the subplan. (We could drill down into the subplan and
* print the relevant targetlist expression, but that has been deemed too
* confusing since it would violate normal SQL scope rules. Also, we're
* relying on this reference to show that the testexpr containing the
* Param has anything to do with that subplan at all.)
*/
subplan = find_param_generator(param, context, &column);
if (subplan)
{
appendStringInfo(context->buf, "(%s%s).col%d",
subplan->useHashTable ? "hashed " : "",
subplan->plan_name, column + 1);
return;
}
/* /*
* If it's an external parameter, see if the outermost namespace provides * If it's an external parameter, see if the outermost namespace provides
* function argument names. * function argument names.
@ -8240,7 +8385,12 @@ get_parameter(Param *param, deparse_context *context)
/* /*
* Not PARAM_EXEC, or couldn't find referent: just print $N. * Not PARAM_EXEC, or couldn't find referent: just print $N.
*
* It's a bug if we get here for anything except PARAM_EXTERN Params, but
* in production builds printing $N seems more useful than failing.
*/ */
Assert(param->paramkind == PARAM_EXTERN);
appendStringInfo(context->buf, "$%d", param->paramid); appendStringInfo(context->buf, "$%d", param->paramid);
} }
@ -8881,12 +9031,79 @@ get_rule_expr(Node *node, deparse_context *context,
* We cannot see an already-planned subplan in rule deparsing, * We cannot see an already-planned subplan in rule deparsing,
* only while EXPLAINing a query plan. We don't try to * only while EXPLAINing a query plan. We don't try to
* reconstruct the original SQL, just reference the subplan * reconstruct the original SQL, just reference the subplan
* that appears elsewhere in EXPLAIN's result. * that appears elsewhere in EXPLAIN's result. It does seem
* useful to show the subLinkType and testexpr (if any), and
* we also note whether the subplan will be hashed.
*/ */
if (subplan->useHashTable) switch (subplan->subLinkType)
appendStringInfo(buf, "(hashed %s)", subplan->plan_name); {
case EXISTS_SUBLINK:
appendStringInfoString(buf, "EXISTS(");
Assert(subplan->testexpr == NULL);
break;
case ALL_SUBLINK:
appendStringInfoString(buf, "(ALL ");
Assert(subplan->testexpr != NULL);
break;
case ANY_SUBLINK:
appendStringInfoString(buf, "(ANY ");
Assert(subplan->testexpr != NULL);
break;
case ROWCOMPARE_SUBLINK:
/* Parenthesizing the testexpr seems sufficient */
appendStringInfoChar(buf, '(');
Assert(subplan->testexpr != NULL);
break;
case EXPR_SUBLINK:
/* No need to decorate these subplan references */
appendStringInfoChar(buf, '(');
Assert(subplan->testexpr == NULL);
break;
case MULTIEXPR_SUBLINK:
/* MULTIEXPR isn't executed in the normal way */
appendStringInfoString(buf, "(rescan ");
Assert(subplan->testexpr == NULL);
break;
case ARRAY_SUBLINK:
appendStringInfoString(buf, "ARRAY(");
Assert(subplan->testexpr == NULL);
break;
case CTE_SUBLINK:
/* This case is unreachable within expressions */
appendStringInfoString(buf, "CTE(");
Assert(subplan->testexpr == NULL);
break;
}
if (subplan->testexpr != NULL)
{
deparse_namespace *dpns;
/*
* Push SubPlan into ancestors list while deparsing
* testexpr, so that we can handle PARAM_EXEC references
* to the SubPlan's paramIds. (This makes it look like
* the SubPlan is an "ancestor" of the current plan node,
* which is a little weird, but it does no harm.) In this
* path, we don't need to mention the SubPlan explicitly,
* because the referencing Params will show its existence.
*/
dpns = (deparse_namespace *) linitial(context->namespaces);
dpns->ancestors = lcons(subplan, dpns->ancestors);
get_rule_expr(subplan->testexpr, context, showimplicit);
appendStringInfoChar(buf, ')');
dpns->ancestors = list_delete_first(dpns->ancestors);
}
else else
appendStringInfo(buf, "(%s)", subplan->plan_name); {
/* No referencing Params, so show the SubPlan's name */
if (subplan->useHashTable)
appendStringInfo(buf, "hashed %s)", subplan->plan_name);
else
appendStringInfo(buf, "%s)", subplan->plan_name);
}
} }
break; break;

View File

@ -738,7 +738,7 @@ select array(select sum(x+y) s
QUERY PLAN QUERY PLAN
------------------------------------------------------------------- -------------------------------------------------------------------
Function Scan on pg_catalog.generate_series x Function Scan on pg_catalog.generate_series x
Output: (SubPlan 1) Output: ARRAY(SubPlan 1)
Function Call: generate_series(1, 3) Function Call: generate_series(1, 3)
SubPlan 1 SubPlan 1
-> Sort -> Sort
@ -915,7 +915,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
------------------------------------------------------------ ------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan using tenk1_unique1 on tenk1 -> Index Only Scan using tenk1_unique1 on tenk1
Index Cond: (unique1 IS NOT NULL) Index Cond: (unique1 IS NOT NULL)
@ -932,7 +932,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------- ---------------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan Backward using tenk1_unique1 on tenk1 -> Index Only Scan Backward using tenk1_unique1 on tenk1
Index Cond: (unique1 IS NOT NULL) Index Cond: (unique1 IS NOT NULL)
@ -949,7 +949,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------ ------------------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan Backward using tenk1_unique1 on tenk1 -> Index Only Scan Backward using tenk1_unique1 on tenk1
Index Cond: ((unique1 IS NOT NULL) AND (unique1 < 42)) Index Cond: ((unique1 IS NOT NULL) AND (unique1 < 42))
@ -966,7 +966,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------ ------------------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan Backward using tenk1_unique1 on tenk1 -> Index Only Scan Backward using tenk1_unique1 on tenk1
Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42)) Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42))
@ -989,7 +989,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan Backward using tenk1_unique1 on tenk1 -> Index Only Scan Backward using tenk1_unique1 on tenk1
Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42000)) Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42000))
@ -1008,7 +1008,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan Backward using tenk1_thous_tenthous on tenk1 -> Index Only Scan Backward using tenk1_thous_tenthous on tenk1
Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL)) Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL))
@ -1025,7 +1025,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
-------------------------------------------------------------------------- --------------------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan using tenk1_thous_tenthous on tenk1 -> Index Only Scan using tenk1_thous_tenthous on tenk1
Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL)) Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL))
@ -1046,7 +1046,7 @@ explain (costs off)
Seq Scan on int4_tbl Seq Scan on int4_tbl
SubPlan 2 SubPlan 2
-> Result -> Result
InitPlan 1 (returns $1) InitPlan 1
-> Limit -> Limit
-> Index Only Scan using tenk1_unique1 on tenk1 -> Index Only Scan using tenk1_unique1 on tenk1
Index Cond: ((unique1 IS NOT NULL) AND (unique1 > int4_tbl.f1)) Index Cond: ((unique1 IS NOT NULL) AND (unique1 > int4_tbl.f1))
@ -1069,8 +1069,8 @@ explain (costs off)
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------- ---------------------------------------------------------------------
HashAggregate HashAggregate
Group Key: $0 Group Key: (InitPlan 1).col1
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan Backward using tenk1_unique2 on tenk1 -> Index Only Scan Backward using tenk1_unique2 on tenk1
Index Cond: (unique2 IS NOT NULL) Index Cond: (unique2 IS NOT NULL)
@ -1088,8 +1088,8 @@ explain (costs off)
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------- ---------------------------------------------------------------------
Sort Sort
Sort Key: ($0) Sort Key: ((InitPlan 1).col1)
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan Backward using tenk1_unique2 on tenk1 -> Index Only Scan Backward using tenk1_unique2 on tenk1
Index Cond: (unique2 IS NOT NULL) Index Cond: (unique2 IS NOT NULL)
@ -1107,8 +1107,8 @@ explain (costs off)
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------- ---------------------------------------------------------------------
Sort Sort
Sort Key: ($0) Sort Key: ((InitPlan 1).col1)
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan Backward using tenk1_unique2 on tenk1 -> Index Only Scan Backward using tenk1_unique2 on tenk1
Index Cond: (unique2 IS NOT NULL) Index Cond: (unique2 IS NOT NULL)
@ -1126,8 +1126,8 @@ explain (costs off)
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------- ---------------------------------------------------------------------
Sort Sort
Sort Key: (($0 + 1)) Sort Key: (((InitPlan 1).col1 + 1))
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan Backward using tenk1_unique2 on tenk1 -> Index Only Scan Backward using tenk1_unique2 on tenk1
Index Cond: (unique2 IS NOT NULL) Index Cond: (unique2 IS NOT NULL)
@ -1146,7 +1146,7 @@ explain (costs off)
--------------------------------------------------------------------- ---------------------------------------------------------------------
Sort Sort
Sort Key: (generate_series(1, 3)) DESC Sort Key: (generate_series(1, 3)) DESC
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan Backward using tenk1_unique2 on tenk1 -> Index Only Scan Backward using tenk1_unique2 on tenk1
Index Cond: (unique2 IS NOT NULL) Index Cond: (unique2 IS NOT NULL)
@ -1168,7 +1168,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
---------------------------------------------------- ----------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Result -> Result
One-Time Filter: (100 IS NOT NULL) One-Time Filter: (100 IS NOT NULL)
@ -1199,7 +1199,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Merge Append -> Merge Append
Sort Key: minmaxtest.f1 Sort Key: minmaxtest.f1
@ -1210,7 +1210,7 @@ explain (costs off)
-> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3 -> 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_4 -> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4
InitPlan 2 (returns $1) InitPlan 2
-> Limit -> Limit
-> Merge Append -> Merge Append
Sort Key: minmaxtest_5.f1 DESC Sort Key: minmaxtest_5.f1 DESC
@ -1235,7 +1235,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------
Unique Unique
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Merge Append -> Merge Append
Sort Key: minmaxtest.f1 Sort Key: minmaxtest.f1
@ -1246,7 +1246,7 @@ explain (costs off)
-> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3 -> 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_4 -> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4
InitPlan 2 (returns $1) InitPlan 2
-> Limit -> Limit
-> Merge Append -> Merge Append
Sort Key: minmaxtest_5.f1 DESC Sort Key: minmaxtest_5.f1 DESC
@ -1258,7 +1258,7 @@ explain (costs off)
Index Cond: (f1 IS NOT NULL) Index Cond: (f1 IS NOT NULL)
-> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9 -> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9
-> Sort -> Sort
Sort Key: ($0), ($1) Sort Key: ((InitPlan 1).col1), ((InitPlan 2).col1)
-> Result -> Result
(26 rows) (26 rows)

View File

@ -559,7 +559,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
------------------------------------------------------------ ------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan using tenk1_unique1 on tenk1 -> Index Only Scan using tenk1_unique1 on tenk1
Index Cond: (unique1 IS NOT NULL) Index Cond: (unique1 IS NOT NULL)
@ -2110,13 +2110,13 @@ order by a, b, c;
explain (costs off) explain (costs off)
select (select grouping(v1)) from (values ((select 1))) v(v1) group by cube(v1); select (select grouping(v1)) from (values ((select 1))) v(v1) group by cube(v1);
QUERY PLAN QUERY PLAN
--------------------------- -------------------------------
MixedAggregate MixedAggregate
Hash Key: $2 Hash Key: (InitPlan 3).col1
Group Key: () Group Key: ()
InitPlan 1 (returns $1) InitPlan 1
-> Result -> Result
InitPlan 3 (returns $2) InitPlan 3
-> Result -> Result
-> Result -> Result
SubPlan 2 SubPlan 2
@ -2133,11 +2133,11 @@ select (select grouping(v1)) from (values ((select 1))) v(v1) group by cube(v1);
explain (costs off) explain (costs off)
select (select grouping(v1)) from (values ((select 1))) v(v1) group by v1; select (select grouping(v1)) from (values ((select 1))) v(v1) group by v1;
QUERY PLAN QUERY PLAN
--------------------------- ----------------
GroupAggregate GroupAggregate
InitPlan 1 (returns $1) InitPlan 1
-> Result -> Result
InitPlan 3 (returns $2) InitPlan 3
-> Result -> Result
-> Result -> Result
SubPlan 2 SubPlan 2

View File

@ -1643,8 +1643,8 @@ explain (verbose, costs off) select min(1-id) from matest0;
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------------- ---------------------------------------------------------------------------------
Result Result
Output: $0 Output: (InitPlan 1).col1
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
Output: ((1 - matest0.id)) Output: ((1 - matest0.id))
-> Result -> Result
@ -1800,7 +1800,7 @@ SELECT min(x) FROM
QUERY PLAN QUERY PLAN
-------------------------------------------------------------------- --------------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Merge Append -> Merge Append
Sort Key: a.unique1 Sort Key: a.unique1
@ -1818,7 +1818,7 @@ SELECT min(y) FROM
QUERY PLAN QUERY PLAN
-------------------------------------------------------------------- --------------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Merge Append -> Merge Append
Sort Key: a.unique1 Sort Key: a.unique1
@ -1899,18 +1899,18 @@ insert into inhcld select x::text, x from generate_series(6,10) x;
explain (verbose, costs off) explain (verbose, costs off)
update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1); update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1);
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
Update on public.inhpar i Update on public.inhpar i
Update on public.inhpar i_1 Update on public.inhpar i_1
Update on public.inhcld i_2 Update on public.inhcld i_2
-> Result -> Result
Output: $2, $3, (SubPlan 1 (returns $2,$3)), i.tableoid, i.ctid Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), i.tableoid, i.ctid
-> Append -> Append
-> Seq Scan on public.inhpar i_1 -> Seq Scan on public.inhpar i_1
Output: i_1.f1, i_1.f2, i_1.tableoid, i_1.ctid Output: i_1.f1, i_1.f2, i_1.tableoid, i_1.ctid
-> Seq Scan on public.inhcld i_2 -> Seq Scan on public.inhcld i_2
Output: i_2.f1, i_2.f2, i_2.tableoid, i_2.ctid Output: i_2.f1, i_2.f2, i_2.tableoid, i_2.ctid
SubPlan 1 (returns $2,$3) SubPlan 1
-> Limit -> Limit
Output: (i.f1), (((i.f2)::text || '-'::text)) Output: (i.f1), (((i.f2)::text || '-'::text))
-> Seq Scan on public.int4_tbl -> Seq Scan on public.int4_tbl
@ -1947,20 +1947,20 @@ insert into inhpar select x, x::text from generate_series(1,10) x;
explain (verbose, costs off) explain (verbose, costs off)
update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1); update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1);
QUERY PLAN QUERY PLAN
----------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------
Update on public.inhpar i Update on public.inhpar i
Update on public.inhcld1 i_1 Update on public.inhcld1 i_1
Update on public.inhcld2 i_2 Update on public.inhcld2 i_2
-> Append -> Append
-> Seq Scan on public.inhcld1 i_1 -> Seq Scan on public.inhcld1 i_1
Output: $2, $3, (SubPlan 1 (returns $2,$3)), i_1.tableoid, i_1.ctid Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), i_1.tableoid, i_1.ctid
SubPlan 1 (returns $2,$3) SubPlan 1
-> Limit -> Limit
Output: (i_1.f1), (((i_1.f2)::text || '-'::text)) Output: (i_1.f1), (((i_1.f2)::text || '-'::text))
-> Seq Scan on public.int4_tbl -> Seq Scan on public.int4_tbl
Output: i_1.f1, ((i_1.f2)::text || '-'::text) Output: i_1.f1, ((i_1.f2)::text || '-'::text)
-> Seq Scan on public.inhcld2 i_2 -> Seq Scan on public.inhcld2 i_2
Output: $2, $3, (SubPlan 1 (returns $2,$3)), i_2.tableoid, i_2.ctid Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), i_2.tableoid, i_2.ctid
(13 rows) (13 rows)
update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1); update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1);
@ -2845,11 +2845,11 @@ explain (costs off) select min(a), max(a) from parted_minmax where b = '12345';
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Limit -> Limit
-> Index Only Scan using parted_minmax1i on parted_minmax1 parted_minmax -> Index Only Scan using parted_minmax1i on parted_minmax1 parted_minmax
Index Cond: ((a IS NOT NULL) AND (b = '12345'::text)) Index Cond: ((a IS NOT NULL) AND (b = '12345'::text))
InitPlan 2 (returns $1) InitPlan 2
-> Limit -> Limit
-> Index Only Scan Backward using parted_minmax1i on parted_minmax1 parted_minmax_1 -> Index Only Scan Backward using parted_minmax1i on parted_minmax1 parted_minmax_1
Index Cond: ((a IS NOT NULL) AND (b = '12345'::text)) Index Cond: ((a IS NOT NULL) AND (b = '12345'::text))

View File

@ -50,7 +50,7 @@ explain (costs off) insert into insertconflicttest values(0, 'Crowberry') on con
Insert on insertconflicttest Insert on insertconflicttest
Conflict Resolution: UPDATE Conflict Resolution: UPDATE
Conflict Arbiter Indexes: op_index_key, collation_index_key, both_index_key Conflict Arbiter Indexes: op_index_key, collation_index_key, both_index_key
Conflict Filter: (SubPlan 1) Conflict Filter: EXISTS(SubPlan 1)
-> Result -> Result
SubPlan 1 SubPlan 1
-> Index Only Scan using both_index_expr_key on insertconflicttest ii -> Index Only Scan using both_index_expr_key on insertconflicttest ii

View File

@ -3029,9 +3029,9 @@ explain (costs off)
select a.* from tenk1 a select a.* from tenk1 a
where unique1 not in (select unique2 from tenk1 b); where unique1 not in (select unique2 from tenk1 b);
QUERY PLAN QUERY PLAN
-------------------------------------------------------- -----------------------------------------------------------
Seq Scan on tenk1 a Seq Scan on tenk1 a
Filter: (NOT (hashed SubPlan 1)) Filter: (NOT (ANY (unique1 = (hashed SubPlan 1).col1)))
SubPlan 1 SubPlan 1
-> Index Only Scan using tenk1_unique2 on tenk1 b -> Index Only Scan using tenk1_unique2 on tenk1 b
(4 rows) (4 rows)
@ -5279,11 +5279,11 @@ select a.unique1, b.unique2
from onek a left join onek b on a.unique1 = b.unique2 from onek a left join onek b on a.unique1 = b.unique2
where (b.unique2, random() > 0) = any (select q1, random() > 0 from int8_tbl c where c.q1 < b.unique1); where (b.unique2, random() > 0) = any (select q1, random() > 0 from int8_tbl c where c.q1 < b.unique1);
QUERY PLAN QUERY PLAN
---------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------
Hash Join Hash Join
Hash Cond: (b.unique2 = a.unique1) Hash Cond: (b.unique2 = a.unique1)
-> Seq Scan on onek b -> Seq Scan on onek b
Filter: (SubPlan 1) Filter: (ANY ((unique2 = (SubPlan 1).col1) AND ((random() > '0'::double precision) = (SubPlan 1).col2)))
SubPlan 1 SubPlan 1
-> Seq Scan on int8_tbl c -> Seq Scan on int8_tbl c
Filter: (q1 < b.unique1) Filter: (q1 < b.unique1)
@ -8263,7 +8263,7 @@ lateral (select * from int8_tbl t1,
and (select v.id=0)) offset 0) ss2) ss and (select v.id=0)) offset 0) ss2) ss
where t1.q1 = ss.q2) ss0; where t1.q1 = ss.q2) ss0;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------
Nested Loop Nested Loop
Output: "*VALUES*".column1, t1.q1, t1.q2, ss2.q1, ss2.q2 Output: "*VALUES*".column1, t1.q1, t1.q2, ss2.q1, ss2.q2
-> Seq Scan on public.int8_tbl t1 -> Seq Scan on public.int8_tbl t1
@ -8277,20 +8277,20 @@ lateral (select * from int8_tbl t1,
Filter: (t1.q1 = ss2.q2) Filter: (t1.q1 = ss2.q2)
-> Seq Scan on public.int8_tbl t2 -> Seq Scan on public.int8_tbl t2
Output: t2.q1, t2.q2 Output: t2.q1, t2.q2
Filter: (SubPlan 3) Filter: (ANY ((t2.q1 = (SubPlan 3).col1) AND ((random() > '0'::double precision) = (SubPlan 3).col2)))
SubPlan 3 SubPlan 3
-> Result -> Result
Output: t3.q2, (random() > '0'::double precision) Output: t3.q2, (random() > '0'::double precision)
One-Time Filter: $4 One-Time Filter: (InitPlan 2).col1
InitPlan 1 (returns $2) InitPlan 1
-> Result -> Result
Output: GREATEST(t1.q1, t2.q2) Output: GREATEST(t1.q1, t2.q2)
InitPlan 2 (returns $4) InitPlan 2
-> Result -> Result
Output: ("*VALUES*".column1 = 0) Output: ("*VALUES*".column1 = 0)
-> Seq Scan on public.int8_tbl t3 -> Seq Scan on public.int8_tbl t3
Output: t3.q1, t3.q2 Output: t3.q1, t3.q2
Filter: (t3.q2 = $2) Filter: (t3.q2 = (InitPlan 1).col1)
(27 rows) (27 rows)
select * from (values (0), (1)) v(id), select * from (values (0), (1)) v(id),

View File

@ -342,7 +342,7 @@ WHERE unique1 < 3
---------------------------------------------------------------- ----------------------------------------------------------------
Index Scan using tenk1_unique1 on tenk1 t0 Index Scan using tenk1_unique1 on tenk1 t0
Index Cond: (unique1 < 3) Index Cond: (unique1 < 3)
Filter: (SubPlan 1) Filter: EXISTS(SubPlan 1)
SubPlan 1 SubPlan 1
-> Nested Loop -> Nested Loop
-> Index Scan using tenk1_hundred on tenk1 t2 -> Index Scan using tenk1_hundred on tenk1 t2

View File

@ -1697,10 +1697,10 @@ WHEN MATCHED AND t.c > s.cnt THEN
-> Seq Scan on public.ref r_2 -> Seq Scan on public.ref r_2
Output: r_2.ab, r_2.cd Output: r_2.ab, r_2.cd
Filter: ((r_2.ab = (s.a + s.b)) AND (r_2.cd = (s.c - s.d))) Filter: ((r_2.ab = (s.a + s.b)) AND (r_2.cd = (s.c - s.d)))
SubPlan 3 (returns $9,$10) SubPlan 3
-> Result -> Result
Output: s.b, $8 Output: s.b, (InitPlan 2).col1
InitPlan 2 (returns $8) InitPlan 2
-> Aggregate -> Aggregate
Output: count(*) Output: count(*)
-> Seq Scan on public.ref r_1 -> Seq Scan on public.ref r_1

View File

@ -2177,17 +2177,17 @@ prepare ab_q2 (int, int) as
select a from ab where a between $1 and $2 and b < (select 3); select a from ab where a between $1 and $2 and b < (select 3);
explain (analyze, costs off, summary off, timing off) execute ab_q2 (2, 2); explain (analyze, costs off, summary off, timing off) execute ab_q2 (2, 2);
QUERY PLAN QUERY PLAN
--------------------------------------------------------- -----------------------------------------------------------------------
Append (actual rows=0 loops=1) Append (actual rows=0 loops=1)
Subplans Removed: 6 Subplans Removed: 6
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
-> Seq Scan on ab_a2_b1 ab_1 (actual rows=0 loops=1) -> Seq Scan on ab_a2_b1 ab_1 (actual rows=0 loops=1)
Filter: ((a >= $1) AND (a <= $2) AND (b < $0)) Filter: ((a >= $1) AND (a <= $2) AND (b < (InitPlan 1).col1))
-> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1) -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1)
Filter: ((a >= $1) AND (a <= $2) AND (b < $0)) Filter: ((a >= $1) AND (a <= $2) AND (b < (InitPlan 1).col1))
-> Seq Scan on ab_a2_b3 ab_3 (never executed) -> Seq Scan on ab_a2_b3 ab_3 (never executed)
Filter: ((a >= $1) AND (a <= $2) AND (b < $0)) Filter: ((a >= $1) AND (a <= $2) AND (b < (InitPlan 1).col1))
(10 rows) (10 rows)
-- As above, but swap the PARAM_EXEC Param to the first partition level -- As above, but swap the PARAM_EXEC Param to the first partition level
@ -2195,17 +2195,17 @@ prepare ab_q3 (int, int) as
select a from ab where b between $1 and $2 and a < (select 3); select a from ab where b between $1 and $2 and a < (select 3);
explain (analyze, costs off, summary off, timing off) execute ab_q3 (2, 2); explain (analyze, costs off, summary off, timing off) execute ab_q3 (2, 2);
QUERY PLAN QUERY PLAN
--------------------------------------------------------- -----------------------------------------------------------------------
Append (actual rows=0 loops=1) Append (actual rows=0 loops=1)
Subplans Removed: 6 Subplans Removed: 6
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
-> Seq Scan on ab_a1_b2 ab_1 (actual rows=0 loops=1) -> Seq Scan on ab_a1_b2 ab_1 (actual rows=0 loops=1)
Filter: ((b >= $1) AND (b <= $2) AND (a < $0)) Filter: ((b >= $1) AND (b <= $2) AND (a < (InitPlan 1).col1))
-> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1) -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1)
Filter: ((b >= $1) AND (b <= $2) AND (a < $0)) Filter: ((b >= $1) AND (b <= $2) AND (a < (InitPlan 1).col1))
-> Seq Scan on ab_a3_b2 ab_3 (never executed) -> Seq Scan on ab_a3_b2 ab_3 (never executed)
Filter: ((b >= $1) AND (b <= $2) AND (a < $0)) Filter: ((b >= $1) AND (b <= $2) AND (a < (InitPlan 1).col1))
(10 rows) (10 rows)
-- --
@ -2412,24 +2412,23 @@ select explain_parallel_append('execute ab_q5 (33, 44, 55)');
-- Test Parallel Append with PARAM_EXEC Params -- Test Parallel Append with PARAM_EXEC Params
select explain_parallel_append('select count(*) from ab where (a = (select 1) or a = (select 3)) and b = 2'); select explain_parallel_append('select count(*) from ab where (a = (select 1) or a = (select 3)) and b = 2');
explain_parallel_append explain_parallel_append
------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------
Aggregate (actual rows=N loops=N) Aggregate (actual rows=N loops=N)
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=N loops=N) -> Result (actual rows=N loops=N)
InitPlan 2 (returns $1) InitPlan 2
-> Result (actual rows=N loops=N) -> Result (actual rows=N loops=N)
-> Gather (actual rows=N loops=N) -> Gather (actual rows=N loops=N)
Workers Planned: 2 Workers Planned: 2
Params Evaluated: $0, $1
Workers Launched: N Workers Launched: N
-> Parallel Append (actual rows=N loops=N) -> Parallel Append (actual rows=N loops=N)
-> Parallel Seq Scan on ab_a1_b2 ab_1 (actual rows=N loops=N) -> Parallel Seq Scan on ab_a1_b2 ab_1 (actual rows=N loops=N)
Filter: ((b = 2) AND ((a = $0) OR (a = $1))) Filter: ((b = 2) AND ((a = (InitPlan 1).col1) OR (a = (InitPlan 2).col1)))
-> Parallel Seq Scan on ab_a2_b2 ab_2 (never executed) -> Parallel Seq Scan on ab_a2_b2 ab_2 (never executed)
Filter: ((b = 2) AND ((a = $0) OR (a = $1))) Filter: ((b = 2) AND ((a = (InitPlan 1).col1) OR (a = (InitPlan 2).col1)))
-> Parallel Seq Scan on ab_a3_b2 ab_3 (actual rows=N loops=N) -> Parallel Seq Scan on ab_a3_b2 ab_3 (actual rows=N loops=N)
Filter: ((b = 2) AND ((a = $0) OR (a = $1))) Filter: ((b = 2) AND ((a = (InitPlan 1).col1) OR (a = (InitPlan 2).col1)))
(16 rows) (15 rows)
-- Test pruning during parallel nested loop query -- Test pruning during parallel nested loop query
create table lprt_a (a int not null); create table lprt_a (a int not null);
@ -2629,57 +2628,57 @@ select * from ab where a = (select max(a) from lprt_a) and b = (select max(a)-1
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------- -------------------------------------------------------------------------
Append (actual rows=0 loops=1) Append (actual rows=0 loops=1)
InitPlan 1 (returns $0) InitPlan 1
-> Aggregate (actual rows=1 loops=1) -> Aggregate (actual rows=1 loops=1)
-> Seq Scan on lprt_a (actual rows=102 loops=1) -> Seq Scan on lprt_a (actual rows=102 loops=1)
InitPlan 2 (returns $1) InitPlan 2
-> Aggregate (actual rows=1 loops=1) -> Aggregate (actual rows=1 loops=1)
-> Seq Scan on lprt_a lprt_a_1 (actual rows=102 loops=1) -> Seq Scan on lprt_a lprt_a_1 (actual rows=102 loops=1)
-> Bitmap Heap Scan on ab_a1_b1 ab_1 (never executed) -> Bitmap Heap Scan on ab_a1_b1 ab_1 (never executed)
Recheck Cond: (a = $0) Recheck Cond: (a = (InitPlan 1).col1)
Filter: (b = $1) Filter: (b = (InitPlan 2).col1)
-> Bitmap Index Scan on ab_a1_b1_a_idx (never executed) -> Bitmap Index Scan on ab_a1_b1_a_idx (never executed)
Index Cond: (a = $0) Index Cond: (a = (InitPlan 1).col1)
-> Bitmap Heap Scan on ab_a1_b2 ab_2 (never executed) -> Bitmap Heap Scan on ab_a1_b2 ab_2 (never executed)
Recheck Cond: (a = $0) Recheck Cond: (a = (InitPlan 1).col1)
Filter: (b = $1) Filter: (b = (InitPlan 2).col1)
-> Bitmap Index Scan on ab_a1_b2_a_idx (never executed) -> Bitmap Index Scan on ab_a1_b2_a_idx (never executed)
Index Cond: (a = $0) Index Cond: (a = (InitPlan 1).col1)
-> Bitmap Heap Scan on ab_a1_b3 ab_3 (never executed) -> Bitmap Heap Scan on ab_a1_b3 ab_3 (never executed)
Recheck Cond: (a = $0) Recheck Cond: (a = (InitPlan 1).col1)
Filter: (b = $1) Filter: (b = (InitPlan 2).col1)
-> Bitmap Index Scan on ab_a1_b3_a_idx (never executed) -> Bitmap Index Scan on ab_a1_b3_a_idx (never executed)
Index Cond: (a = $0) Index Cond: (a = (InitPlan 1).col1)
-> Bitmap Heap Scan on ab_a2_b1 ab_4 (never executed) -> Bitmap Heap Scan on ab_a2_b1 ab_4 (never executed)
Recheck Cond: (a = $0) Recheck Cond: (a = (InitPlan 1).col1)
Filter: (b = $1) Filter: (b = (InitPlan 2).col1)
-> Bitmap Index Scan on ab_a2_b1_a_idx (never executed) -> Bitmap Index Scan on ab_a2_b1_a_idx (never executed)
Index Cond: (a = $0) Index Cond: (a = (InitPlan 1).col1)
-> Bitmap Heap Scan on ab_a2_b2 ab_5 (never executed) -> Bitmap Heap Scan on ab_a2_b2 ab_5 (never executed)
Recheck Cond: (a = $0) Recheck Cond: (a = (InitPlan 1).col1)
Filter: (b = $1) Filter: (b = (InitPlan 2).col1)
-> Bitmap Index Scan on ab_a2_b2_a_idx (never executed) -> Bitmap Index Scan on ab_a2_b2_a_idx (never executed)
Index Cond: (a = $0) Index Cond: (a = (InitPlan 1).col1)
-> Bitmap Heap Scan on ab_a2_b3 ab_6 (never executed) -> Bitmap Heap Scan on ab_a2_b3 ab_6 (never executed)
Recheck Cond: (a = $0) Recheck Cond: (a = (InitPlan 1).col1)
Filter: (b = $1) Filter: (b = (InitPlan 2).col1)
-> Bitmap Index Scan on ab_a2_b3_a_idx (never executed) -> Bitmap Index Scan on ab_a2_b3_a_idx (never executed)
Index Cond: (a = $0) Index Cond: (a = (InitPlan 1).col1)
-> Bitmap Heap Scan on ab_a3_b1 ab_7 (never executed) -> Bitmap Heap Scan on ab_a3_b1 ab_7 (never executed)
Recheck Cond: (a = $0) Recheck Cond: (a = (InitPlan 1).col1)
Filter: (b = $1) Filter: (b = (InitPlan 2).col1)
-> Bitmap Index Scan on ab_a3_b1_a_idx (never executed) -> Bitmap Index Scan on ab_a3_b1_a_idx (never executed)
Index Cond: (a = $0) Index Cond: (a = (InitPlan 1).col1)
-> Bitmap Heap Scan on ab_a3_b2 ab_8 (actual rows=0 loops=1) -> Bitmap Heap Scan on ab_a3_b2 ab_8 (actual rows=0 loops=1)
Recheck Cond: (a = $0) Recheck Cond: (a = (InitPlan 1).col1)
Filter: (b = $1) Filter: (b = (InitPlan 2).col1)
-> Bitmap Index Scan on ab_a3_b2_a_idx (actual rows=0 loops=1) -> Bitmap Index Scan on ab_a3_b2_a_idx (actual rows=0 loops=1)
Index Cond: (a = $0) Index Cond: (a = (InitPlan 1).col1)
-> Bitmap Heap Scan on ab_a3_b3 ab_9 (never executed) -> Bitmap Heap Scan on ab_a3_b3 ab_9 (never executed)
Recheck Cond: (a = $0) Recheck Cond: (a = (InitPlan 1).col1)
Filter: (b = $1) Filter: (b = (InitPlan 2).col1)
-> Bitmap Index Scan on ab_a3_b3_a_idx (never executed) -> Bitmap Index Scan on ab_a3_b3_a_idx (never executed)
Index Cond: (a = $0) Index Cond: (a = (InitPlan 1).col1)
(52 rows) (52 rows)
-- Test run-time partition pruning with UNION ALL parents -- Test run-time partition pruning with UNION ALL parents
@ -2688,42 +2687,42 @@ select * from (select * from ab where a = 1 union all select * from ab) ab where
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Append (actual rows=0 loops=1) Append (actual rows=0 loops=1)
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
-> Append (actual rows=0 loops=1) -> Append (actual rows=0 loops=1)
-> Bitmap Heap Scan on ab_a1_b1 ab_11 (actual rows=0 loops=1) -> Bitmap Heap Scan on ab_a1_b1 ab_11 (actual rows=0 loops=1)
Recheck Cond: (a = 1) Recheck Cond: (a = 1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1)
Index Cond: (a = 1) Index Cond: (a = 1)
-> Bitmap Heap Scan on ab_a1_b2 ab_12 (never executed) -> Bitmap Heap Scan on ab_a1_b2 ab_12 (never executed)
Recheck Cond: (a = 1) Recheck Cond: (a = 1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Bitmap Index Scan on ab_a1_b2_a_idx (never executed) -> Bitmap Index Scan on ab_a1_b2_a_idx (never executed)
Index Cond: (a = 1) Index Cond: (a = 1)
-> Bitmap Heap Scan on ab_a1_b3 ab_13 (never executed) -> Bitmap Heap Scan on ab_a1_b3 ab_13 (never executed)
Recheck Cond: (a = 1) Recheck Cond: (a = 1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Bitmap Index Scan on ab_a1_b3_a_idx (never executed) -> Bitmap Index Scan on ab_a1_b3_a_idx (never executed)
Index Cond: (a = 1) Index Cond: (a = 1)
-> Seq Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1) -> Seq Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a1_b2 ab_2 (never executed) -> Seq Scan on ab_a1_b2 ab_2 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a1_b3 ab_3 (never executed) -> Seq Scan on ab_a1_b3 ab_3 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a2_b1 ab_4 (actual rows=0 loops=1) -> Seq Scan on ab_a2_b1 ab_4 (actual rows=0 loops=1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a2_b2 ab_5 (never executed) -> Seq Scan on ab_a2_b2 ab_5 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a2_b3 ab_6 (never executed) -> Seq Scan on ab_a2_b3 ab_6 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a3_b1 ab_7 (actual rows=0 loops=1) -> Seq Scan on ab_a3_b1 ab_7 (actual rows=0 loops=1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a3_b2 ab_8 (never executed) -> Seq Scan on ab_a3_b2 ab_8 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a3_b3 ab_9 (never executed) -> Seq Scan on ab_a3_b3 ab_9 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
(37 rows) (37 rows)
-- A case containing a UNION ALL with a non-partitioned child. -- A case containing a UNION ALL with a non-partitioned child.
@ -2732,44 +2731,44 @@ select * from (select * from ab where a = 1 union all (values(10,5)) union all s
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Append (actual rows=0 loops=1) Append (actual rows=0 loops=1)
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
-> Append (actual rows=0 loops=1) -> Append (actual rows=0 loops=1)
-> Bitmap Heap Scan on ab_a1_b1 ab_11 (actual rows=0 loops=1) -> Bitmap Heap Scan on ab_a1_b1 ab_11 (actual rows=0 loops=1)
Recheck Cond: (a = 1) Recheck Cond: (a = 1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1)
Index Cond: (a = 1) Index Cond: (a = 1)
-> Bitmap Heap Scan on ab_a1_b2 ab_12 (never executed) -> Bitmap Heap Scan on ab_a1_b2 ab_12 (never executed)
Recheck Cond: (a = 1) Recheck Cond: (a = 1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Bitmap Index Scan on ab_a1_b2_a_idx (never executed) -> Bitmap Index Scan on ab_a1_b2_a_idx (never executed)
Index Cond: (a = 1) Index Cond: (a = 1)
-> Bitmap Heap Scan on ab_a1_b3 ab_13 (never executed) -> Bitmap Heap Scan on ab_a1_b3 ab_13 (never executed)
Recheck Cond: (a = 1) Recheck Cond: (a = 1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Bitmap Index Scan on ab_a1_b3_a_idx (never executed) -> Bitmap Index Scan on ab_a1_b3_a_idx (never executed)
Index Cond: (a = 1) Index Cond: (a = 1)
-> Result (actual rows=0 loops=1) -> Result (actual rows=0 loops=1)
One-Time Filter: (5 = $0) One-Time Filter: (5 = (InitPlan 1).col1)
-> Seq Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1) -> Seq Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a1_b2 ab_2 (never executed) -> Seq Scan on ab_a1_b2 ab_2 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a1_b3 ab_3 (never executed) -> Seq Scan on ab_a1_b3 ab_3 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a2_b1 ab_4 (actual rows=0 loops=1) -> Seq Scan on ab_a2_b1 ab_4 (actual rows=0 loops=1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a2_b2 ab_5 (never executed) -> Seq Scan on ab_a2_b2 ab_5 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a2_b3 ab_6 (never executed) -> Seq Scan on ab_a2_b3 ab_6 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a3_b1 ab_7 (actual rows=0 loops=1) -> Seq Scan on ab_a3_b1 ab_7 (actual rows=0 loops=1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a3_b2 ab_8 (never executed) -> Seq Scan on ab_a3_b2 ab_8 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a3_b3 ab_9 (never executed) -> Seq Scan on ab_a3_b3 ab_9 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
(39 rows) (39 rows)
-- Another UNION ALL test, but containing a mix of exec init and exec run-time pruning. -- Another UNION ALL test, but containing a mix of exec init and exec run-time pruning.
@ -2788,26 +2787,26 @@ union all
-- Ensure the xy_1 subplan is not pruned. -- Ensure the xy_1 subplan is not pruned.
explain (analyze, costs off, summary off, timing off) execute ab_q6(1); explain (analyze, costs off, summary off, timing off) execute ab_q6(1);
QUERY PLAN QUERY PLAN
-------------------------------------------------- --------------------------------------------------------
Append (actual rows=0 loops=1) Append (actual rows=0 loops=1)
Subplans Removed: 12 Subplans Removed: 12
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
-> Seq Scan on ab_a1_b1 ab_1 (never executed) -> Seq Scan on ab_a1_b1 ab_1 (never executed)
Filter: ((a = $1) AND (b = $0)) Filter: ((a = $1) AND (b = (InitPlan 1).col1))
-> Seq Scan on ab_a1_b2 ab_2 (never executed) -> Seq Scan on ab_a1_b2 ab_2 (never executed)
Filter: ((a = $1) AND (b = $0)) Filter: ((a = $1) AND (b = (InitPlan 1).col1))
-> Seq Scan on ab_a1_b3 ab_3 (never executed) -> Seq Scan on ab_a1_b3 ab_3 (never executed)
Filter: ((a = $1) AND (b = $0)) Filter: ((a = $1) AND (b = (InitPlan 1).col1))
-> Seq Scan on xy_1 (actual rows=0 loops=1) -> Seq Scan on xy_1 (actual rows=0 loops=1)
Filter: ((x = $1) AND (y = $0)) Filter: ((x = $1) AND (y = (InitPlan 1).col1))
Rows Removed by Filter: 1 Rows Removed by Filter: 1
-> Seq Scan on ab_a1_b1 ab_4 (never executed) -> Seq Scan on ab_a1_b1 ab_4 (never executed)
Filter: ((a = $1) AND (b = $0)) Filter: ((a = $1) AND (b = (InitPlan 1).col1))
-> Seq Scan on ab_a1_b2 ab_5 (never executed) -> Seq Scan on ab_a1_b2 ab_5 (never executed)
Filter: ((a = $1) AND (b = $0)) Filter: ((a = $1) AND (b = (InitPlan 1).col1))
-> Seq Scan on ab_a1_b3 ab_6 (never executed) -> Seq Scan on ab_a1_b3 ab_6 (never executed)
Filter: ((a = $1) AND (b = $0)) Filter: ((a = $1) AND (b = (InitPlan 1).col1))
(19 rows) (19 rows)
-- Ensure we see just the xy_1 row. -- Ensure we see just the xy_1 row.
@ -2886,7 +2885,7 @@ update ab_a1 set b = 3 from ab_a2 where ab_a2.b = (select 1);
Update on ab_a1_b1 ab_a1_1 Update on ab_a1_b1 ab_a1_1
Update on ab_a1_b2 ab_a1_2 Update on ab_a1_b2 ab_a1_2
Update on ab_a1_b3 ab_a1_3 Update on ab_a1_b3 ab_a1_3
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
-> Nested Loop (actual rows=3 loops=1) -> Nested Loop (actual rows=3 loops=1)
-> Append (actual rows=3 loops=1) -> Append (actual rows=3 loops=1)
@ -2896,11 +2895,11 @@ update ab_a1 set b = 3 from ab_a2 where ab_a2.b = (select 1);
-> Materialize (actual rows=1 loops=3) -> Materialize (actual rows=1 loops=3)
-> Append (actual rows=1 loops=1) -> Append (actual rows=1 loops=1)
-> Seq Scan on ab_a2_b1 ab_a2_1 (actual rows=1 loops=1) -> Seq Scan on ab_a2_b1 ab_a2_1 (actual rows=1 loops=1)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a2_b2 ab_a2_2 (never executed) -> Seq Scan on ab_a2_b2 ab_a2_2 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
-> Seq Scan on ab_a2_b3 ab_a2_3 (never executed) -> Seq Scan on ab_a2_b3 ab_a2_3 (never executed)
Filter: (b = $0) Filter: (b = (InitPlan 1).col1)
(19 rows) (19 rows)
select tableoid::regclass, * from ab; select tableoid::regclass, * from ab;
@ -3234,12 +3233,12 @@ select * from listp where a = (select null::int);
QUERY PLAN QUERY PLAN
------------------------------------------------------ ------------------------------------------------------
Append (actual rows=0 loops=1) Append (actual rows=0 loops=1)
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
-> Seq Scan on listp_1_1 listp_1 (never executed) -> Seq Scan on listp_1_1 listp_1 (never executed)
Filter: (a = $0) Filter: (a = (InitPlan 1).col1)
-> Seq Scan on listp_2_1 listp_2 (never executed) -> Seq Scan on listp_2_1 listp_2 (never executed)
Filter: (a = $0) Filter: (a = (InitPlan 1).col1)
(7 rows) (7 rows)
drop table listp; drop table listp;
@ -3378,13 +3377,13 @@ prepare ps1 as
explain (analyze, costs off, summary off, timing off) explain (analyze, costs off, summary off, timing off)
execute ps1(1); execute ps1(1);
QUERY PLAN QUERY PLAN
-------------------------------------------------------- -------------------------------------------------------------
Append (actual rows=1 loops=1) Append (actual rows=1 loops=1)
Subplans Removed: 2 Subplans Removed: 2
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
-> Seq Scan on mc3p1 mc3p_1 (actual rows=1 loops=1) -> Seq Scan on mc3p1 mc3p_1 (actual rows=1 loops=1)
Filter: ((a = $1) AND (abs(b) < $0)) Filter: ((a = $1) AND (abs(b) < (InitPlan 1).col1))
(6 rows) (6 rows)
deallocate ps1; deallocate ps1;
@ -3393,15 +3392,15 @@ prepare ps2 as
explain (analyze, costs off, summary off, timing off) explain (analyze, costs off, summary off, timing off)
execute ps2(1); execute ps2(1);
QUERY PLAN QUERY PLAN
-------------------------------------------------------- --------------------------------------------------------------
Append (actual rows=2 loops=1) Append (actual rows=2 loops=1)
Subplans Removed: 1 Subplans Removed: 1
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
-> Seq Scan on mc3p0 mc3p_1 (actual rows=1 loops=1) -> Seq Scan on mc3p0 mc3p_1 (actual rows=1 loops=1)
Filter: ((a <= $1) AND (abs(b) < $0)) Filter: ((a <= $1) AND (abs(b) < (InitPlan 1).col1))
-> Seq Scan on mc3p1 mc3p_2 (actual rows=1 loops=1) -> Seq Scan on mc3p1 mc3p_2 (actual rows=1 loops=1)
Filter: ((a <= $1) AND (abs(b) < $0)) Filter: ((a <= $1) AND (abs(b) < (InitPlan 1).col1))
(8 rows) (8 rows)
deallocate ps2; deallocate ps2;
@ -3417,14 +3416,14 @@ select * from boolp where a = (select value from boolvalues where value);
QUERY PLAN QUERY PLAN
----------------------------------------------------------- -----------------------------------------------------------
Append (actual rows=0 loops=1) Append (actual rows=0 loops=1)
InitPlan 1 (returns $0) InitPlan 1
-> Seq Scan on boolvalues (actual rows=1 loops=1) -> Seq Scan on boolvalues (actual rows=1 loops=1)
Filter: value Filter: value
Rows Removed by Filter: 1 Rows Removed by Filter: 1
-> Seq Scan on boolp_f boolp_1 (never executed) -> Seq Scan on boolp_f boolp_1 (never executed)
Filter: (a = $0) Filter: (a = (InitPlan 1).col1)
-> Seq Scan on boolp_t boolp_2 (actual rows=0 loops=1) -> Seq Scan on boolp_t boolp_2 (actual rows=0 loops=1)
Filter: (a = $0) Filter: (a = (InitPlan 1).col1)
(9 rows) (9 rows)
explain (analyze, costs off, summary off, timing off) explain (analyze, costs off, summary off, timing off)
@ -3432,14 +3431,14 @@ select * from boolp where a = (select value from boolvalues where not value);
QUERY PLAN QUERY PLAN
----------------------------------------------------------- -----------------------------------------------------------
Append (actual rows=0 loops=1) Append (actual rows=0 loops=1)
InitPlan 1 (returns $0) InitPlan 1
-> Seq Scan on boolvalues (actual rows=1 loops=1) -> Seq Scan on boolvalues (actual rows=1 loops=1)
Filter: (NOT value) Filter: (NOT value)
Rows Removed by Filter: 1 Rows Removed by Filter: 1
-> Seq Scan on boolp_f boolp_1 (actual rows=0 loops=1) -> Seq Scan on boolp_f boolp_1 (actual rows=0 loops=1)
Filter: (a = $0) Filter: (a = (InitPlan 1).col1)
-> Seq Scan on boolp_t boolp_2 (never executed) -> Seq Scan on boolp_t boolp_2 (never executed)
Filter: (a = $0) Filter: (a = (InitPlan 1).col1)
(9 rows) (9 rows)
drop table boolp; drop table boolp;
@ -3528,18 +3527,18 @@ explain (analyze, costs off, summary off, timing off) select * from ma_test wher
----------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------
Merge Append (actual rows=20 loops=1) Merge Append (actual rows=20 loops=1)
Sort Key: ma_test.b Sort Key: ma_test.b
InitPlan 2 (returns $1) InitPlan 2
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
InitPlan 1 (returns $0) InitPlan 1
-> Limit (actual rows=1 loops=1) -> Limit (actual rows=1 loops=1)
-> Index Scan using ma_test_p2_b_idx on ma_test_p2 (actual rows=1 loops=1) -> Index Scan using ma_test_p2_b_idx on ma_test_p2 (actual rows=1 loops=1)
Index Cond: (b IS NOT NULL) Index Cond: (b IS NOT NULL)
-> Index Scan using ma_test_p1_b_idx on ma_test_p1 ma_test_1 (never executed) -> Index Scan using ma_test_p1_b_idx on ma_test_p1 ma_test_1 (never executed)
Filter: (a >= $1) Filter: (a >= (InitPlan 2).col1)
-> Index Scan using ma_test_p2_b_idx on ma_test_p2 ma_test_2 (actual rows=10 loops=1) -> Index Scan using ma_test_p2_b_idx on ma_test_p2 ma_test_2 (actual rows=10 loops=1)
Filter: (a >= $1) Filter: (a >= (InitPlan 2).col1)
-> Index Scan using ma_test_p3_b_idx on ma_test_p3 ma_test_3 (actual rows=10 loops=1) -> Index Scan using ma_test_p3_b_idx on ma_test_p3 ma_test_3 (actual rows=10 loops=1)
Filter: (a >= $1) Filter: (a >= (InitPlan 2).col1)
(14 rows) (14 rows)
reset enable_seqscan; reset enable_seqscan;
@ -3909,16 +3908,16 @@ from (
) s(a, b, c) ) s(a, b, c)
where s.a = 1 and s.b = 1 and s.c = (select 1); where s.a = 1 and s.b = 1 and s.c = (select 1);
QUERY PLAN QUERY PLAN
---------------------------------------------------- -------------------------------------------------------------------
Append Append
InitPlan 1 (returns $0) InitPlan 1
-> Result -> Result
-> Seq Scan on p1 p -> Seq Scan on p1 p
Filter: ((a = 1) AND (b = 1) AND (c = $0)) Filter: ((a = 1) AND (b = 1) AND (c = (InitPlan 1).col1))
-> Seq Scan on q111 q1 -> Seq Scan on q111 q1
Filter: ((a = 1) AND (b = 1) AND (c = $0)) Filter: ((a = 1) AND (b = 1) AND (c = (InitPlan 1).col1))
-> Result -> Result
One-Time Filter: (1 = $0) One-Time Filter: (1 = (InitPlan 1).col1)
(9 rows) (9 rows)
select * select *
@ -3947,17 +3946,17 @@ from (
where s.a = $1 and s.b = $2 and s.c = (select 1); where s.a = $1 and s.b = $2 and s.c = (select 1);
explain (costs off) execute q (1, 1); explain (costs off) execute q (1, 1);
QUERY PLAN QUERY PLAN
--------------------------------------------------------------- ------------------------------------------------------------------------------
Append Append
Subplans Removed: 1 Subplans Removed: 1
InitPlan 1 (returns $0) InitPlan 1
-> Result -> Result
-> Seq Scan on p1 p -> Seq Scan on p1 p
Filter: ((a = $1) AND (b = $2) AND (c = $0)) Filter: ((a = $1) AND (b = $2) AND (c = (InitPlan 1).col1))
-> Seq Scan on q111 q1 -> Seq Scan on q111 q1
Filter: ((a = $1) AND (b = $2) AND (c = $0)) Filter: ((a = $1) AND (b = $2) AND (c = (InitPlan 1).col1))
-> Result -> Result
One-Time Filter: ((1 = $1) AND (1 = $2) AND (1 = $0)) One-Time Filter: ((1 = $1) AND (1 = $2) AND (1 = (InitPlan 1).col1))
(10 rows) (10 rows)
execute q (1, 1); execute q (1, 1);
@ -3976,10 +3975,10 @@ create table listp2_10 partition of listp2 for values in (10);
explain (analyze, costs off, summary off, timing off) explain (analyze, costs off, summary off, timing off)
select * from listp where a = (select 2) and b <> 10; select * from listp where a = (select 2) and b <> 10;
QUERY PLAN QUERY PLAN
-------------------------------------------------- ---------------------------------------------------
Seq Scan on listp1 listp (actual rows=0 loops=1) Seq Scan on listp1 listp (actual rows=0 loops=1)
Filter: ((b <> 10) AND (a = $0)) Filter: ((b <> 10) AND (a = (InitPlan 1).col1))
InitPlan 1 (returns $0) InitPlan 1
-> Result (never executed) -> Result (never executed)
(4 rows) (4 rows)
@ -4044,16 +4043,15 @@ select explain_parallel_append('select * from listp where a = (select 1);');
---------------------------------------------------------------------- ----------------------------------------------------------------------
Gather (actual rows=N loops=N) Gather (actual rows=N loops=N)
Workers Planned: 2 Workers Planned: 2
Params Evaluated: $0
Workers Launched: N Workers Launched: N
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=N loops=N) -> Result (actual rows=N loops=N)
-> Parallel Append (actual rows=N loops=N) -> Parallel Append (actual rows=N loops=N)
-> Seq Scan on listp_12_1 listp_1 (actual rows=N loops=N) -> Seq Scan on listp_12_1 listp_1 (actual rows=N loops=N)
Filter: (a = $0) Filter: (a = (InitPlan 1).col1)
-> Parallel Seq Scan on listp_12_2 listp_2 (never executed) -> Parallel Seq Scan on listp_12_2 listp_2 (never executed)
Filter: (a = $0) Filter: (a = (InitPlan 1).col1)
(11 rows) (10 rows)
-- Like the above but throw some more complexity at the planner by adding -- Like the above but throw some more complexity at the planner by adding
-- a UNION ALL. We expect both sides of the union not to scan the -- a UNION ALL. We expect both sides of the union not to scan the
@ -4069,19 +4067,19 @@ select * from listp where a = (select 2);');
Workers Launched: N Workers Launched: N
-> Parallel Append (actual rows=N loops=N) -> Parallel Append (actual rows=N loops=N)
-> Parallel Append (actual rows=N loops=N) -> Parallel Append (actual rows=N loops=N)
InitPlan 2 (returns $1) InitPlan 2
-> Result (actual rows=N loops=N) -> Result (actual rows=N loops=N)
-> Seq Scan on listp_12_1 listp_1 (never executed) -> Seq Scan on listp_12_1 listp_1 (never executed)
Filter: (a = $1) Filter: (a = (InitPlan 2).col1)
-> Parallel Seq Scan on listp_12_2 listp_2 (actual rows=N loops=N) -> Parallel Seq Scan on listp_12_2 listp_2 (actual rows=N loops=N)
Filter: (a = $1) Filter: (a = (InitPlan 2).col1)
-> Parallel Append (actual rows=N loops=N) -> Parallel Append (actual rows=N loops=N)
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=N loops=N) -> Result (actual rows=N loops=N)
-> Seq Scan on listp_12_1 listp_4 (actual rows=N loops=N) -> Seq Scan on listp_12_1 listp_4 (actual rows=N loops=N)
Filter: (a = $0) Filter: (a = (InitPlan 1).col1)
-> Parallel Seq Scan on listp_12_2 listp_5 (never executed) -> Parallel Seq Scan on listp_12_2 listp_5 (never executed)
Filter: (a = $0) Filter: (a = (InitPlan 1).col1)
(18 rows) (18 rows)
drop table listp; drop table listp;
@ -4104,20 +4102,20 @@ select * from rangep where b IN((select 1),(select 2)) order by a;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------
Append (actual rows=0 loops=1) Append (actual rows=0 loops=1)
InitPlan 1 (returns $0) InitPlan 1
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
InitPlan 2 (returns $1) InitPlan 2
-> Result (actual rows=1 loops=1) -> Result (actual rows=1 loops=1)
-> Merge Append (actual rows=0 loops=1) -> Merge Append (actual rows=0 loops=1)
Sort Key: rangep_2.a Sort Key: rangep_2.a
-> Index Scan using rangep_0_to_100_1_a_idx on rangep_0_to_100_1 rangep_2 (actual rows=0 loops=1) -> Index Scan using rangep_0_to_100_1_a_idx on rangep_0_to_100_1 rangep_2 (actual rows=0 loops=1)
Filter: (b = ANY (ARRAY[$0, $1])) Filter: (b = ANY (ARRAY[(InitPlan 1).col1, (InitPlan 2).col1]))
-> Index Scan using rangep_0_to_100_2_a_idx on rangep_0_to_100_2 rangep_3 (actual rows=0 loops=1) -> Index Scan using rangep_0_to_100_2_a_idx on rangep_0_to_100_2 rangep_3 (actual rows=0 loops=1)
Filter: (b = ANY (ARRAY[$0, $1])) Filter: (b = ANY (ARRAY[(InitPlan 1).col1, (InitPlan 2).col1]))
-> Index Scan using rangep_0_to_100_3_a_idx on rangep_0_to_100_3 rangep_4 (never executed) -> Index Scan using rangep_0_to_100_3_a_idx on rangep_0_to_100_3 rangep_4 (never executed)
Filter: (b = ANY (ARRAY[$0, $1])) Filter: (b = ANY (ARRAY[(InitPlan 1).col1, (InitPlan 2).col1]))
-> Index Scan using rangep_100_to_200_a_idx on rangep_100_to_200 rangep_5 (actual rows=0 loops=1) -> Index Scan using rangep_100_to_200_a_idx on rangep_100_to_200 rangep_5 (actual rows=0 loops=1)
Filter: (b = ANY (ARRAY[$0, $1])) Filter: (b = ANY (ARRAY[(InitPlan 1).col1, (InitPlan 2).col1]))
(15 rows) (15 rows)
reset enable_sort; reset enable_sort;

View File

@ -1473,17 +1473,17 @@ rollback;
begin; begin;
explain (costs off) declare c1 cursor for select (select 42) as x; explain (costs off) declare c1 cursor for select (select 42) as x;
QUERY PLAN QUERY PLAN
--------------------------- ----------------
Result Result
InitPlan 1 (returns $0) InitPlan 1
-> Result -> Result
(3 rows) (3 rows)
explain (costs off) declare c1 scroll cursor for select (select 42) as x; explain (costs off) declare c1 scroll cursor for select (select 42) as x;
QUERY PLAN QUERY PLAN
--------------------------- ----------------
Materialize Materialize
InitPlan 1 (returns $0) InitPlan 1
-> Result -> Result
-> Result -> Result
(4 rows) (4 rows)

View File

@ -266,26 +266,26 @@ NOTICE: f_leak => awesome science fiction
EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle); EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle);
QUERY PLAN QUERY PLAN
---------------------------------------------------- --------------------------------------------------------------
Seq Scan on document Seq Scan on document
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
InitPlan 1 (returns $0) InitPlan 1
-> Index Scan using uaccount_pkey on uaccount -> Index Scan using uaccount_pkey on uaccount
Index Cond: (pguser = CURRENT_USER) Index Cond: (pguser = CURRENT_USER)
(5 rows) (5 rows)
EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle); EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle);
QUERY PLAN QUERY PLAN
----------------------------------------------------------- --------------------------------------------------------------------------
Hash Join Hash Join
Hash Cond: (category.cid = document.cid) Hash Cond: (category.cid = document.cid)
InitPlan 1 (returns $0) InitPlan 1
-> 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 category -> Seq Scan on category
-> Hash -> Hash
-> Seq Scan on document -> Seq Scan on document
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
(9 rows) (9 rows)
-- viewpoint from regress_rls_dave -- viewpoint from regress_rls_dave
@ -330,26 +330,26 @@ NOTICE: f_leak => awesome technology book
EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle); EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle);
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
Seq Scan on document Seq Scan on document
Filter: ((cid <> 44) AND (cid <> 44) AND (cid < 50) AND (dlevel <= $0) AND f_leak(dtitle)) Filter: ((cid <> 44) AND (cid <> 44) AND (cid < 50) AND (dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
InitPlan 1 (returns $0) InitPlan 1
-> Index Scan using uaccount_pkey on uaccount -> Index Scan using uaccount_pkey on uaccount
Index Cond: (pguser = CURRENT_USER) Index Cond: (pguser = CURRENT_USER)
(5 rows) (5 rows)
EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle); EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle);
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------
Hash Join Hash Join
Hash Cond: (category.cid = document.cid) Hash Cond: (category.cid = document.cid)
InitPlan 1 (returns $0) InitPlan 1
-> 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 category -> Seq Scan on category
-> Hash -> Hash
-> Seq Scan on document -> Seq Scan on document
Filter: ((cid <> 44) AND (cid <> 44) AND (cid < 50) AND (dlevel <= $0) AND f_leak(dtitle)) Filter: ((cid <> 44) AND (cid <> 44) AND (cid < 50) AND (dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
(9 rows) (9 rows)
-- 44 would technically fail for both p2r and p1r, but we should get an error -- 44 would technically fail for both p2r and p1r, but we should get an error
@ -988,17 +988,17 @@ NOTICE: f_leak => my first satire
EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
QUERY PLAN QUERY PLAN
------------------------------------------------------------ --------------------------------------------------------------------
Append Append
InitPlan 1 (returns $0) InitPlan 1
-> 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_1 -> Seq Scan on part_document_fiction part_document_1
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-> Seq Scan on part_document_satire part_document_2 -> Seq Scan on part_document_satire part_document_2
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-> Seq Scan on part_document_nonfiction part_document_3 -> Seq Scan on part_document_nonfiction part_document_3
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
(10 rows) (10 rows)
-- viewpoint from regress_rls_carol -- viewpoint from regress_rls_carol
@ -1030,17 +1030,17 @@ NOTICE: f_leak => awesome technology book
EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
QUERY PLAN QUERY PLAN
------------------------------------------------------------ --------------------------------------------------------------------
Append Append
InitPlan 1 (returns $0) InitPlan 1
-> 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_1 -> Seq Scan on part_document_fiction part_document_1
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-> Seq Scan on part_document_satire part_document_2 -> Seq Scan on part_document_satire part_document_2
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-> Seq Scan on part_document_nonfiction part_document_3 -> Seq Scan on part_document_nonfiction part_document_3
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
(10 rows) (10 rows)
-- viewpoint from regress_rls_dave -- viewpoint from regress_rls_dave
@ -1060,10 +1060,10 @@ NOTICE: f_leak => awesome science fiction
EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
QUERY PLAN QUERY PLAN
-------------------------------------------------------------- -----------------------------------------------------------------------------
Seq Scan on part_document_fiction part_document Seq Scan on part_document_fiction part_document
Filter: ((cid < 55) AND (dlevel <= $0) AND f_leak(dtitle)) Filter: ((cid < 55) AND (dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
InitPlan 1 (returns $0) InitPlan 1
-> Index Scan using uaccount_pkey on uaccount -> Index Scan using uaccount_pkey on uaccount
Index Cond: (pguser = CURRENT_USER) Index Cond: (pguser = CURRENT_USER)
(5 rows) (5 rows)
@ -1138,10 +1138,10 @@ NOTICE: f_leak => awesome science fiction
EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
QUERY PLAN QUERY PLAN
-------------------------------------------------------------- -----------------------------------------------------------------------------
Seq Scan on part_document_fiction part_document Seq Scan on part_document_fiction part_document
Filter: ((cid < 55) AND (dlevel <= $0) AND f_leak(dtitle)) Filter: ((cid < 55) AND (dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
InitPlan 1 (returns $0) InitPlan 1
-> Index Scan using uaccount_pkey on uaccount -> Index Scan using uaccount_pkey on uaccount
Index Cond: (pguser = CURRENT_USER) Index Cond: (pguser = CURRENT_USER)
(5 rows) (5 rows)
@ -1177,17 +1177,17 @@ NOTICE: f_leak => awesome technology book
EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
QUERY PLAN QUERY PLAN
------------------------------------------------------------ --------------------------------------------------------------------
Append Append
InitPlan 1 (returns $0) InitPlan 1
-> 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_1 -> Seq Scan on part_document_fiction part_document_1
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-> Seq Scan on part_document_satire part_document_2 -> Seq Scan on part_document_satire part_document_2
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-> Seq Scan on part_document_nonfiction part_document_3 -> Seq Scan on part_document_nonfiction part_document_3
Filter: ((dlevel <= $0) AND f_leak(dtitle)) Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
(10 rows) (10 rows)
-- only owner can change policies -- only owner can change policies
@ -1438,9 +1438,9 @@ NOTICE: f_leak => 03b26944890929ff751653acb2f2af79
EXPLAIN (COSTS OFF) SELECT * FROM only s1 WHERE f_leak(b); EXPLAIN (COSTS OFF) SELECT * FROM only s1 WHERE f_leak(b);
QUERY PLAN QUERY PLAN
----------------------------------------------------------- ---------------------------------------------------------------
Seq Scan on s1 Seq Scan on s1
Filter: ((hashed SubPlan 1) AND f_leak(b)) Filter: ((ANY (a = (hashed SubPlan 1).col1)) AND f_leak(b))
SubPlan 1 SubPlan 1
-> Seq Scan on s2 -> Seq Scan on s2
Filter: (((x % 2) = 0) AND (y ~~ '%2f%'::text)) Filter: (((x % 2) = 0) AND (y ~~ '%2f%'::text))
@ -1458,9 +1458,9 @@ NOTICE: f_leak => 03b26944890929ff751653acb2f2af79
EXPLAIN (COSTS OFF) SELECT * FROM s1 WHERE f_leak(b); EXPLAIN (COSTS OFF) SELECT * FROM s1 WHERE f_leak(b);
QUERY PLAN QUERY PLAN
----------------------------------------------------------- ---------------------------------------------------------------
Seq Scan on s1 Seq Scan on s1
Filter: ((hashed SubPlan 1) AND f_leak(b)) Filter: ((ANY (a = (hashed SubPlan 1).col1)) AND f_leak(b))
SubPlan 1 SubPlan 1
-> Seq Scan on s2 -> Seq Scan on s2
Filter: (((x % 2) = 0) AND (y ~~ '%af%'::text)) Filter: (((x % 2) = 0) AND (y ~~ '%af%'::text))
@ -1480,7 +1480,7 @@ EXPLAIN (COSTS OFF) SELECT (SELECT x FROM s1 LIMIT 1) xx, * FROM s2 WHERE y like
SubPlan 2 SubPlan 2
-> Limit -> Limit
-> Seq Scan on s1 -> Seq Scan on s1
Filter: (hashed SubPlan 1) Filter: (ANY (a = (hashed SubPlan 1).col1))
SubPlan 1 SubPlan 1
-> Seq Scan on s2 s2_1 -> Seq Scan on s2 s2_1
Filter: (((x % 2) = 0) AND (y ~~ '%af%'::text)) Filter: (((x % 2) = 0) AND (y ~~ '%af%'::text))
@ -2718,9 +2718,9 @@ NOTICE: f_leak => bbb
EXPLAIN (COSTS OFF) SELECT * FROM rls_view; EXPLAIN (COSTS OFF) SELECT * FROM rls_view;
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------- ---------------------------------------------------------------------------------------
Seq Scan on z1 Seq Scan on z1
Filter: ((NOT (hashed SubPlan 1)) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((NOT (ANY (a = (hashed SubPlan 1).col1))) AND ((a % 2) = 0) AND f_leak(b))
SubPlan 1 SubPlan 1
-> Seq Scan on z1_blacklist -> Seq Scan on z1_blacklist
(4 rows) (4 rows)
@ -2736,9 +2736,9 @@ NOTICE: f_leak => bbb
EXPLAIN (COSTS OFF) SELECT * FROM rls_view; EXPLAIN (COSTS OFF) SELECT * FROM rls_view;
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------- ---------------------------------------------------------------------------------------
Seq Scan on z1 Seq Scan on z1
Filter: ((NOT (hashed SubPlan 1)) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((NOT (ANY (a = (hashed SubPlan 1).col1))) AND ((a % 2) = 0) AND f_leak(b))
SubPlan 1 SubPlan 1
-> Seq Scan on z1_blacklist -> Seq Scan on z1_blacklist
(4 rows) (4 rows)
@ -2908,9 +2908,9 @@ NOTICE: f_leak => bbb
EXPLAIN (COSTS OFF) SELECT * FROM rls_view; EXPLAIN (COSTS OFF) SELECT * FROM rls_view;
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------- ---------------------------------------------------------------------------------------
Seq Scan on z1 Seq Scan on z1
Filter: ((NOT (hashed SubPlan 1)) AND ((a % 2) = 0) AND f_leak(b)) Filter: ((NOT (ANY (a = (hashed SubPlan 1).col1))) AND ((a % 2) = 0) AND f_leak(b))
SubPlan 1 SubPlan 1
-> Seq Scan on z1_blacklist -> Seq Scan on z1_blacklist
(4 rows) (4 rows)
@ -2934,9 +2934,9 @@ NOTICE: f_leak => aba
EXPLAIN (COSTS OFF) SELECT * FROM rls_view; EXPLAIN (COSTS OFF) SELECT * FROM rls_view;
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------- ---------------------------------------------------------------------------------------
Seq Scan on z1 Seq Scan on z1
Filter: ((NOT (hashed SubPlan 1)) AND ((a % 2) = 1) AND f_leak(b)) Filter: ((NOT (ANY (a = (hashed SubPlan 1).col1))) AND ((a % 2) = 1) AND f_leak(b))
SubPlan 1 SubPlan 1
-> Seq Scan on z1_blacklist -> Seq Scan on z1_blacklist
(4 rows) (4 rows)

View File

@ -1250,7 +1250,7 @@ select * from cte2 as t
where (select * from (select c as c1) s where (select * from (select c as c1) s
where (select (c1).f1 > 0)) is not null; where (select (c1).f1 > 0)) is not null;
QUERY PLAN QUERY PLAN
-------------------------------------------- ----------------------------------------------
CTE Scan on cte CTE Scan on cte
Output: cte.c Output: cte.c
Filter: ((SubPlan 3) IS NOT NULL) Filter: ((SubPlan 3) IS NOT NULL)
@ -1260,8 +1260,8 @@ where (select * from (select c as c1) s
SubPlan 3 SubPlan 3
-> Result -> Result
Output: cte.c Output: cte.c
One-Time Filter: $2 One-Time Filter: (InitPlan 2).col1
InitPlan 2 (returns $2) InitPlan 2
-> Result -> Result
Output: ((cte.c).f1 > 0) Output: ((cte.c).f1 > 0)
(13 rows) (13 rows)

View File

@ -292,13 +292,13 @@ explain (costs off)
select count(*) from tenk1 where (two, four) not in select count(*) from tenk1 where (two, four) not in
(select hundred, thousand from tenk2 where thousand > 100); (select hundred, thousand from tenk2 where thousand > 100);
QUERY PLAN QUERY PLAN
------------------------------------------------------ ----------------------------------------------------------------------------------------------------------------
Finalize Aggregate Finalize Aggregate
-> Gather -> Gather
Workers Planned: 4 Workers Planned: 4
-> Partial Aggregate -> Partial Aggregate
-> Parallel Seq Scan on tenk1 -> Parallel Seq Scan on tenk1
Filter: (NOT (hashed SubPlan 1)) Filter: (NOT (ANY ((two = (hashed SubPlan 1).col1) AND (four = (hashed SubPlan 1).col2))))
SubPlan 1 SubPlan 1
-> Seq Scan on tenk2 -> Seq Scan on tenk2
Filter: (thousand > 100) Filter: (thousand > 100)
@ -316,9 +316,9 @@ explain (costs off)
select * from tenk1 where (unique1 + random())::integer not in select * from tenk1 where (unique1 + random())::integer not in
(select ten from tenk2); (select ten from tenk2);
QUERY PLAN QUERY PLAN
------------------------------------ -------------------------------------------------------------------------------------------------------
Seq Scan on tenk1 Seq Scan on tenk1
Filter: (NOT (hashed SubPlan 1)) Filter: (NOT (ANY ((((unique1)::double precision + random()))::integer = (hashed SubPlan 1).col1)))
SubPlan 1 SubPlan 1
-> Seq Scan on tenk2 -> Seq Scan on tenk2
(4 rows) (4 rows)
@ -335,7 +335,7 @@ explain (costs off)
QUERY PLAN QUERY PLAN
------------------------------------------------------ ------------------------------------------------------
Aggregate Aggregate
InitPlan 1 (returns $2) InitPlan 1
-> Finalize Aggregate -> Finalize Aggregate
-> Gather -> Gather
Workers Planned: 2 Workers Planned: 2
@ -343,10 +343,9 @@ explain (costs off)
-> Parallel Seq Scan on tenk2 -> Parallel Seq Scan on tenk2
-> Gather -> Gather
Workers Planned: 4 Workers Planned: 4
Params Evaluated: $2
-> Parallel Seq Scan on tenk1 -> Parallel Seq Scan on tenk1
Filter: (unique1 = $2) Filter: (unique1 = (InitPlan 1).col1)
(12 rows) (11 rows)
select count(*) from tenk1 select count(*) from tenk1
where tenk1.unique1 = (Select max(tenk2.unique1) from tenk2); where tenk1.unique1 = (Select max(tenk2.unique1) from tenk2);
@ -1150,27 +1149,25 @@ ORDER BY 1;
-> Append -> Append
-> Gather -> Gather
Workers Planned: 4 Workers Planned: 4
Params Evaluated: $1 InitPlan 1
InitPlan 1 (returns $1)
-> Limit -> Limit
-> Gather -> Gather
Workers Planned: 4 Workers Planned: 4
-> Parallel Seq Scan on tenk1 tenk1_2 -> Parallel Seq Scan on tenk1 tenk1_2
Filter: (fivethous = 1) Filter: (fivethous = 1)
-> Parallel Seq Scan on tenk1 -> Parallel Seq Scan on tenk1
Filter: (fivethous = $1) Filter: (fivethous = (InitPlan 1).col1)
-> Gather -> Gather
Workers Planned: 4 Workers Planned: 4
Params Evaluated: $3 InitPlan 2
InitPlan 2 (returns $3)
-> Limit -> Limit
-> Gather -> Gather
Workers Planned: 4 Workers Planned: 4
-> Parallel Seq Scan on tenk1 tenk1_3 -> Parallel Seq Scan on tenk1 tenk1_3
Filter: (fivethous = 1) Filter: (fivethous = 1)
-> Parallel Seq Scan on tenk1 tenk1_1 -> Parallel Seq Scan on tenk1 tenk1_1
Filter: (fivethous = $3) Filter: (fivethous = (InitPlan 2).col1)
(25 rows) (23 rows)
-- test interaction with SRFs -- test interaction with SRFs
SELECT * FROM information_schema.foreign_data_wrapper_options SELECT * FROM information_schema.foreign_data_wrapper_options
@ -1183,9 +1180,9 @@ EXPLAIN (VERBOSE, COSTS OFF)
SELECT generate_series(1, two), array(select generate_series(1, two)) SELECT generate_series(1, two), array(select generate_series(1, two))
FROM tenk1 ORDER BY tenthous; FROM tenk1 ORDER BY tenthous;
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------- ---------------------------------------------------------------------------
ProjectSet ProjectSet
Output: generate_series(1, tenk1.two), (SubPlan 1), tenk1.tenthous Output: generate_series(1, tenk1.two), ARRAY(SubPlan 1), tenk1.tenthous
-> Gather Merge -> Gather Merge
Output: tenk1.two, tenk1.tenthous Output: tenk1.two, tenk1.tenthous
Workers Planned: 4 Workers Planned: 4

View File

@ -1064,8 +1064,8 @@ SELECT JSON_ARRAY(SELECT i FROM (VALUES (1), (2), (NULL), (4)) foo(i) RETURNING
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------- ---------------------------------------------------------------------
Result Result
Output: $0 Output: (InitPlan 1).col1
InitPlan 1 (returns $0) InitPlan 1
-> Aggregate -> Aggregate
Output: JSON_ARRAYAGG("*VALUES*".column1 RETURNING jsonb) Output: JSON_ARRAYAGG("*VALUES*".column1 RETURNING jsonb)
-> Values Scan on "*VALUES*" -> Values Scan on "*VALUES*"

View File

@ -202,6 +202,57 @@ SELECT f1 AS "Correlated Field"
3 3
(5 rows) (5 rows)
-- Check ROWCOMPARE cases, both correlated and not
EXPLAIN (VERBOSE, COSTS OFF)
SELECT ROW(1, 2) = (SELECT f1, f2) AS eq FROM SUBSELECT_TBL;
QUERY PLAN
-----------------------------------------------------------------
Seq Scan on public.subselect_tbl
Output: (((1 = (SubPlan 1).col1) AND (2 = (SubPlan 1).col2)))
SubPlan 1
-> Result
Output: subselect_tbl.f1, subselect_tbl.f2
(5 rows)
SELECT ROW(1, 2) = (SELECT f1, f2) AS eq FROM SUBSELECT_TBL;
eq
----
t
f
f
f
f
f
f
f
(8 rows)
EXPLAIN (VERBOSE, COSTS OFF)
SELECT ROW(1, 2) = (SELECT 3, 4) AS eq FROM SUBSELECT_TBL;
QUERY PLAN
-----------------------------------------------------------------
Seq Scan on public.subselect_tbl
Output: ((1 = (InitPlan 1).col1) AND (2 = (InitPlan 1).col2))
InitPlan 1
-> Result
Output: 3, 4
(5 rows)
SELECT ROW(1, 2) = (SELECT 3, 4) AS eq FROM SUBSELECT_TBL;
eq
----
f
f
f
f
f
f
f
f
(8 rows)
SELECT ROW(1, 2) = (SELECT f1, f2 FROM SUBSELECT_TBL); -- error
ERROR: more than one row returned by a subquery used as an expression
-- Subselects without aliases -- Subselects without aliases
SELECT count FROM (SELECT COUNT(DISTINCT name) FROM road); SELECT count FROM (SELECT COUNT(DISTINCT name) FROM road);
count count
@ -325,17 +376,17 @@ explain (verbose, costs off) select '42' union all select 43;
explain (verbose, costs off) explain (verbose, costs off)
select 1 = all (select (select 1)); select 1 = all (select (select 1));
QUERY PLAN QUERY PLAN
----------------------------------- -------------------------------------------
Result Result
Output: (SubPlan 2) Output: (ALL (1 = (SubPlan 2).col1))
SubPlan 2 SubPlan 2
-> Materialize -> Materialize
Output: ($0) Output: ((InitPlan 1).col1)
InitPlan 1 (returns $0) InitPlan 1
-> Result -> Result
Output: 1 Output: 1
-> Result -> Result
Output: $0 Output: (InitPlan 1).col1
(10 rows) (10 rows)
select 1 = all (select (select 1)); select 1 = all (select (select 1));
@ -377,7 +428,7 @@ select * from int4_tbl o where exists
QUERY PLAN QUERY PLAN
-------------------------------------- --------------------------------------
Seq Scan on int4_tbl o Seq Scan on int4_tbl o
Filter: (SubPlan 1) Filter: EXISTS(SubPlan 1)
SubPlan 1 SubPlan 1
-> Limit -> Limit
-> Seq Scan on int4_tbl i -> Seq Scan on int4_tbl i
@ -841,9 +892,9 @@ select * from outer_text where (f1, f2) not in (select * from inner_text);
explain (verbose, costs off) explain (verbose, costs off)
select 'foo'::text in (select 'bar'::name union all select 'bar'::name); select 'foo'::text in (select 'bar'::name union all select 'bar'::name);
QUERY PLAN QUERY PLAN
------------------------------------- ---------------------------------------------------------
Result Result
Output: (hashed SubPlan 1) Output: (ANY ('foo'::text = (hashed SubPlan 1).col1))
SubPlan 1 SubPlan 1
-> Append -> Append
-> Result -> Result
@ -865,9 +916,9 @@ select 'foo'::text in (select 'bar'::name union all select 'bar'::name);
explain (verbose, costs off) explain (verbose, costs off)
select row(row(row(1))) = any (select row(row(1))); select row(row(row(1))) = any (select row(row(1)));
QUERY PLAN QUERY PLAN
------------------------------------------- --------------------------------------------------------
Result Result
Output: (SubPlan 1) Output: (ANY ('("(1)")'::record = (SubPlan 1).col1))
SubPlan 1 SubPlan 1
-> Materialize -> Materialize
Output: '("(1)")'::record Output: '("(1)")'::record
@ -908,9 +959,9 @@ create operator = (procedure=bogus_int8_text_eq, leftarg=int8, rightarg=text);
explain (costs off) explain (costs off)
select * from int8_tbl where q1 in (select c1 from inner_text); select * from int8_tbl where q1 in (select c1 from inner_text);
QUERY PLAN QUERY PLAN
-------------------------------- --------------------------------------------------------
Seq Scan on int8_tbl Seq Scan on int8_tbl
Filter: (hashed SubPlan 1) Filter: (ANY ((q1)::text = (hashed SubPlan 1).col1))
SubPlan 1 SubPlan 1
-> Seq Scan on inner_text -> Seq Scan on inner_text
(4 rows) (4 rows)
@ -929,9 +980,9 @@ language sql as 'select $1::text = $2 and $1::text = $2';
explain (costs off) explain (costs off)
select * from int8_tbl where q1 in (select c1 from inner_text); select * from int8_tbl where q1 in (select c1 from inner_text);
QUERY PLAN QUERY PLAN
-------------------------------- -----------------------------------------------------------------------------------------------------
Seq Scan on int8_tbl Seq Scan on int8_tbl
Filter: (hashed SubPlan 1) Filter: (ANY (((q1)::text = (hashed SubPlan 1).col1) AND ((q1)::text = (hashed SubPlan 1).col1)))
SubPlan 1 SubPlan 1
-> Seq Scan on inner_text -> Seq Scan on inner_text
(4 rows) (4 rows)
@ -950,9 +1001,9 @@ language sql as 'select $2 = $1::text';
explain (costs off) explain (costs off)
select * from int8_tbl where q1 in (select c1 from inner_text); select * from int8_tbl where q1 in (select c1 from inner_text);
QUERY PLAN QUERY PLAN
-------------------------------------- -------------------------------------------------
Seq Scan on int8_tbl Seq Scan on int8_tbl
Filter: (SubPlan 1) Filter: (ANY ((SubPlan 1).col1 = (q1)::text))
SubPlan 1 SubPlan 1
-> Materialize -> Materialize
-> Seq Scan on inner_text -> Seq Scan on inner_text
@ -973,10 +1024,10 @@ explain (costs off)
select count(*) from tenk1 t select count(*) from tenk1 t
where (exists(select 1 from tenk1 k where k.unique1 = t.unique2) or ten < 0); where (exists(select 1 from tenk1 k where k.unique1 = t.unique2) or ten < 0);
QUERY PLAN QUERY PLAN
-------------------------------------------------------------- --------------------------------------------------------------------------
Aggregate Aggregate
-> Seq Scan on tenk1 t -> Seq Scan on tenk1 t
Filter: ((hashed SubPlan 2) OR (ten < 0)) Filter: ((ANY (unique2 = (hashed SubPlan 2).col1)) OR (ten < 0))
SubPlan 2 SubPlan 2
-> Index Only Scan using tenk1_unique1 on tenk1 k -> Index Only Scan using tenk1_unique1 on tenk1 k
(5 rows) (5 rows)
@ -997,7 +1048,7 @@ where (exists(select 1 from tenk1 k where k.unique1 = t.unique2) or ten < 0)
Aggregate Aggregate
-> Bitmap Heap Scan on tenk1 t -> Bitmap Heap Scan on tenk1 t
Recheck Cond: (thousand = 1) Recheck Cond: (thousand = 1)
Filter: ((SubPlan 1) OR (ten < 0)) Filter: (EXISTS(SubPlan 1) OR (ten < 0))
-> Bitmap Index Scan on tenk1_thous_tenthous -> Bitmap Index Scan on tenk1_thous_tenthous
Index Cond: (thousand = 1) Index Cond: (thousand = 1)
SubPlan 1 SubPlan 1
@ -1023,10 +1074,10 @@ explain (costs off)
select * from exists_tbl t1 select * from exists_tbl t1
where (exists(select 1 from exists_tbl t2 where t1.c1 = t2.c2) or c3 < 0); where (exists(select 1 from exists_tbl t2 where t1.c1 = t2.c2) or c3 < 0);
QUERY PLAN QUERY PLAN
------------------------------------------------------ --------------------------------------------------------------------
Append Append
-> Seq Scan on exists_tbl_null t1_1 -> Seq Scan on exists_tbl_null t1_1
Filter: ((SubPlan 1) OR (c3 < 0)) Filter: (EXISTS(SubPlan 1) OR (c3 < 0))
SubPlan 1 SubPlan 1
-> Append -> Append
-> Seq Scan on exists_tbl_null t2_1 -> Seq Scan on exists_tbl_null t2_1
@ -1034,7 +1085,7 @@ select * from exists_tbl t1
-> Seq Scan on exists_tbl_def t2_2 -> Seq Scan on exists_tbl_def t2_2
Filter: (t1_1.c1 = c2) Filter: (t1_1.c1 = c2)
-> Seq Scan on exists_tbl_def t1_2 -> Seq Scan on exists_tbl_def t1_2
Filter: ((hashed SubPlan 2) OR (c3 < 0)) Filter: ((ANY (c1 = (hashed SubPlan 2).col1)) OR (c3 < 0))
SubPlan 2 SubPlan 2
-> Append -> Append
-> Seq Scan on exists_tbl_null t2_4 -> Seq Scan on exists_tbl_null t2_4
@ -1072,13 +1123,13 @@ explain (verbose, costs off)
select x, x from select x, x from
(select (select now()) as x from (values(1),(2)) v(y)) ss; (select (select now()) as x from (values(1),(2)) v(y)) ss;
QUERY PLAN QUERY PLAN
--------------------------- ------------------------------------------------
Values Scan on "*VALUES*" Values Scan on "*VALUES*"
Output: $0, $1 Output: (InitPlan 1).col1, (InitPlan 2).col1
InitPlan 1 (returns $0) InitPlan 1
-> Result -> Result
Output: now() Output: now()
InitPlan 2 (returns $1) InitPlan 2
-> Result -> Result
Output: now() Output: now()
(8 rows) (8 rows)
@ -1087,12 +1138,12 @@ explain (verbose, costs off)
select x, x from select x, x from
(select (select random()) as x from (values(1),(2)) v(y)) ss; (select (select random()) as x from (values(1),(2)) v(y)) ss;
QUERY PLAN QUERY PLAN
---------------------------------- -----------------------------------
Subquery Scan on ss Subquery Scan on ss
Output: ss.x, ss.x Output: ss.x, ss.x
-> Values Scan on "*VALUES*" -> Values Scan on "*VALUES*"
Output: $0 Output: (InitPlan 1).col1
InitPlan 1 (returns $0) InitPlan 1
-> Result -> Result
Output: random() Output: random()
(7 rows) (7 rows)
@ -1143,14 +1194,14 @@ where o.ten = 0;
QUERY PLAN QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate Aggregate
Output: sum((((hashed SubPlan 1)))::integer) Output: sum((((ANY (i.ten = (hashed SubPlan 1).col1))))::integer)
-> Nested Loop -> Nested Loop
Output: ((hashed SubPlan 1)) Output: ((ANY (i.ten = (hashed SubPlan 1).col1)))
-> Seq Scan on public.onek o -> Seq Scan on public.onek o
Output: o.unique1, o.unique2, o.two, o.four, o.ten, o.twenty, o.hundred, o.thousand, o.twothousand, o.fivethous, o.tenthous, o.odd, o.even, o.stringu1, o.stringu2, o.string4 Output: o.unique1, o.unique2, o.two, o.four, o.ten, o.twenty, o.hundred, o.thousand, o.twothousand, o.fivethous, o.tenthous, o.odd, o.even, o.stringu1, o.stringu2, o.string4
Filter: (o.ten = 0) Filter: (o.ten = 0)
-> Index Scan using onek_unique1 on public.onek i -> Index Scan using onek_unique1 on public.onek i
Output: (hashed SubPlan 1), random() Output: (ANY (i.ten = (hashed SubPlan 1).col1)), random()
Index Cond: (i.unique1 = o.unique1) Index Cond: (i.unique1 = o.unique1)
SubPlan 1 SubPlan 1
-> Seq Scan on public.int4_tbl -> Seq Scan on public.int4_tbl
@ -1346,7 +1397,7 @@ select * from int4_tbl where
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Nested Loop Semi Join Nested Loop Semi Join
Output: int4_tbl.f1 Output: int4_tbl.f1
Join Filter: (CASE WHEN (hashed SubPlan 1) THEN int4_tbl.f1 ELSE NULL::integer END = b.ten) Join Filter: (CASE WHEN (ANY (int4_tbl.f1 = (hashed SubPlan 1).col1)) THEN int4_tbl.f1 ELSE NULL::integer END = b.ten)
-> Seq Scan on public.int4_tbl -> Seq Scan on public.int4_tbl
Output: int4_tbl.f1 Output: int4_tbl.f1
-> Seq Scan on public.tenk1 b -> Seq Scan on public.tenk1 b
@ -1946,9 +1997,9 @@ select * from tenk1 A where exists
where A.hundred in (select C.hundred FROM tenk2 C where A.hundred in (select C.hundred FROM tenk2 C
WHERE c.odd = b.odd)); WHERE c.odd = b.odd));
QUERY PLAN QUERY PLAN
--------------------------------- -----------------------------------------------------
Nested Loop Semi Join Nested Loop Semi Join
Join Filter: (SubPlan 1) Join Filter: (ANY (a.hundred = (SubPlan 1).col1))
-> Seq Scan on tenk1 a -> Seq Scan on tenk1 a
-> Materialize -> Materialize
-> Seq Scan on tenk2 b -> Seq Scan on tenk2 b
@ -1963,9 +2014,9 @@ explain (costs off)
SELECT * FROM tenk1 A LEFT JOIN tenk2 B SELECT * FROM tenk1 A LEFT JOIN tenk2 B
ON A.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = b.odd); ON A.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = b.odd);
QUERY PLAN QUERY PLAN
--------------------------------- -----------------------------------------------------
Nested Loop Left Join Nested Loop Left Join
Join Filter: (SubPlan 1) Join Filter: (ANY (a.hundred = (SubPlan 1).col1))
-> Seq Scan on tenk1 a -> Seq Scan on tenk1 a
-> Materialize -> Materialize
-> Seq Scan on tenk2 b -> Seq Scan on tenk2 b
@ -1980,9 +2031,9 @@ explain (costs off)
SELECT * FROM tenk1 A LEFT JOIN tenk2 B SELECT * FROM tenk1 A LEFT JOIN tenk2 B
ON B.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = a.odd); ON B.hundred in (SELECT c.hundred FROM tenk2 C WHERE c.odd = a.odd);
QUERY PLAN QUERY PLAN
--------------------------------- -----------------------------------------------------
Nested Loop Left Join Nested Loop Left Join
Join Filter: (SubPlan 1) Join Filter: (ANY (b.hundred = (SubPlan 1).col1))
-> Seq Scan on tenk1 a -> Seq Scan on tenk1 a
-> Materialize -> Materialize
-> Seq Scan on tenk2 b -> Seq Scan on tenk2 b
@ -2045,7 +2096,7 @@ ON B.hundred in (SELECT min(c.hundred) FROM tenk2 C WHERE c.odd = b.odd);
-> Subquery Scan on "ANY_subquery" -> Subquery Scan on "ANY_subquery"
Filter: (b.hundred = "ANY_subquery".min) Filter: (b.hundred = "ANY_subquery".min)
-> Result -> Result
InitPlan 1 (returns $1) InitPlan 1
-> Limit -> Limit
-> Index Scan using tenk2_hundred on tenk2 c -> Index Scan using tenk2_hundred on tenk2 c
Index Cond: (hundred IS NOT NULL) Index Cond: (hundred IS NOT NULL)

View File

@ -3038,18 +3038,18 @@ EXPLAIN (costs off) INSERT INTO rw_view1 VALUES (2, 'New row 2');
QUERY PLAN QUERY PLAN
----------------------------------------------------------- -----------------------------------------------------------
Insert on base_tbl Insert on base_tbl
InitPlan 1 (returns $0) InitPlan 1
-> Index Only Scan using base_tbl_pkey on base_tbl t -> Index Only Scan using base_tbl_pkey on base_tbl t
Index Cond: (id = 2) Index Cond: (id = 2)
-> Result -> Result
One-Time Filter: ($0 IS NOT TRUE) One-Time Filter: ((InitPlan 1).col1 IS NOT TRUE)
Update on base_tbl Update on base_tbl
InitPlan 1 (returns $0) InitPlan 1
-> Index Only Scan using base_tbl_pkey on base_tbl t -> Index Only Scan using base_tbl_pkey on base_tbl t
Index Cond: (id = 2) Index Cond: (id = 2)
-> Result -> Result
One-Time Filter: $0 One-Time Filter: (InitPlan 1).col1
-> Index Scan using base_tbl_pkey on base_tbl -> Index Scan using base_tbl_pkey on base_tbl
Index Cond: (id = 2) Index Cond: (id = 2)
(15 rows) (15 rows)
@ -3109,7 +3109,7 @@ SELECT * FROM v1 WHERE a=8;
EXPLAIN (VERBOSE, COSTS OFF) EXPLAIN (VERBOSE, COSTS OFF)
UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6; UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6;
QUERY PLAN QUERY PLAN
----------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------
Update on public.t1 Update on public.t1
Update on public.t1 t1_1 Update on public.t1 t1_1
Update on public.t11 t1_2 Update on public.t11 t1_2
@ -3121,7 +3121,7 @@ UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6;
-> Index Scan using t1_a_idx on public.t1 t1_1 -> Index Scan using t1_a_idx on public.t1 t1_1
Output: t1_1.tableoid, t1_1.ctid Output: t1_1.tableoid, 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))
Filter: ((t1_1.a <> 6) AND (SubPlan 1) AND snoop(t1_1.a) AND leakproof(t1_1.a)) Filter: ((t1_1.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_1.a) AND leakproof(t1_1.a))
SubPlan 1 SubPlan 1
-> Append -> Append
-> Seq Scan on public.t12 t12_1 -> Seq Scan on public.t12 t12_1
@ -3131,15 +3131,15 @@ UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6;
-> Index Scan using t11_a_idx on public.t11 t1_2 -> Index Scan using t11_a_idx on public.t11 t1_2
Output: t1_2.tableoid, t1_2.ctid Output: t1_2.tableoid, t1_2.ctid
Index Cond: ((t1_2.a > 5) AND (t1_2.a < 7)) Index Cond: ((t1_2.a > 5) AND (t1_2.a < 7))
Filter: ((t1_2.a <> 6) AND (SubPlan 1) AND snoop(t1_2.a) AND leakproof(t1_2.a)) Filter: ((t1_2.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_2.a) AND leakproof(t1_2.a))
-> Index Scan using t12_a_idx on public.t12 t1_3 -> Index Scan using t12_a_idx on public.t12 t1_3
Output: t1_3.tableoid, t1_3.ctid Output: t1_3.tableoid, t1_3.ctid
Index Cond: ((t1_3.a > 5) AND (t1_3.a < 7)) Index Cond: ((t1_3.a > 5) AND (t1_3.a < 7))
Filter: ((t1_3.a <> 6) AND (SubPlan 1) AND snoop(t1_3.a) AND leakproof(t1_3.a)) Filter: ((t1_3.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_3.a) AND leakproof(t1_3.a))
-> Index Scan using t111_a_idx on public.t111 t1_4 -> Index Scan using t111_a_idx on public.t111 t1_4
Output: t1_4.tableoid, t1_4.ctid Output: t1_4.tableoid, t1_4.ctid
Index Cond: ((t1_4.a > 5) AND (t1_4.a < 7)) Index Cond: ((t1_4.a > 5) AND (t1_4.a < 7))
Filter: ((t1_4.a <> 6) AND (SubPlan 1) AND snoop(t1_4.a) AND leakproof(t1_4.a)) Filter: ((t1_4.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_4.a) AND leakproof(t1_4.a))
(30 rows) (30 rows)
UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6; UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6;
@ -3156,7 +3156,7 @@ SELECT * FROM t1 WHERE a=100; -- Nothing should have been changed to 100
EXPLAIN (VERBOSE, COSTS OFF) EXPLAIN (VERBOSE, COSTS OFF)
UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8; UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
QUERY PLAN QUERY PLAN
----------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------
Update on public.t1 Update on public.t1
Update on public.t1 t1_1 Update on public.t1 t1_1
Update on public.t11 t1_2 Update on public.t11 t1_2
@ -3168,7 +3168,7 @@ UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
-> Index Scan using t1_a_idx on public.t1 t1_1 -> Index Scan using t1_a_idx on public.t1 t1_1
Output: t1_1.a, t1_1.tableoid, t1_1.ctid Output: t1_1.a, t1_1.tableoid, 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))
Filter: ((SubPlan 1) AND snoop(t1_1.a) AND leakproof(t1_1.a)) Filter: (EXISTS(SubPlan 1) AND snoop(t1_1.a) AND leakproof(t1_1.a))
SubPlan 1 SubPlan 1
-> Append -> Append
-> Seq Scan on public.t12 t12_1 -> Seq Scan on public.t12 t12_1
@ -3178,15 +3178,15 @@ UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
-> Index Scan using t11_a_idx on public.t11 t1_2 -> Index Scan using t11_a_idx on public.t11 t1_2
Output: t1_2.a, t1_2.tableoid, t1_2.ctid Output: t1_2.a, t1_2.tableoid, t1_2.ctid
Index Cond: ((t1_2.a > 5) AND (t1_2.a = 8)) Index Cond: ((t1_2.a > 5) AND (t1_2.a = 8))
Filter: ((SubPlan 1) AND snoop(t1_2.a) AND leakproof(t1_2.a)) Filter: (EXISTS(SubPlan 1) AND snoop(t1_2.a) AND leakproof(t1_2.a))
-> Index Scan using t12_a_idx on public.t12 t1_3 -> Index Scan using t12_a_idx on public.t12 t1_3
Output: t1_3.a, t1_3.tableoid, t1_3.ctid Output: t1_3.a, t1_3.tableoid, t1_3.ctid
Index Cond: ((t1_3.a > 5) AND (t1_3.a = 8)) Index Cond: ((t1_3.a > 5) AND (t1_3.a = 8))
Filter: ((SubPlan 1) AND snoop(t1_3.a) AND leakproof(t1_3.a)) Filter: (EXISTS(SubPlan 1) AND snoop(t1_3.a) AND leakproof(t1_3.a))
-> Index Scan using t111_a_idx on public.t111 t1_4 -> Index Scan using t111_a_idx on public.t111 t1_4
Output: t1_4.a, t1_4.tableoid, t1_4.ctid Output: t1_4.a, t1_4.tableoid, t1_4.ctid
Index Cond: ((t1_4.a > 5) AND (t1_4.a = 8)) Index Cond: ((t1_4.a > 5) AND (t1_4.a = 8))
Filter: ((SubPlan 1) AND snoop(t1_4.a) AND leakproof(t1_4.a)) Filter: (EXISTS(SubPlan 1) AND snoop(t1_4.a) AND leakproof(t1_4.a))
(30 rows) (30 rows)
UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8; UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
@ -3371,9 +3371,9 @@ CREATE VIEW v2 WITH (security_barrier = true) AS
SELECT * FROM v1 WHERE EXISTS (SELECT 1); SELECT * FROM v1 WHERE EXISTS (SELECT 1);
EXPLAIN (COSTS OFF) UPDATE v2 SET a = 1; EXPLAIN (COSTS OFF) UPDATE v2 SET a = 1;
QUERY PLAN QUERY PLAN
--------------------------------------------------- --------------------------------------------------------------
Update on t1 Update on t1
InitPlan 1 (returns $0) InitPlan 1
-> Result -> Result
-> Merge Join -> Merge Join
Merge Cond: (t1.a = v1.a) Merge Cond: (t1.a = v1.a)
@ -3384,7 +3384,7 @@ EXPLAIN (COSTS OFF) UPDATE v2 SET a = 1;
Sort Key: v1.a Sort Key: v1.a
-> Subquery Scan on v1 -> Subquery Scan on v1
-> Result -> Result
One-Time Filter: $0 One-Time Filter: (InitPlan 1).col1
-> Seq Scan on t1 t1_1 -> Seq Scan on t1 t1_1
(14 rows) (14 rows)

View File

@ -179,14 +179,14 @@ UPDATE update_test t
SET (a, b) = (SELECT b, a FROM update_test s WHERE s.a = t.a) SET (a, b) = (SELECT b, a FROM update_test s WHERE s.a = t.a)
WHERE CURRENT_USER = SESSION_USER; WHERE CURRENT_USER = SESSION_USER;
QUERY PLAN QUERY PLAN
------------------------------------------------------------- --------------------------------------------------------------------------------
Update on public.update_test t Update on public.update_test t
-> Result -> Result
Output: $1, $2, (SubPlan 1 (returns $1,$2)), t.ctid Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), t.ctid
One-Time Filter: (CURRENT_USER = SESSION_USER) One-Time Filter: (CURRENT_USER = SESSION_USER)
-> Seq Scan on public.update_test t -> Seq Scan on public.update_test t
Output: t.a, t.ctid Output: t.a, t.ctid
SubPlan 1 (returns $1,$2) SubPlan 1
-> Seq Scan on public.update_test s -> Seq Scan on public.update_test s
Output: s.b, s.a Output: s.b, s.a
Filter: (s.a = t.a) Filter: (s.a = t.a)

View File

@ -4279,7 +4279,7 @@ WHERE c = 1;
Subquery Scan on emp Subquery Scan on emp
Filter: (emp.c = 1) Filter: (emp.c = 1)
-> WindowAgg -> WindowAgg
InitPlan 1 (returns $0) InitPlan 1
-> Result -> Result
-> Sort -> Sort
Sort Key: empsalary.empno DESC Sort Key: empsalary.empno DESC

View File

@ -3100,7 +3100,7 @@ WHEN NOT MATCHED THEN INSERT VALUES(o.k, o.v);
CTE cte_init CTE cte_init
-> Result -> Result
Output: 1, 'cte_init val'::text Output: 1, 'cte_init val'::text
InitPlan 2 (returns $1) InitPlan 2
-> Limit -> Limit
Output: ((cte_init.b || ' merge update'::text)) Output: ((cte_init.b || ' merge update'::text))
-> CTE Scan on cte_init -> CTE Scan on cte_init
@ -3143,11 +3143,11 @@ WHEN NOT MATCHED THEN INSERT VALUES(o.a, o.b || (SELECT merge_source_cte.*::text
CTE merge_source_cte CTE merge_source_cte
-> Result -> Result
Output: 15, 'merge_source_cte val'::text Output: 15, 'merge_source_cte val'::text
InitPlan 2 (returns $1) InitPlan 2
-> CTE Scan on merge_source_cte merge_source_cte_1 -> CTE Scan on merge_source_cte merge_source_cte_1
Output: ((merge_source_cte_1.b || (merge_source_cte_1.*)::text) || ' merge update'::text) Output: ((merge_source_cte_1.b || (merge_source_cte_1.*)::text) || ' merge update'::text)
Filter: (merge_source_cte_1.a = 15) Filter: (merge_source_cte_1.a = 15)
InitPlan 3 (returns $2) InitPlan 3
-> CTE Scan on merge_source_cte merge_source_cte_2 -> CTE Scan on merge_source_cte merge_source_cte_2
Output: ((merge_source_cte_2.*)::text || ' merge insert'::text) Output: ((merge_source_cte_2.*)::text || ' merge insert'::text)
-> Hash Right Join -> Hash Right Join

View File

@ -82,6 +82,20 @@ SELECT f1 AS "Correlated Field"
WHERE (f1, f2) IN (SELECT f2, CAST(f3 AS int4) FROM SUBSELECT_TBL WHERE (f1, f2) IN (SELECT f2, CAST(f3 AS int4) FROM SUBSELECT_TBL
WHERE f3 IS NOT NULL); WHERE f3 IS NOT NULL);
-- Check ROWCOMPARE cases, both correlated and not
EXPLAIN (VERBOSE, COSTS OFF)
SELECT ROW(1, 2) = (SELECT f1, f2) AS eq FROM SUBSELECT_TBL;
SELECT ROW(1, 2) = (SELECT f1, f2) AS eq FROM SUBSELECT_TBL;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT ROW(1, 2) = (SELECT 3, 4) AS eq FROM SUBSELECT_TBL;
SELECT ROW(1, 2) = (SELECT 3, 4) AS eq FROM SUBSELECT_TBL;
SELECT ROW(1, 2) = (SELECT f1, f2 FROM SUBSELECT_TBL); -- error
-- Subselects without aliases -- Subselects without aliases
SELECT count FROM (SELECT COUNT(DISTINCT name) FROM road); SELECT count FROM (SELECT COUNT(DISTINCT name) FROM road);