Skip to content

Commit 0bf3ae8

Browse files
committed
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.
1 parent 3422fec commit 0bf3ae8

File tree

21 files changed

+1515
-125
lines changed

21 files changed

+1515
-125
lines changed

contrib/postgres_fdw/deparse.c

+100
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,69 @@ deparseUpdateSql(StringInfo buf, PlannerInfo *root,
13141314
returningList, retrieved_attrs);
13151315
}
13161316

1317+
/*
1318+
* deparse remote UPDATE statement
1319+
*
1320+
* The statement text is appended to buf, and we also create an integer List
1321+
* of the columns being retrieved by RETURNING (if any), which is returned
1322+
* to *retrieved_attrs.
1323+
*/
1324+
void
1325+
deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
1326+
Index rtindex, Relation rel,
1327+
List *targetlist,
1328+
List *targetAttrs,
1329+
List *remote_conds,
1330+
List **params_list,
1331+
List *returningList,
1332+
List **retrieved_attrs)
1333+
{
1334+
RelOptInfo *baserel = root->simple_rel_array[rtindex];
1335+
deparse_expr_cxt context;
1336+
int nestlevel;
1337+
bool first;
1338+
ListCell *lc;
1339+
1340+
/* Set up context struct for recursion */
1341+
context.root = root;
1342+
context.foreignrel = baserel;
1343+
context.buf = buf;
1344+
context.params_list = params_list;
1345+
1346+
appendStringInfoString(buf, "UPDATE ");
1347+
deparseRelation(buf, rel);
1348+
appendStringInfoString(buf, " SET ");
1349+
1350+
/* Make sure any constants in the exprs are printed portably */
1351+
nestlevel = set_transmission_modes();
1352+
1353+
first = true;
1354+
foreach(lc, targetAttrs)
1355+
{
1356+
int attnum = lfirst_int(lc);
1357+
TargetEntry *tle = get_tle_by_resno(targetlist, attnum);
1358+
1359+
if (!first)
1360+
appendStringInfoString(buf, ", ");
1361+
first = false;
1362+
1363+
deparseColumnRef(buf, rtindex, attnum, root, false);
1364+
appendStringInfoString(buf, " = ");
1365+
deparseExpr((Expr *) tle->expr, &context);
1366+
}
1367+
1368+
reset_transmission_modes(nestlevel);
1369+
1370+
if (remote_conds)
1371+
{
1372+
appendStringInfo(buf, " WHERE ");
1373+
appendConditions(remote_conds, &context);
1374+
}
1375+
1376+
deparseReturningList(buf, root, rtindex, rel, false,
1377+
returningList, retrieved_attrs);
1378+
}
1379+
13171380
/*
13181381
* deparse remote DELETE statement
13191382
*
@@ -1336,6 +1399,43 @@ deparseDeleteSql(StringInfo buf, PlannerInfo *root,
13361399
returningList, retrieved_attrs);
13371400
}
13381401

1402+
/*
1403+
* deparse remote DELETE statement
1404+
*
1405+
* The statement text is appended to buf, and we also create an integer List
1406+
* of the columns being retrieved by RETURNING (if any), which is returned
1407+
* to *retrieved_attrs.
1408+
*/
1409+
void
1410+
deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root,
1411+
Index rtindex, Relation rel,
1412+
List *remote_conds,
1413+
List **params_list,
1414+
List *returningList,
1415+
List **retrieved_attrs)
1416+
{
1417+
RelOptInfo *baserel = root->simple_rel_array[rtindex];
1418+
deparse_expr_cxt context;
1419+
1420+
/* Set up context struct for recursion */
1421+
context.root = root;
1422+
context.foreignrel = baserel;
1423+
context.buf = buf;
1424+
context.params_list = params_list;
1425+
1426+
appendStringInfoString(buf, "DELETE FROM ");
1427+
deparseRelation(buf, rel);
1428+
1429+
if (remote_conds)
1430+
{
1431+
appendStringInfo(buf, " WHERE ");
1432+
appendConditions(remote_conds, &context);
1433+
}
1434+
1435+
deparseReturningList(buf, root, rtindex, rel, false,
1436+
returningList, retrieved_attrs);
1437+
}
1438+
13391439
/*
13401440
* Add a RETURNING clause, if needed, to an INSERT/UPDATE/DELETE.
13411441
*/

0 commit comments

Comments
 (0)