Pulling up direct-correlated ANY_SUBLINK

From: Richard Guo <riguo(at)pivotal(dot)io>
To: PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: Pulling up direct-correlated ANY_SUBLINK
Date: 2019-09-10 07:26:47
Message-ID: CAN_9JTx7N+CxEQLnu_uHxx+EscSgxLLuNgaZT6Sjvdpt7toy3w@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

Currently we do not try to pull up sub-select of type ANY_SUBLINK if it
refers to any Vars of the parent query, as indicated in the code snippet
below:

JoinExpr *
convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink,
Relids available_rels)
{
...

if (contain_vars_of_level((Node *) subselect, 1))
return NULL;

Why do we have this check?

Can we try to pull up direct-correlated ANY SubLink with the help of
LATERAL? That is, do the pull up in the same way as uncorrelated ANY
SubLink, by adding the SubLink's subselect to the query's rangetable,
but explicitly set LATERAL for its RangeTblEntry, like:

--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -1226,13 +1226,6 @@ convert_ANY_sublink_to_join(PlannerInfo *root,
SubLink *sublink,
Assert(sublink->subLinkType == ANY_SUBLINK);

/*
- * The sub-select must not refer to any Vars of the parent query.
(Vars of
- * higher levels should be okay, though.)
- */
- if (contain_vars_of_level((Node *) subselect, 1))
- return NULL;
-
- /*
* The test expression must contain some Vars of the parent query,
else
* it's not gonna be a join. (Note that it won't have Vars
referring to
* the subquery, rather Params.)
@@ -1267,7 +1260,7 @@ convert_ANY_sublink_to_join(PlannerInfo *root,
SubLink *sublink,
rte = addRangeTableEntryForSubquery(pstate,
subselect,
makeAlias("ANY_subquery", NIL),
- false,
+ contain_vars_of_level((Node *)
subselect, 1), /* lateral */
false);
parse->rtable = lappend(parse->rtable, rte);
rtindex = list_length(parse->rtable);

By this way, we can convert the query:

select * from a where a.i = ANY(select i from b where a.j > b.j);

To:

select * from a SEMI JOIN lateral(select * from b where a.j > b.j) sub on
a.i = sub.i;

Does this make sense?

Thanks
Richard

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Alexander Korotkov 2019-09-10 08:19:48 Re: WIP: BRIN multi-range indexes
Previous Message Tsunakawa, Takayuki 2019-09-10 06:44:48 RE: [bug fix] Produce a crash dump before main() on Windows