1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Directly modify foreign tables.

postgres_fdw can now sent an UPDATE or DELETE statement directly to
the foreign server in simple cases, rather than sending a SELECT FOR
UPDATE statement and then updating or deleting rows one-by-one.

Etsuro Fujita, reviewed by Rushabh Lathia, Shigeru Hanada, Kyotaro
Horiguchi, Albe Laurenz, Thom Brown, and me.
This commit is contained in:
Robert Haas
2016-03-18 13:48:58 -04:00
parent 3422feccca
commit 0bf3ae88af
21 changed files with 1515 additions and 125 deletions

View File

@ -1314,6 +1314,69 @@ deparseUpdateSql(StringInfo buf, PlannerInfo *root,
returningList, retrieved_attrs);
}
/*
* deparse remote UPDATE statement
*
* The statement text is appended to buf, and we also create an integer List
* of the columns being retrieved by RETURNING (if any), which is returned
* to *retrieved_attrs.
*/
void
deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
Index rtindex, Relation rel,
List *targetlist,
List *targetAttrs,
List *remote_conds,
List **params_list,
List *returningList,
List **retrieved_attrs)
{
RelOptInfo *baserel = root->simple_rel_array[rtindex];
deparse_expr_cxt context;
int nestlevel;
bool first;
ListCell *lc;
/* Set up context struct for recursion */
context.root = root;
context.foreignrel = baserel;
context.buf = buf;
context.params_list = params_list;
appendStringInfoString(buf, "UPDATE ");
deparseRelation(buf, rel);
appendStringInfoString(buf, " SET ");
/* Make sure any constants in the exprs are printed portably */
nestlevel = set_transmission_modes();
first = true;
foreach(lc, targetAttrs)
{
int attnum = lfirst_int(lc);
TargetEntry *tle = get_tle_by_resno(targetlist, attnum);
if (!first)
appendStringInfoString(buf, ", ");
first = false;
deparseColumnRef(buf, rtindex, attnum, root, false);
appendStringInfoString(buf, " = ");
deparseExpr((Expr *) tle->expr, &context);
}
reset_transmission_modes(nestlevel);
if (remote_conds)
{
appendStringInfo(buf, " WHERE ");
appendConditions(remote_conds, &context);
}
deparseReturningList(buf, root, rtindex, rel, false,
returningList, retrieved_attrs);
}
/*
* deparse remote DELETE statement
*
@ -1336,6 +1399,43 @@ deparseDeleteSql(StringInfo buf, PlannerInfo *root,
returningList, retrieved_attrs);
}
/*
* deparse remote DELETE statement
*
* The statement text is appended to buf, and we also create an integer List
* of the columns being retrieved by RETURNING (if any), which is returned
* to *retrieved_attrs.
*/
void
deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root,
Index rtindex, Relation rel,
List *remote_conds,
List **params_list,
List *returningList,
List **retrieved_attrs)
{
RelOptInfo *baserel = root->simple_rel_array[rtindex];
deparse_expr_cxt context;
/* Set up context struct for recursion */
context.root = root;
context.foreignrel = baserel;
context.buf = buf;
context.params_list = params_list;
appendStringInfoString(buf, "DELETE FROM ");
deparseRelation(buf, rel);
if (remote_conds)
{
appendStringInfo(buf, " WHERE ");
appendConditions(remote_conds, &context);
}
deparseReturningList(buf, root, rtindex, rel, false,
returningList, retrieved_attrs);
}
/*
* Add a RETURNING clause, if needed, to an INSERT/UPDATE/DELETE.
*/