On Fri, May 08, 2020 at 02:25:45AM -0500, Justin Pryzby wrote: > Seems to me it should, at least conditionally. At least if there's a function > scan or a relation or .. > > I mentioned a bit about our use-case here: > https://www.postgresql.org/message-id/20200219173742.GA30939%40telsasoft.com > => I'd prefer our loaders to write their own data rather than dirtying large > fractions of buffer cache and leaving it around for other backends to clean > up.
Nobody suggested otherwise so I added here and cleaned up to pass tests. https://commitfest.postgresql.org/28/2553/ -- Justin
>From ba5cf05960a097cf82c10a29af81f4f66a9274a6 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryz...@telsasoft.com> Date: Fri, 8 May 2020 02:17:32 -0500 Subject: [PATCH v1] Make INSERT SELECT use a BulkInsertState --- src/backend/executor/nodeModifyTable.c | 21 +++++++++++++++++++-- src/include/nodes/execnodes.h | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 20a4c474cc..aa85245f39 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -578,7 +578,7 @@ ExecInsert(ModifyTableState *mtstate, table_tuple_insert_speculative(resultRelationDesc, slot, estate->es_output_cid, 0, - NULL, + NULL, /* Bulk insert not supported */ specToken); /* insert index entries for tuple */ @@ -617,7 +617,7 @@ ExecInsert(ModifyTableState *mtstate, /* insert the tuple normally */ table_tuple_insert(resultRelationDesc, slot, estate->es_output_cid, - 0, NULL); + 0, mtstate->bistate); /* insert index entries for tuple */ if (resultRelInfo->ri_NumIndices > 0) @@ -2332,6 +2332,17 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) mtstate->mt_arowmarks = (List **) palloc0(sizeof(List *) * nplans); mtstate->mt_nplans = nplans; + mtstate->bistate = NULL; + if (operation == CMD_INSERT && + node->onConflictAction != ONCONFLICT_UPDATE && + node->rootResultRelIndex < 0) + { + Plan *p = linitial(node->plans); + Assert(nplans == 1); + + if (!IsA(p, Result) && !IsA(p, ProjectSet) && !IsA(p, ValuesScan)) + mtstate->bistate = GetBulkInsertState(); + } /* set up epqstate with dummy subplan data for the moment */ EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL, node->epqParam); @@ -2776,6 +2787,12 @@ ExecEndModifyTable(ModifyTableState *node) resultRelInfo); } + if (node->bistate) + { + FreeBulkInsertState(node->bistate); + table_finish_bulk_insert((getTargetResultRelInfo(node))->ri_RelationDesc, 0); + } + /* * Close all the partitioned tables, leaf partitions, and their indices * and release the slot used for tuple routing, if set. diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 4fee043bb2..daf365f181 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -14,6 +14,7 @@ #ifndef EXECNODES_H #define EXECNODES_H +#include "access/heapam.h" #include "access/tupconvert.h" #include "executor/instrument.h" #include "fmgr.h" @@ -1177,6 +1178,7 @@ typedef struct ModifyTableState List **mt_arowmarks; /* per-subplan ExecAuxRowMark lists */ EPQState mt_epqstate; /* for evaluating EvalPlanQual rechecks */ bool fireBSTriggers; /* do we need to fire stmt triggers? */ + BulkInsertState bistate; /* State for bulk insert like INSERT SELECT */ /* * Slot for storing tuples in the root partitioned table's rowtype during -- 2.17.0