diff options
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r-- | src/backend/commands/explain.c | 70 |
1 files changed, 64 insertions, 6 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index f4cc90183a4..c5452e3cb6a 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -103,7 +103,8 @@ static void ExplainIndexScanDetails(Oid indexid, ScanDirection indexorderdir, static void ExplainScanTarget(Scan *plan, ExplainState *es); static void ExplainModifyTarget(ModifyTable *plan, ExplainState *es); static void ExplainTargetRel(Plan *plan, Index rti, ExplainState *es); -static void show_modifytable_info(ModifyTableState *mtstate, ExplainState *es); +static void show_modifytable_info(ModifyTableState *mtstate, List *ancestors, + ExplainState *es); static void ExplainMemberNodes(List *plans, PlanState **planstates, List *ancestors, ExplainState *es); static void ExplainSubPlans(List *plans, List *ancestors, @@ -744,6 +745,9 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used) case T_ModifyTable: *rels_used = bms_add_member(*rels_used, ((ModifyTable *) plan)->nominalRelation); + if (((ModifyTable *) plan)->exclRelRTI) + *rels_used = bms_add_member(*rels_used, + ((ModifyTable *) plan)->exclRelRTI); break; default: break; @@ -1466,7 +1470,8 @@ ExplainNode(PlanState *planstate, List *ancestors, planstate, es); break; case T_ModifyTable: - show_modifytable_info((ModifyTableState *) planstate, es); + show_modifytable_info((ModifyTableState *) planstate, ancestors, + es); break; case T_Hash: show_hash_info((HashState *) planstate, es); @@ -2317,18 +2322,22 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es) /* * Show extra information for a ModifyTable node * - * We have two objectives here. First, if there's more than one target table - * or it's different from the nominal target, identify the actual target(s). - * Second, give FDWs a chance to display extra info about foreign targets. + * We have three objectives here. First, if there's more than one target + * table or it's different from the nominal target, identify the actual + * target(s). Second, give FDWs a chance to display extra info about foreign + * targets. Third, show information about ON CONFLICT. */ static void -show_modifytable_info(ModifyTableState *mtstate, ExplainState *es) +show_modifytable_info(ModifyTableState *mtstate, List *ancestors, + ExplainState *es) { ModifyTable *node = (ModifyTable *) mtstate->ps.plan; const char *operation; const char *foperation; bool labeltargets; int j; + List *idxNames = NIL; + ListCell *lst; switch (node->operation) { @@ -2414,6 +2423,55 @@ show_modifytable_info(ModifyTableState *mtstate, ExplainState *es) } } + /* Gather names of ON CONFLICT arbiter indexes */ + foreach(lst, node->arbiterIndexes) + { + char *indexname = get_rel_name(lfirst_oid(lst)); + + idxNames = lappend(idxNames, indexname); + } + + if (node->onConflictAction != ONCONFLICT_NONE) + { + ExplainProperty("Conflict Resolution", + node->onConflictAction == ONCONFLICT_NOTHING ? + "NOTHING" : "UPDATE", + false, es); + + /* + * Don't display arbiter indexes at all when DO NOTHING variant + * implicitly ignores all conflicts + */ + if (idxNames) + ExplainPropertyList("Conflict Arbiter Indexes", idxNames, es); + + /* ON CONFLICT DO UPDATE WHERE qual is specially displayed */ + if (node->onConflictWhere) + { + show_upper_qual((List *) node->onConflictWhere, "Conflict Filter", + &mtstate->ps, ancestors, es); + show_instrumentation_count("Rows Removed by Conflict Filter", 1, &mtstate->ps, es); + } + + /* EXPLAIN ANALYZE display of actual outcome for each tuple proposed */ + if (es->analyze && mtstate->ps.instrument) + { + double total; + double insert_path; + double other_path; + + InstrEndLoop(mtstate->mt_plans[0]->instrument); + + /* count the number of source rows */ + total = mtstate->mt_plans[0]->instrument->ntuples; + other_path = mtstate->ps.instrument->nfiltered2; + insert_path = total - other_path; + + ExplainPropertyFloat("Tuples Inserted", insert_path, 0, es); + ExplainPropertyFloat("Conflicting Tuples", other_path, 0, es); + } + } + if (labeltargets) ExplainCloseGroup("Target Tables", "Target Tables", false, es); } |