aboutsummaryrefslogtreecommitdiff
path: root/contrib/postgres_fdw/deparse.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2018-05-01 13:21:46 -0400
committerRobert Haas <rhaas@postgresql.org>2018-05-01 13:21:46 -0400
commit37a3058bc7c8224d4c0d8b36176d821636a1f90e (patch)
tree1410ad72fa6d03214b0354a904a75b283c22998a /contrib/postgres_fdw/deparse.c
parent6594ee280383b7548b006e7f96c8d06137fced57 (diff)
downloadpostgresql-37a3058bc7c8224d4c0d8b36176d821636a1f90e.tar.gz
postgresql-37a3058bc7c8224d4c0d8b36176d821636a1f90e.zip
Fix interaction of foreign tuple routing with remote triggers.
Without these fixes, changes to the inserted tuple made by remote triggers are ignored when building local RETURNING tuples. In the core code, call ExecInitRoutingInfo at a later point from within ExecInitPartitionInfo so that the FDW callback gets invoked after the returning list has been built. But move CheckValidResultRel out of ExecInitRoutingInfo so that it can happen at an earlier stage. In postgres_fdw, refactor assorted deparsing functions to work with the RTE rather than the PlannerInfo, which saves us having to construct a fake PlannerInfo in cases where we don't have a real one. Then, we can pass down a constructed RTE that yields the correct deparse result when no real one exists. Unfortunately, this necessitates a hack that understands how the core code manages RT indexes for update tuple routing, which is ugly, but we don't have a better idea right now. Original report, analysis, and patch by Etsuro Fujita. Heavily refactored by me. Then worked over some more by Amit Langote. Discussion: http://postgr.es/m/5AD4882B.10002@lab.ntt.co.jp
Diffstat (limited to 'contrib/postgres_fdw/deparse.c')
-rw-r--r--contrib/postgres_fdw/deparse.c58
1 files changed, 25 insertions, 33 deletions
diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c
index 6e2fa1420c4..d272719ff48 100644
--- a/contrib/postgres_fdw/deparse.c
+++ b/contrib/postgres_fdw/deparse.c
@@ -125,7 +125,7 @@ static char *deparse_type_name(Oid type_oid, int32 typemod);
* Functions to construct string representation of a node tree.
*/
static void deparseTargetList(StringInfo buf,
- PlannerInfo *root,
+ RangeTblEntry *rte,
Index rtindex,
Relation rel,
bool is_returning,
@@ -137,13 +137,13 @@ static void deparseExplicitTargetList(List *tlist,
List **retrieved_attrs,
deparse_expr_cxt *context);
static void deparseSubqueryTargetList(deparse_expr_cxt *context);
-static void deparseReturningList(StringInfo buf, PlannerInfo *root,
+static void deparseReturningList(StringInfo buf, RangeTblEntry *rte,
Index rtindex, Relation rel,
bool trig_after_row,
List *returningList,
List **retrieved_attrs);
static void deparseColumnRef(StringInfo buf, int varno, int varattno,
- PlannerInfo *root, bool qualify_col);
+ RangeTblEntry *rte, bool qualify_col);
static void deparseRelation(StringInfo buf, Relation rel);
static void deparseExpr(Expr *expr, deparse_expr_cxt *context);
static void deparseVar(Var *node, deparse_expr_cxt *context);
@@ -1050,7 +1050,7 @@ deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs,
*/
Relation rel = heap_open(rte->relid, NoLock);
- deparseTargetList(buf, root, foreignrel->relid, rel, false,
+ deparseTargetList(buf, rte, foreignrel->relid, rel, false,
fpinfo->attrs_used, false, retrieved_attrs);
heap_close(rel, NoLock);
}
@@ -1099,7 +1099,7 @@ deparseFromExpr(List *quals, deparse_expr_cxt *context)
*/
static void
deparseTargetList(StringInfo buf,
- PlannerInfo *root,
+ RangeTblEntry *rte,
Index rtindex,
Relation rel,
bool is_returning,
@@ -1137,7 +1137,7 @@ deparseTargetList(StringInfo buf,
appendStringInfoString(buf, " RETURNING ");
first = false;
- deparseColumnRef(buf, rtindex, i, root, qualify_col);
+ deparseColumnRef(buf, rtindex, i, rte, qualify_col);
*retrieved_attrs = lappend_int(*retrieved_attrs, i);
}
@@ -1649,7 +1649,7 @@ deparseRangeTblRef(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
* to *retrieved_attrs.
*/
void
-deparseInsertSql(StringInfo buf, PlannerInfo *root,
+deparseInsertSql(StringInfo buf, RangeTblEntry *rte,
Index rtindex, Relation rel,
List *targetAttrs, bool doNothing,
List *returningList, List **retrieved_attrs)
@@ -1674,7 +1674,7 @@ deparseInsertSql(StringInfo buf, PlannerInfo *root,
appendStringInfoString(buf, ", ");
first = false;
- deparseColumnRef(buf, rtindex, attnum, root, false);
+ deparseColumnRef(buf, rtindex, attnum, rte, false);
}
appendStringInfoString(buf, ") VALUES (");
@@ -1699,7 +1699,7 @@ deparseInsertSql(StringInfo buf, PlannerInfo *root,
if (doNothing)
appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
- deparseReturningList(buf, root, rtindex, rel,
+ deparseReturningList(buf, rte, rtindex, rel,
rel->trigdesc && rel->trigdesc->trig_insert_after_row,
returningList, retrieved_attrs);
}
@@ -1712,7 +1712,7 @@ deparseInsertSql(StringInfo buf, PlannerInfo *root,
* to *retrieved_attrs.
*/
void
-deparseUpdateSql(StringInfo buf, PlannerInfo *root,
+deparseUpdateSql(StringInfo buf, RangeTblEntry *rte,
Index rtindex, Relation rel,
List *targetAttrs, List *returningList,
List **retrieved_attrs)
@@ -1735,13 +1735,13 @@ deparseUpdateSql(StringInfo buf, PlannerInfo *root,
appendStringInfoString(buf, ", ");
first = false;
- deparseColumnRef(buf, rtindex, attnum, root, false);
+ deparseColumnRef(buf, rtindex, attnum, rte, false);
appendStringInfo(buf, " = $%d", pindex);
pindex++;
}
appendStringInfoString(buf, " WHERE ctid = $1");
- deparseReturningList(buf, root, rtindex, rel,
+ deparseReturningList(buf, rte, rtindex, rel,
rel->trigdesc && rel->trigdesc->trig_update_after_row,
returningList, retrieved_attrs);
}
@@ -1777,6 +1777,7 @@ deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
int nestlevel;
bool first;
ListCell *lc;
+ RangeTblEntry *rte = planner_rt_fetch(rtindex, root);
/* Set up context struct for recursion */
context.root = root;
@@ -1808,7 +1809,7 @@ deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
appendStringInfoString(buf, ", ");
first = false;
- deparseColumnRef(buf, rtindex, attnum, root, false);
+ deparseColumnRef(buf, rtindex, attnum, rte, false);
appendStringInfoString(buf, " = ");
deparseExpr((Expr *) tle->expr, &context);
}
@@ -1835,7 +1836,7 @@ deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
deparseExplicitTargetList(returningList, true, retrieved_attrs,
&context);
else
- deparseReturningList(buf, root, rtindex, rel, false,
+ deparseReturningList(buf, rte, rtindex, rel, false,
returningList, retrieved_attrs);
}
@@ -1847,7 +1848,7 @@ deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
* to *retrieved_attrs.
*/
void
-deparseDeleteSql(StringInfo buf, PlannerInfo *root,
+deparseDeleteSql(StringInfo buf, RangeTblEntry *rte,
Index rtindex, Relation rel,
List *returningList,
List **retrieved_attrs)
@@ -1856,7 +1857,7 @@ deparseDeleteSql(StringInfo buf, PlannerInfo *root,
deparseRelation(buf, rel);
appendStringInfoString(buf, " WHERE ctid = $1");
- deparseReturningList(buf, root, rtindex, rel,
+ deparseReturningList(buf, rte, rtindex, rel,
rel->trigdesc && rel->trigdesc->trig_delete_after_row,
returningList, retrieved_attrs);
}
@@ -1918,7 +1919,8 @@ deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root,
deparseExplicitTargetList(returningList, true, retrieved_attrs,
&context);
else
- deparseReturningList(buf, root, rtindex, rel, false,
+ deparseReturningList(buf, planner_rt_fetch(rtindex, root),
+ rtindex, rel, false,
returningList, retrieved_attrs);
}
@@ -1926,7 +1928,7 @@ deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root,
* Add a RETURNING clause, if needed, to an INSERT/UPDATE/DELETE.
*/
static void
-deparseReturningList(StringInfo buf, PlannerInfo *root,
+deparseReturningList(StringInfo buf, RangeTblEntry *rte,
Index rtindex, Relation rel,
bool trig_after_row,
List *returningList,
@@ -1952,7 +1954,7 @@ deparseReturningList(StringInfo buf, PlannerInfo *root,
}
if (attrs_used != NULL)
- deparseTargetList(buf, root, rtindex, rel, true, attrs_used, false,
+ deparseTargetList(buf, rte, rtindex, rel, true, attrs_used, false,
retrieved_attrs);
else
*retrieved_attrs = NIL;
@@ -2048,11 +2050,9 @@ deparseAnalyzeSql(StringInfo buf, Relation rel, List **retrieved_attrs)
* If qualify_col is true, qualify column name with the alias of relation.
*/
static void
-deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root,
+deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte,
bool qualify_col)
{
- RangeTblEntry *rte;
-
/* We support fetching the remote side's CTID and OID. */
if (varattno == SelfItemPointerAttributeNumber)
{
@@ -2077,10 +2077,7 @@ deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root,
Oid fetchval = 0;
if (varattno == TableOidAttributeNumber)
- {
- rte = planner_rt_fetch(varno, root);
fetchval = rte->relid;
- }
if (qualify_col)
{
@@ -2100,9 +2097,6 @@ deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root,
/* Required only to be passed down to deparseTargetList(). */
List *retrieved_attrs;
- /* Get RangeTblEntry from array in PlannerInfo. */
- rte = planner_rt_fetch(varno, root);
-
/*
* The lock on the relation will be held by upper callers, so it's
* fine to open it with no lock here.
@@ -2134,7 +2128,7 @@ deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root,
}
appendStringInfoString(buf, "ROW(");
- deparseTargetList(buf, root, varno, rel, false, attrs_used, qualify_col,
+ deparseTargetList(buf, rte, varno, rel, false, attrs_used, qualify_col,
&retrieved_attrs);
appendStringInfoChar(buf, ')');
@@ -2154,9 +2148,6 @@ deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root,
/* varno must not be any of OUTER_VAR, INNER_VAR and INDEX_VAR. */
Assert(!IS_SPECIAL_VARNO(varno));
- /* Get RangeTblEntry from array in PlannerInfo. */
- rte = planner_rt_fetch(varno, root);
-
/*
* If it's a column of a foreign table, and it has the column_name FDW
* option, use that value.
@@ -2354,7 +2345,8 @@ deparseVar(Var *node, deparse_expr_cxt *context)
if (bms_is_member(node->varno, relids) && node->varlevelsup == 0)
deparseColumnRef(context->buf, node->varno, node->varattno,
- context->root, qualify_col);
+ planner_rt_fetch(node->varno, context->root),
+ qualify_col);
else
{
/* Treat like a Param */