mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
Fix contrib/postgres_fdw's handling of column defaults.
Adopt the position that only locally-defined defaults matter. Any defaults defined in the remote database do not affect insertions performed through a foreign table (unless they are for columns not known to the foreign table). While it'd arguably be more useful to permit remote defaults to be used, making that work in a consistent fashion requires far more work than seems possible for 9.3.
This commit is contained in:
@ -1023,6 +1023,8 @@ postgresPlanForeignModify(PlannerInfo *root,
|
||||
int subplan_index)
|
||||
{
|
||||
CmdType operation = plan->operation;
|
||||
RangeTblEntry *rte = planner_rt_fetch(resultRelation, root);
|
||||
Relation rel;
|
||||
StringInfoData sql;
|
||||
List *targetAttrs = NIL;
|
||||
List *returningList = NIL;
|
||||
@ -1030,15 +1032,33 @@ postgresPlanForeignModify(PlannerInfo *root,
|
||||
initStringInfo(&sql);
|
||||
|
||||
/*
|
||||
* Construct a list of the columns that are to be assigned during INSERT
|
||||
* or UPDATE. We should transmit only these columns, for performance and
|
||||
* to respect any DEFAULT values the remote side may have for other
|
||||
* columns. (XXX this will need some re-thinking when we support default
|
||||
* expressions for foreign tables.)
|
||||
* Core code already has some lock on each rel being planned, so we can
|
||||
* use NoLock here.
|
||||
*/
|
||||
if (operation == CMD_INSERT || operation == CMD_UPDATE)
|
||||
rel = heap_open(rte->relid, NoLock);
|
||||
|
||||
/*
|
||||
* In an INSERT, we transmit all columns that are defined in the foreign
|
||||
* table. In an UPDATE, we transmit only columns that were explicitly
|
||||
* targets of the UPDATE, so as to avoid unnecessary data transmission.
|
||||
* (We can't do that for INSERT since we would miss sending default values
|
||||
* for columns not listed in the source statement.)
|
||||
*/
|
||||
if (operation == CMD_INSERT)
|
||||
{
|
||||
TupleDesc tupdesc = RelationGetDescr(rel);
|
||||
int attnum;
|
||||
|
||||
for (attnum = 1; attnum <= tupdesc->natts; attnum++)
|
||||
{
|
||||
Form_pg_attribute attr = tupdesc->attrs[attnum - 1];
|
||||
|
||||
if (!attr->attisdropped)
|
||||
targetAttrs = lappend_int(targetAttrs, attnum);
|
||||
}
|
||||
}
|
||||
else if (operation == CMD_UPDATE)
|
||||
{
|
||||
RangeTblEntry *rte = planner_rt_fetch(resultRelation, root);
|
||||
Bitmapset *tmpset = bms_copy(rte->modifiedCols);
|
||||
AttrNumber col;
|
||||
|
||||
@ -1063,21 +1083,24 @@ postgresPlanForeignModify(PlannerInfo *root,
|
||||
switch (operation)
|
||||
{
|
||||
case CMD_INSERT:
|
||||
deparseInsertSql(&sql, root, resultRelation,
|
||||
deparseInsertSql(&sql, root, resultRelation, rel,
|
||||
targetAttrs, returningList);
|
||||
break;
|
||||
case CMD_UPDATE:
|
||||
deparseUpdateSql(&sql, root, resultRelation,
|
||||
deparseUpdateSql(&sql, root, resultRelation, rel,
|
||||
targetAttrs, returningList);
|
||||
break;
|
||||
case CMD_DELETE:
|
||||
deparseDeleteSql(&sql, root, resultRelation, returningList);
|
||||
deparseDeleteSql(&sql, root, resultRelation, rel,
|
||||
returningList);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unexpected operation: %d", (int) operation);
|
||||
break;
|
||||
}
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
|
||||
/*
|
||||
* Build the fdw_private list that will be available to the executor.
|
||||
* Items in the list must match enum FdwModifyPrivateIndex, above.
|
||||
|
Reference in New Issue
Block a user