summaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/plan/createplan.c18
-rw-r--r--src/backend/optimizer/util/plancat.c54
2 files changed, 70 insertions, 2 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index f23326a1c51..752a7a9a67b 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -6989,6 +6989,8 @@ make_modifytable(PlannerInfo *root, Plan *subplan,
List *mergeActionLists, int epqParam)
{
ModifyTable *node = makeNode(ModifyTable);
+ bool transition_tables = false;
+ bool transition_tables_valid = false;
List *fdw_private_list;
Bitmapset *direct_modify_plans;
ListCell *lc;
@@ -7134,7 +7136,7 @@ make_modifytable(PlannerInfo *root, Plan *subplan,
* callback functions needed for that and (2) there are no local
* structures that need to be run for each modified row: row-level
* triggers on the foreign table, stored generated columns, WITH CHECK
- * OPTIONs from parent views.
+ * OPTIONs from parent views, transition tables on the named relation.
*/
direct_modify = false;
if (fdwroutine != NULL &&
@@ -7145,7 +7147,19 @@ make_modifytable(PlannerInfo *root, Plan *subplan,
withCheckOptionLists == NIL &&
!has_row_triggers(root, rti, operation) &&
!has_stored_generated_columns(root, rti))
- direct_modify = fdwroutine->PlanDirectModify(root, node, rti, i);
+ {
+ /* transition_tables is the same for all result relations */
+ if (!transition_tables_valid)
+ {
+ transition_tables = has_transition_tables(root,
+ nominalRelation,
+ operation);
+ transition_tables_valid = true;
+ }
+ if (!transition_tables)
+ direct_modify = fdwroutine->PlanDirectModify(root, node,
+ rti, i);
+ }
if (direct_modify)
direct_modify_plans = bms_add_member(direct_modify_plans, i);
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 7d2f403212f..002cea0c116 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -2218,6 +2218,60 @@ has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
}
/*
+ * has_transition_tables
+ *
+ * Detect whether the specified relation has any transition tables for event.
+ */
+bool
+has_transition_tables(PlannerInfo *root, Index rti, CmdType event)
+{
+ RangeTblEntry *rte = planner_rt_fetch(rti, root);
+ Relation relation;
+ TriggerDesc *trigDesc;
+ bool result = false;
+
+ Assert(rte->rtekind == RTE_RELATION);
+
+ /* Currently foreign tables cannot have transition tables */
+ if (rte->relkind == RELKIND_FOREIGN_TABLE)
+ return result;
+
+ /* Assume we already have adequate lock */
+ relation = table_open(rte->relid, NoLock);
+
+ trigDesc = relation->trigdesc;
+ switch (event)
+ {
+ case CMD_INSERT:
+ if (trigDesc &&
+ trigDesc->trig_insert_new_table)
+ result = true;
+ break;
+ case CMD_UPDATE:
+ if (trigDesc &&
+ (trigDesc->trig_update_old_table ||
+ trigDesc->trig_update_new_table))
+ result = true;
+ break;
+ case CMD_DELETE:
+ if (trigDesc &&
+ trigDesc->trig_delete_old_table)
+ result = true;
+ break;
+ /* There is no separate event for MERGE, only INSERT/UPDATE/DELETE */
+ case CMD_MERGE:
+ result = false;
+ break;
+ default:
+ elog(ERROR, "unrecognized CmdType: %d", (int) event);
+ break;
+ }
+
+ table_close(relation, NoLock);
+ return result;
+}
+
+/*
* has_stored_generated_columns
*
* Does table identified by RTI have any STORED GENERATED columns?