Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a2b91d2

Browse files
author
Commitfest Bot
committed
[CF 5470] Function scan FDW pushdown
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5470 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/a7f8c4dc2cede1054229c13769a1ba93@postgrespro.ru Author(s): Alexander Pyhalov, Gleb Kashkin
2 parents 65db396 + a34e6f7 commit a2b91d2

File tree

9 files changed

+1046
-105
lines changed

9 files changed

+1046
-105
lines changed

contrib/postgres_fdw/deparse.c

Lines changed: 142 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ static void deparseConst(Const *node, deparse_expr_cxt *context, int showtype);
153153
static void deparseParam(Param *node, deparse_expr_cxt *context);
154154
static void deparseSubscriptingRef(SubscriptingRef *node, deparse_expr_cxt *context);
155155
static void deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context);
156+
static void deparseFuncColnames(StringInfo buf, int varno, RangeTblEntry *rte, bool qualify_col);
156157
static void deparseOpExpr(OpExpr *node, deparse_expr_cxt *context);
157158
static bool isPlainForeignVar(Expr *node, deparse_expr_cxt *context);
158159
static void deparseOperatorName(StringInfo buf, Form_pg_operator opform);
@@ -1977,23 +1978,98 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
19771978
{
19781979
RangeTblEntry *rte = planner_rt_fetch(foreignrel->relid, root);
19791980

1980-
/*
1981-
* Core code already has some lock on each rel being planned, so we
1982-
* can use NoLock here.
1983-
*/
1984-
Relation rel = table_open(rte->relid, NoLock);
1981+
Assert(rte->rtekind == RTE_RELATION || rte->rtekind == RTE_FUNCTION);
1982+
if (rte->rtekind == RTE_RELATION)
1983+
{
1984+
/*
1985+
* Core code already has some lock on each rel being planned, so
1986+
* we can use NoLock here.
1987+
*/
1988+
Relation rel = table_open(rte->relid, NoLock);
19851989

1986-
deparseRelation(buf, rel);
1990+
deparseRelation(buf, rel);
1991+
1992+
table_close(rel, NoLock);
1993+
}
1994+
else if (rte->rtekind == RTE_FUNCTION)
1995+
{
1996+
RangeTblFunction *rtfunc;
1997+
deparse_expr_cxt context;
1998+
ListCell *lc;
1999+
bool first = true;
2000+
int n;
2001+
2002+
n = list_length(rte->functions);
2003+
Assert(n >= 1);
2004+
2005+
if (n > 1)
2006+
appendStringInfoString(buf, "ROWS FROM (");
2007+
2008+
foreach(lc, rte->functions)
2009+
{
2010+
if (!first)
2011+
appendStringInfoString(buf, ", ");
2012+
else
2013+
first = false;
2014+
2015+
rtfunc = (RangeTblFunction *) lfirst(lc);
2016+
2017+
context.root = root;
2018+
context.foreignrel = foreignrel;
2019+
context.scanrel = foreignrel;
2020+
context.buf = buf;
2021+
context.params_list = params_list;
2022+
2023+
deparseExpr((Expr *) rtfunc->funcexpr, &context);
2024+
}
2025+
2026+
if (n > 1)
2027+
appendStringInfoString(buf, ")");
2028+
}
19872029

19882030
/*
19892031
* Add a unique alias to avoid any conflict in relation names due to
19902032
* pulled up subqueries in the query being built for a pushed down
19912033
* join.
19922034
*/
19932035
if (use_alias)
2036+
{
19942037
appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, foreignrel->relid);
2038+
if (rte->rtekind == RTE_FUNCTION)
2039+
{
2040+
appendStringInfo(buf, " (");
2041+
deparseFuncColnames(buf, 0, rte, false);
2042+
appendStringInfo(buf, ") ");
2043+
}
2044+
}
2045+
}
2046+
}
19952047

1996-
table_close(rel, NoLock);
2048+
/*
2049+
* Deparse function columns alias list
2050+
*/
2051+
static void
2052+
deparseFuncColnames(StringInfo buf, int varno, RangeTblEntry *rte, bool qualify_col)
2053+
{
2054+
bool first = true;
2055+
ListCell *lc;
2056+
2057+
Assert(rte);
2058+
Assert(rte->rtekind == RTE_FUNCTION);
2059+
Assert(rte->eref);
2060+
2061+
foreach(lc, rte->eref->colnames)
2062+
{
2063+
char *colname = strVal(lfirst(lc));
2064+
2065+
if (colname[0] == '\0')
2066+
continue;
2067+
if (!first)
2068+
appendStringInfoString(buf, ",");
2069+
if (qualify_col)
2070+
ADD_REL_QUALIFIER(buf, varno);
2071+
appendStringInfoString(buf, quote_identifier(colname));
2072+
first = false;
19972073
}
19982074
}
19992075

@@ -2717,23 +2793,6 @@ deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte,
27172793
/* Required only to be passed down to deparseTargetList(). */
27182794
List *retrieved_attrs;
27192795

2720-
/*
2721-
* The lock on the relation will be held by upper callers, so it's
2722-
* fine to open it with no lock here.
2723-
*/
2724-
rel = table_open(rte->relid, NoLock);
2725-
2726-
/*
2727-
* The local name of the foreign table can not be recognized by the
2728-
* foreign server and the table it references on foreign server might
2729-
* have different column ordering or different columns than those
2730-
* declared locally. Hence we have to deparse whole-row reference as
2731-
* ROW(columns referenced locally). Construct this by deparsing a
2732-
* "whole row" attribute.
2733-
*/
2734-
attrs_used = bms_add_member(NULL,
2735-
0 - FirstLowInvalidHeapAttributeNumber);
2736-
27372796
/*
27382797
* In case the whole-row reference is under an outer join then it has
27392798
* to go NULL whenever the rest of the row goes NULL. Deparsing a join
@@ -2748,16 +2807,43 @@ deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte,
27482807
}
27492808

27502809
appendStringInfoString(buf, "ROW(");
2751-
deparseTargetList(buf, rte, varno, rel, false, attrs_used, qualify_col,
2752-
&retrieved_attrs);
2810+
if (rte->rtekind == RTE_RELATION)
2811+
{
2812+
/*
2813+
* The local name of the foreign table can not be recognized by
2814+
* the foreign server and the table it references on foreign
2815+
* server might have different column ordering or different
2816+
* columns than those declared locally. Hence we have to deparse
2817+
* whole-row reference as ROW(columns referenced locally).
2818+
* Construct this by deparsing a "whole row" attribute.
2819+
*/
2820+
attrs_used = bms_add_member(NULL,
2821+
0 - FirstLowInvalidHeapAttributeNumber);
2822+
2823+
/*
2824+
* The lock on the relation will be held by upper callers, so it's
2825+
* fine to open it with no lock here.
2826+
*/
2827+
rel = table_open(rte->relid, NoLock);
2828+
deparseTargetList(buf, rte, varno, rel, false, attrs_used, qualify_col,
2829+
&retrieved_attrs);
2830+
table_close(rel, NoLock);
2831+
bms_free(attrs_used);
2832+
}
2833+
else if (rte->rtekind == RTE_FUNCTION)
2834+
{
2835+
/*
2836+
* Function call is translated as-is, function returns the same
2837+
* columns in the same order as on local server
2838+
*/
2839+
deparseFuncColnames(buf, varno, rte, qualify_col);
2840+
}
27532841
appendStringInfoChar(buf, ')');
27542842

27552843
/* Complete the CASE WHEN statement started above. */
27562844
if (qualify_col)
27572845
appendStringInfoString(buf, " END");
27582846

2759-
table_close(rel, NoLock);
2760-
bms_free(attrs_used);
27612847
}
27622848
else
27632849
{
@@ -2772,29 +2858,40 @@ deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte,
27722858
* If it's a column of a foreign table, and it has the column_name FDW
27732859
* option, use that value.
27742860
*/
2775-
options = GetForeignColumnOptions(rte->relid, varattno);
2776-
foreach(lc, options)
2861+
if (rte->rtekind == RTE_RELATION)
27772862
{
2778-
DefElem *def = (DefElem *) lfirst(lc);
2779-
2780-
if (strcmp(def->defname, "column_name") == 0)
2863+
options = GetForeignColumnOptions(rte->relid, varattno);
2864+
foreach(lc, options)
27812865
{
2782-
colname = defGetString(def);
2783-
break;
2866+
DefElem *def = (DefElem *) lfirst(lc);
2867+
2868+
if (strcmp(def->defname, "column_name") == 0)
2869+
{
2870+
colname = defGetString(def);
2871+
break;
2872+
}
27842873
}
2785-
}
27862874

2787-
/*
2788-
* If it's a column of a regular table or it doesn't have column_name
2789-
* FDW option, use attribute name.
2790-
*/
2791-
if (colname == NULL)
2792-
colname = get_attname(rte->relid, varattno, false);
2875+
/*
2876+
* If it's a column of a regular table or it doesn't have
2877+
* column_name FDW option, use attribute name.
2878+
*/
2879+
if (colname == NULL)
2880+
colname = get_attname(rte->relid, varattno, false);
27932881

2794-
if (qualify_col)
2795-
ADD_REL_QUALIFIER(buf, varno);
2882+
if (qualify_col)
2883+
ADD_REL_QUALIFIER(buf, varno);
27962884

2797-
appendStringInfoString(buf, quote_identifier(colname));
2885+
appendStringInfoString(buf, quote_identifier(colname));
2886+
}
2887+
else if (rte->rtekind == RTE_FUNCTION)
2888+
{
2889+
colname = get_rte_attribute_name(rte, varattno);
2890+
2891+
if (qualify_col)
2892+
ADD_REL_QUALIFIER(buf, varno);
2893+
appendStringInfoString(buf, quote_identifier(colname));
2894+
}
27982895
}
27992896
}
28002897

0 commit comments

Comments
 (0)