Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit824dbea

Browse files
committed
Add support for deparsing semi-joins to contrib/postgres_fdw
SEMI-JOIN is deparsed as the EXISTS subquery. It references outer and innerrelations, so it should be evaluated as the condition in the upper-level WHEREclause. The signatures of deparseFromExprForRel() and deparseRangeTblRef() arerevised so that they can add conditions to the upper level.PgFdwRelationInfo now has a hidden_subquery_rels field, referencing the relidsused in the inner parts of semi-join. They can't be referred to from upperrelations and should be used internally for equivalence member searches.The planner can create semi-join, which refers to inner rel vars in its targetlist. However, we deparse semi-join as an exists() subquery. So we skip thecase when the target list references to inner rel of semi-join.Author: Alexander PyhalovReviewed-by: Ashutosh Bapat, Ian Lawrence Barwick, Yuuki Fujii, Tomas VondraDiscussion:https://postgr.es/m/c9e2a757cf3ac2333714eaf83a9cc184@postgrespro.ru
1 parent278eb13 commit824dbea

File tree

5 files changed

+697
-81
lines changed

5 files changed

+697
-81
lines changed

‎contrib/postgres_fdw/deparse.c

Lines changed: 188 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,15 @@ static void appendConditions(List *exprs, deparse_expr_cxt *context);
180180
staticvoiddeparseFromExprForRel(StringInfobuf,PlannerInfo*root,
181181
RelOptInfo*foreignrel,booluse_alias,
182182
Indexignore_rel,List**ignore_conds,
183+
List**additional_conds,
183184
List**params_list);
185+
staticvoidappendWhereClause(List*exprs,List*additional_conds,
186+
deparse_expr_cxt*context);
184187
staticvoiddeparseFromExpr(List*quals,deparse_expr_cxt*context);
185188
staticvoiddeparseRangeTblRef(StringInfobuf,PlannerInfo*root,
186189
RelOptInfo*foreignrel,boolmake_subquery,
187-
Indexignore_rel,List**ignore_conds,List**params_list);
190+
Indexignore_rel,List**ignore_conds,
191+
List**additional_conds,List**params_list);
188192
staticvoiddeparseAggref(Aggref*node,deparse_expr_cxt*context);
189193
staticvoidappendGroupByClause(List*tlist,deparse_expr_cxt*context);
190194
staticvoidappendOrderBySuffix(Oidsortop,Oidsortcoltype,boolnulls_first,
@@ -1370,6 +1374,7 @@ deparseFromExpr(List *quals, deparse_expr_cxt *context)
13701374
{
13711375
StringInfobuf=context->buf;
13721376
RelOptInfo*scanrel=context->scanrel;
1377+
List*additional_conds=NIL;
13731378

13741379
/* For upper relations, scanrel must be either a joinrel or a baserel */
13751380
Assert(!IS_UPPER_REL(context->foreignrel)||
@@ -1379,14 +1384,11 @@ deparseFromExpr(List *quals, deparse_expr_cxt *context)
13791384
appendStringInfoString(buf," FROM ");
13801385
deparseFromExprForRel(buf,context->root,scanrel,
13811386
(bms_membership(scanrel->relids)==BMS_MULTIPLE),
1382-
(Index)0,NULL,context->params_list);
1383-
1384-
/* Construct WHERE clause */
1385-
if (quals!=NIL)
1386-
{
1387-
appendStringInfoString(buf," WHERE ");
1388-
appendConditions(quals,context);
1389-
}
1387+
(Index)0,NULL,&additional_conds,
1388+
context->params_list);
1389+
appendWhereClause(quals,additional_conds,context);
1390+
if (additional_conds!=NIL)
1391+
list_free_deep(additional_conds);
13901392
}
13911393

13921394
/*
@@ -1598,6 +1600,42 @@ appendConditions(List *exprs, deparse_expr_cxt *context)
15981600
reset_transmission_modes(nestlevel);
15991601
}
16001602

1603+
/*
1604+
* Append WHERE clause, containing conditions from exprs and additional_conds,
1605+
* to context->buf.
1606+
*/
1607+
staticvoid
1608+
appendWhereClause(List*exprs,List*additional_conds,deparse_expr_cxt*context)
1609+
{
1610+
StringInfobuf=context->buf;
1611+
boolneed_and= false;
1612+
ListCell*lc;
1613+
1614+
if (exprs!=NIL||additional_conds!=NIL)
1615+
appendStringInfoString(buf," WHERE ");
1616+
1617+
/*
1618+
* If there are some filters, append them.
1619+
*/
1620+
if (exprs!=NIL)
1621+
{
1622+
appendConditions(exprs,context);
1623+
need_and= true;
1624+
}
1625+
1626+
/*
1627+
* If there are some EXISTS conditions, coming from SEMI-JOINS, append
1628+
* them.
1629+
*/
1630+
foreach(lc,additional_conds)
1631+
{
1632+
if (need_and)
1633+
appendStringInfoString(buf," AND ");
1634+
appendStringInfoString(buf, (char*)lfirst(lc));
1635+
need_and= true;
1636+
}
1637+
}
1638+
16011639
/* Output join name for given join type */
16021640
constchar*
16031641
get_jointype_name(JoinTypejointype)
@@ -1616,6 +1654,9 @@ get_jointype_name(JoinType jointype)
16161654
caseJOIN_FULL:
16171655
return"FULL";
16181656

1657+
caseJOIN_SEMI:
1658+
return"SEMI";
1659+
16191660
default:
16201661
/* Shouldn't come here, but protect from buggy code. */
16211662
elog(ERROR,"unsupported join type %d",jointype);
@@ -1712,11 +1753,14 @@ deparseSubqueryTargetList(deparse_expr_cxt *context)
17121753
* of DELETE; it deparses the join relation as if the relation never contained
17131754
* the target relation, and creates a List of conditions to be deparsed into
17141755
* the top-level WHERE clause, which is returned to *ignore_conds.
1756+
*
1757+
* 'additional_conds' is a pointer to a list of strings to be appended to
1758+
* the WHERE clause, coming from lower-level SEMI-JOINs.
17151759
*/
17161760
staticvoid
17171761
deparseFromExprForRel(StringInfobuf,PlannerInfo*root,RelOptInfo*foreignrel,
17181762
booluse_alias,Indexignore_rel,List**ignore_conds,
1719-
List**params_list)
1763+
List**additional_conds,List**params_list)
17201764
{
17211765
PgFdwRelationInfo*fpinfo= (PgFdwRelationInfo*)foreignrel->fdw_private;
17221766

@@ -1728,6 +1772,8 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
17281772
RelOptInfo*innerrel=fpinfo->innerrel;
17291773
boolouterrel_is_target= false;
17301774
boolinnerrel_is_target= false;
1775+
List*additional_conds_i=NIL;
1776+
List*additional_conds_o=NIL;
17311777

17321778
if (ignore_rel>0&&bms_is_member(ignore_rel,foreignrel->relids))
17331779
{
@@ -1764,7 +1810,8 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
17641810
initStringInfo(&join_sql_o);
17651811
deparseRangeTblRef(&join_sql_o,root,outerrel,
17661812
fpinfo->make_outerrel_subquery,
1767-
ignore_rel,ignore_conds,params_list);
1813+
ignore_rel,ignore_conds,&additional_conds_o,
1814+
params_list);
17681815

17691816
/*
17701817
* If inner relation is the target relation, skip deparsing it.
@@ -1780,6 +1827,12 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
17801827
Assert(fpinfo->jointype==JOIN_INNER);
17811828
Assert(fpinfo->joinclauses==NIL);
17821829
appendBinaryStringInfo(buf,join_sql_o.data,join_sql_o.len);
1830+
/* Pass EXISTS conditions to upper level */
1831+
if (additional_conds_o!=NIL)
1832+
{
1833+
Assert(*additional_conds==NIL);
1834+
*additional_conds=additional_conds_o;
1835+
}
17831836
return;
17841837
}
17851838
}
@@ -1790,7 +1843,54 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
17901843
initStringInfo(&join_sql_i);
17911844
deparseRangeTblRef(&join_sql_i,root,innerrel,
17921845
fpinfo->make_innerrel_subquery,
1793-
ignore_rel,ignore_conds,params_list);
1846+
ignore_rel,ignore_conds,&additional_conds_i,
1847+
params_list);
1848+
1849+
/*
1850+
* SEMI-JOIN is deparsed as the EXISTS subquery. It references
1851+
* outer and inner relations, so it should be evaluated as the
1852+
* condition in the upper-level WHERE clause. We deparse the
1853+
* condition and pass it to upper level callers as an
1854+
* additional_conds list. Upper level callers are responsible for
1855+
* inserting conditions from the list where appropriate.
1856+
*/
1857+
if (fpinfo->jointype==JOIN_SEMI)
1858+
{
1859+
deparse_expr_cxtcontext;
1860+
StringInfoDatastr;
1861+
1862+
/* Construct deparsed condition from this SEMI-JOIN */
1863+
initStringInfo(&str);
1864+
appendStringInfo(&str,"EXISTS (SELECT NULL FROM %s",
1865+
join_sql_i.data);
1866+
1867+
context.buf=&str;
1868+
context.foreignrel=foreignrel;
1869+
context.scanrel=foreignrel;
1870+
context.root=root;
1871+
context.params_list=params_list;
1872+
1873+
/*
1874+
* Append SEMI-JOIN clauses and EXISTS conditions from lower
1875+
* levels to the current EXISTS subquery
1876+
*/
1877+
appendWhereClause(fpinfo->joinclauses,additional_conds_i,&context);
1878+
1879+
/*
1880+
* EXISTS conditions, coming from lower join levels, have just
1881+
* been processed.
1882+
*/
1883+
if (additional_conds_i!=NIL)
1884+
{
1885+
list_free_deep(additional_conds_i);
1886+
additional_conds_i=NIL;
1887+
}
1888+
1889+
/* Close parentheses for EXISTS subquery */
1890+
appendStringInfo(&str,")");
1891+
1892+
*additional_conds=lappend(*additional_conds,str.data);
1893+
}
17941894

17951895
/*
17961896
* If outer relation is the target relation, skip deparsing it.
@@ -1801,6 +1901,12 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
18011901
Assert(fpinfo->jointype==JOIN_INNER);
18021902
Assert(fpinfo->joinclauses==NIL);
18031903
appendBinaryStringInfo(buf,join_sql_i.data,join_sql_i.len);
1904+
/* Pass EXISTS conditions to the upper call */
1905+
if (additional_conds_i!=NIL)
1906+
{
1907+
Assert(*additional_conds==NIL);
1908+
*additional_conds=additional_conds_i;
1909+
}
18041910
return;
18051911
}
18061912
}
@@ -1809,33 +1915,65 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
18091915
Assert(!outerrel_is_target&& !innerrel_is_target);
18101916

18111917
/*
1812-
* Fora join relationFROM clauseentryis deparsed as
1813-
*
1814-
*((outer relation) <join type> (inner relation) ON (joinclauses))
1918+
* ForsemijoinFROM clause is deparsed as an outer relation. An inner
1919+
* relation and join clauses are converted to EXISTS condition and
1920+
*passed to the upper level.
18151921
*/
1816-
appendStringInfo(buf,"(%s %s JOIN %s ON ",join_sql_o.data,
1817-
get_jointype_name(fpinfo->jointype),join_sql_i.data);
1818-
1819-
/* Append join clause; (TRUE) if no join clause */
1820-
if (fpinfo->joinclauses)
1922+
if (fpinfo->jointype==JOIN_SEMI)
18211923
{
1822-
deparse_expr_cxtcontext;
1924+
appendStringInfo(buf,"%s",join_sql_o.data);
1925+
}
1926+
else
1927+
{
1928+
/*
1929+
* For a join relation FROM clause, entry is deparsed as
1930+
*
1931+
* ((outer relation) <join type> (inner relation) ON
1932+
* (joinclauses))
1933+
*/
1934+
appendStringInfo(buf,"(%s %s JOIN %s ON ",join_sql_o.data,
1935+
get_jointype_name(fpinfo->jointype),join_sql_i.data);
18231936

1824-
context.buf=buf;
1825-
context.foreignrel=foreignrel;
1826-
context.scanrel=foreignrel;
1827-
context.root=root;
1828-
context.params_list=params_list;
1937+
/* Append join clause; (TRUE) if no join clause */
1938+
if (fpinfo->joinclauses)
1939+
{
1940+
deparse_expr_cxtcontext;
18291941

1830-
appendStringInfoChar(buf,'(');
1831-
appendConditions(fpinfo->joinclauses,&context);
1942+
context.buf=buf;
1943+
context.foreignrel=foreignrel;
1944+
context.scanrel=foreignrel;
1945+
context.root=root;
1946+
context.params_list=params_list;
1947+
1948+
appendStringInfoChar(buf,'(');
1949+
appendConditions(fpinfo->joinclauses,&context);
1950+
appendStringInfoChar(buf,')');
1951+
}
1952+
else
1953+
appendStringInfoString(buf,"(TRUE)");
1954+
1955+
/* End the FROM clause entry. */
18321956
appendStringInfoChar(buf,')');
18331957
}
1834-
else
1835-
appendStringInfoString(buf,"(TRUE)");
18361958

1837-
/* End the FROM clause entry. */
1838-
appendStringInfoChar(buf,')');
1959+
/*
1960+
* Construct additional_conds to be passed to the upper caller from
1961+
* current level additional_conds and additional_conds, coming from
1962+
* inner and outer rels.
1963+
*/
1964+
if (additional_conds_o!=NIL)
1965+
{
1966+
*additional_conds=list_concat(*additional_conds,
1967+
additional_conds_o);
1968+
list_free(additional_conds_o);
1969+
}
1970+
1971+
if (additional_conds_i!=NIL)
1972+
{
1973+
*additional_conds=list_concat(*additional_conds,
1974+
additional_conds_i);
1975+
list_free(additional_conds_i);
1976+
}
18391977
}
18401978
else
18411979
{
@@ -1863,11 +2001,13 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
18632001

18642002
/*
18652003
* Append FROM clause entry for the given relation into buf.
2004+
* Conditions from lower-level SEMI-JOINs are appended to additional_conds
2005+
* and should be added to upper level WHERE clause.
18662006
*/
18672007
staticvoid
18682008
deparseRangeTblRef(StringInfobuf,PlannerInfo*root,RelOptInfo*foreignrel,
18692009
boolmake_subquery,Indexignore_rel,List**ignore_conds,
1870-
List**params_list)
2010+
List**additional_conds,List**params_list)
18712011
{
18722012
PgFdwRelationInfo*fpinfo= (PgFdwRelationInfo*)foreignrel->fdw_private;
18732013

@@ -1925,7 +2065,8 @@ deparseRangeTblRef(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
19252065
}
19262066
else
19272067
deparseFromExprForRel(buf,root,foreignrel, true,ignore_rel,
1928-
ignore_conds,params_list);
2068+
ignore_conds,additional_conds,
2069+
params_list);
19292070
}
19302071

19312072
/*
@@ -2148,6 +2289,7 @@ deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
21482289
RangeTblEntry*rte=planner_rt_fetch(rtindex,root);
21492290
ListCell*lc,
21502291
*lc2;
2292+
List*additional_conds=NIL;
21512293

21522294
/* Set up context struct for recursion */
21532295
context.root=root;
@@ -2189,17 +2331,17 @@ deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
21892331
{
21902332
List*ignore_conds=NIL;
21912333

2334+
21922335
appendStringInfoString(buf," FROM ");
21932336
deparseFromExprForRel(buf,root,foreignrel, true,rtindex,
2194-
&ignore_conds,params_list);
2337+
&ignore_conds,&additional_conds,params_list);
21952338
remote_conds=list_concat(remote_conds,ignore_conds);
21962339
}
21972340

2198-
if (remote_conds)
2199-
{
2200-
appendStringInfoString(buf," WHERE ");
2201-
appendConditions(remote_conds,&context);
2202-
}
2341+
appendWhereClause(remote_conds,additional_conds,&context);
2342+
2343+
if (additional_conds!=NIL)
2344+
list_free_deep(additional_conds);
22032345

22042346
if (foreignrel->reloptkind==RELOPT_JOINREL)
22052347
deparseExplicitTargetList(returningList, true,retrieved_attrs,
@@ -2255,6 +2397,7 @@ deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root,
22552397
List**retrieved_attrs)
22562398
{
22572399
deparse_expr_cxtcontext;
2400+
List*additional_conds=NIL;
22582401

22592402
/* Set up context struct for recursion */
22602403
context.root=root;
@@ -2274,15 +2417,14 @@ deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root,
22742417

22752418
appendStringInfoString(buf," USING ");
22762419
deparseFromExprForRel(buf,root,foreignrel, true,rtindex,
2277-
&ignore_conds,params_list);
2420+
&ignore_conds,&additional_conds,params_list);
22782421
remote_conds=list_concat(remote_conds,ignore_conds);
22792422
}
22802423

2281-
if (remote_conds)
2282-
{
2283-
appendStringInfoString(buf," WHERE ");
2284-
appendConditions(remote_conds,&context);
2285-
}
2424+
appendWhereClause(remote_conds,additional_conds,&context);
2425+
2426+
if (additional_conds!=NIL)
2427+
list_free_deep(additional_conds);
22862428

22872429
if (foreignrel->reloptkind==RELOPT_JOINREL)
22882430
deparseExplicitTargetList(returningList, true,retrieved_attrs,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp