Let table AM insertion methods control index insertion
authorAlexander Korotkov <akorotkov@postgresql.org>
Sat, 30 Mar 2024 20:39:03 +0000 (22:39 +0200)
committerAlexander Korotkov <akorotkov@postgresql.org>
Sat, 30 Mar 2024 20:53:56 +0000 (22:53 +0200)
Previously, the executor did index insert unconditionally after calling
table AM interface methods tuple_insert() and multi_insert().  This commit
introduces the new parameter insert_indexes for these two methods.  Setting
'*insert_indexes' to true saves the current logic.  Setting it to false
indicates that table AM cares about index inserts itself and doesn't want the
caller to do that.

Discussion: https://postgr.es/m/CAPpHfdurb9ycV8udYqM%3Do0sPS66PJ4RCBM1g-bBpvzUfogY0EA%40mail.gmail.com
Reviewed-by: Pavel Borisov, Matthias van de Meent, Mark Dilger
12 files changed:
src/backend/access/heap/heapam.c
src/backend/access/heap/heapam_handler.c
src/backend/access/table/tableam.c
src/backend/catalog/indexing.c
src/backend/commands/copyfrom.c
src/backend/commands/createas.c
src/backend/commands/matview.c
src/backend/commands/tablecmds.c
src/backend/executor/execReplication.c
src/backend/executor/nodeModifyTable.c
src/include/access/heapam.h
src/include/access/tableam.h

index 2f6527df0dc2d9c2b23320def2e8e8aaf81e7f45..b661d9811eb6fbe4e19acd300585285ad858aea7 100644 (file)
@@ -2088,7 +2088,8 @@ heap_multi_insert_pages(HeapTuple *heaptuples, int done, int ntuples, Size saveF
  */
 void
 heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
-                                 CommandId cid, int options, BulkInsertState bistate)
+                                 CommandId cid, int options, BulkInsertState bistate,
+                                 bool *insert_indexes)
 {
        TransactionId xid = GetCurrentTransactionId();
        HeapTuple  *heaptuples;
@@ -2437,6 +2438,7 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
                slots[i]->tts_tid = heaptuples[i]->t_self;
 
        pgstat_count_heap_insert(relation, ntuples);
+       *insert_indexes = true;
 }
 
 /*
index 26b3be9779d0bfd50067481cd738eb174e679357..41a4bb0981dd06d561be205c430658e4ba6052ca 100644 (file)
@@ -245,7 +245,7 @@ heapam_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot,
 
 static TupleTableSlot *
 heapam_tuple_insert(Relation relation, TupleTableSlot *slot, CommandId cid,
-                                       int options, BulkInsertState bistate)
+                                       int options, BulkInsertState bistate, bool *insert_indexes)
 {
        bool            shouldFree = true;
        HeapTuple       tuple = ExecFetchSlotHeapTuple(slot, true, &shouldFree);
@@ -261,6 +261,8 @@ heapam_tuple_insert(Relation relation, TupleTableSlot *slot, CommandId cid,
        if (shouldFree)
                pfree(tuple);
 
+       *insert_indexes = true;
+
        return slot;
 }
 
index 8d3675be959c16486db3e9168013eac2e5705b19..805d222cebc466cc2d3da2d965656b61de9f51e4 100644 (file)
@@ -273,9 +273,11 @@ table_tuple_get_latest_tid(TableScanDesc scan, ItemPointer tid)
  * default command ID and not allowing access to the speedup options.
  */
 void
-simple_table_tuple_insert(Relation rel, TupleTableSlot *slot)
+simple_table_tuple_insert(Relation rel, TupleTableSlot *slot,
+                                                 bool *insert_indexes)
 {
-       table_tuple_insert(rel, slot, GetCurrentCommandId(true), 0, NULL);
+       table_tuple_insert(rel, slot, GetCurrentCommandId(true), 0, NULL,
+                                          insert_indexes);
 }
 
 /*
index d0d1abda58af3d6647b88e101e09e8b276b65af6..4d404f22f835f2a39f6385ef136ce0cfb822b8c6 100644 (file)
@@ -273,12 +273,14 @@ void
 CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot,
                                                                 int ntuples, CatalogIndexState indstate)
 {
+       bool            insertIndexes;
+
        /* Nothing to do */
        if (ntuples <= 0)
                return;
 
        heap_multi_insert(heapRel, slot, ntuples,
-                                         GetCurrentCommandId(true), 0, NULL);
+                                         GetCurrentCommandId(true), 0, NULL, &insertIndexes);
 
        /*
         * There is no equivalent to heap_multi_insert for the catalog indexes, so
index 8908a440e19a03cc72f3d0e5dd2b8760fa583489..b6736369771f1ca93537930ca21e7b88c7b3d861 100644 (file)
@@ -397,6 +397,7 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo,
                bool            line_buf_valid = cstate->line_buf_valid;
                uint64          save_cur_lineno = cstate->cur_lineno;
                MemoryContext oldcontext;
+               bool            insertIndexes;
 
                Assert(buffer->bistate != NULL);
 
@@ -416,7 +417,8 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo,
                                                   nused,
                                                   mycid,
                                                   ti_options,
-                                                  buffer->bistate);
+                                                  buffer->bistate,
+                                                  &insertIndexes);
                MemoryContextSwitchTo(oldcontext);
 
                for (i = 0; i < nused; i++)
@@ -425,7 +427,7 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo,
                         * If there are any indexes, update them for all the inserted
                         * tuples, and run AFTER ROW INSERT triggers.
                         */
-                       if (resultRelInfo->ri_NumIndices > 0)
+                       if (insertIndexes && resultRelInfo->ri_NumIndices > 0)
                        {
                                List       *recheckIndexes;
 
@@ -1265,11 +1267,14 @@ CopyFrom(CopyFromState cstate)
                                        }
                                        else
                                        {
+                                               bool            insertIndexes;
+
                                                /* OK, store the tuple and create index entries for it */
                                                table_tuple_insert(resultRelInfo->ri_RelationDesc,
-                                                                                  myslot, mycid, ti_options, bistate);
+                                                                                  myslot, mycid, ti_options, bistate,
+                                                                                  &insertIndexes);
 
-                                               if (resultRelInfo->ri_NumIndices > 0)
+                                               if (insertIndexes && resultRelInfo->ri_NumIndices > 0)
                                                        recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
                                                                                                                                   myslot,
                                                                                                                                   estate,
index 62050f4dc590b8a17326e64405562e91cc4923b9..afd3dace079e1bc1a7c6f2185a3304327cc798c1 100644 (file)
@@ -578,6 +578,7 @@ static bool
 intorel_receive(TupleTableSlot *slot, DestReceiver *self)
 {
        DR_intorel *myState = (DR_intorel *) self;
+       bool            insertIndexes;
 
        /* Nothing to insert if WITH NO DATA is specified. */
        if (!myState->into->skipData)
@@ -594,7 +595,8 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
                                                   slot,
                                                   myState->output_cid,
                                                   myState->ti_options,
-                                                  myState->bistate);
+                                                  myState->bistate,
+                                                  &insertIndexes);
        }
 
        /* We know this is a newly created relation, so there are no indexes */
index 6d09b755564e32bbe81bf1c3c3a59e29e4709a17..9ec13d098467d4417511af25145f98f9a6b5c61d 100644 (file)
@@ -476,6 +476,7 @@ static bool
 transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
 {
        DR_transientrel *myState = (DR_transientrel *) self;
+       bool            insertIndexes;
 
        /*
         * Note that the input slot might not be of the type of the target
@@ -490,7 +491,8 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
                                           slot,
                                           myState->output_cid,
                                           myState->ti_options,
-                                          myState->bistate);
+                                          myState->bistate,
+                                          &insertIndexes);
 
        /* We know this is a newly created relation, so there are no indexes */
 
index 3fcb9cd078340032aec834de304f7d174061bd88..a28f405e27fab7069e1949e65c3fdcd8e7dc311b 100644 (file)
@@ -6360,8 +6360,12 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
 
                        /* Write the tuple out to the new relation */
                        if (newrel)
+                       {
+                               bool            insertIndexes;
+
                                table_tuple_insert(newrel, insertslot, mycid,
-                                                                  ti_options, bistate);
+                                                                  ti_options, bistate, &insertIndexes);
+                       }
 
                        ResetExprContext(econtext);
 
index 0cad843fb6981acc9b951e1f81eaaa5048cfdf4d..db685473fc0debfb4b51df5f498ccdf9834e4d02 100644 (file)
@@ -509,6 +509,7 @@ ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo,
        if (!skip_tuple)
        {
                List       *recheckIndexes = NIL;
+               bool            insertIndexes;
 
                /* Compute stored generated columns */
                if (rel->rd_att->constr &&
@@ -523,9 +524,10 @@ ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo,
                        ExecPartitionCheck(resultRelInfo, slot, estate, true);
 
                /* OK, store the tuple and create index entries for it */
-               simple_table_tuple_insert(resultRelInfo->ri_RelationDesc, slot);
+               simple_table_tuple_insert(resultRelInfo->ri_RelationDesc, slot,
+                                                                 &insertIndexes);
 
-               if (resultRelInfo->ri_NumIndices > 0)
+               if (insertIndexes && resultRelInfo->ri_NumIndices > 0)
                        recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
                                                                                                   slot, estate, false, false,
                                                                                                   NULL, NIL, false);
index 325d380b0a97e4c4e5c4611afb6efd74902baf29..df63844b35013f48874ea3524866ecc92400c9f7 100644 (file)
@@ -1135,13 +1135,15 @@ ExecInsert(ModifyTableContext *context,
                }
                else
                {
+                       bool            insertIndexes;
+
                        /* insert the tuple normally */
                        slot = table_tuple_insert(resultRelationDesc, slot,
                                                                          estate->es_output_cid,
-                                                                         0, NULL);
+                                                                         0, NULL, &insertIndexes);
 
                        /* insert index entries for tuple */
-                       if (resultRelInfo->ri_NumIndices > 0)
+                       if (insertIndexes && resultRelInfo->ri_NumIndices > 0)
                                recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
                                                                                                           slot, estate, false,
                                                                                                           false, NULL, NIL,
index 91fbc95034345e560cd29347830a60349bc2e56d..32a3fbce961d9e1d9087c67f3da59be143742558 100644 (file)
@@ -282,7 +282,7 @@ extern void heap_insert(Relation relation, HeapTuple tup, CommandId cid,
                                                int options, BulkInsertState bistate);
 extern void heap_multi_insert(Relation relation, struct TupleTableSlot **slots,
                                                          int ntuples, CommandId cid, int options,
-                                                         BulkInsertState bistate);
+                                                         BulkInsertState bistate, bool *insert_indexes);
 extern TM_Result heap_delete(Relation relation, ItemPointer tid,
                                                         CommandId cid, Snapshot crosscheck, int options,
                                                         struct TM_FailureData *tmfd, bool changingPart,
index cf68ec48ebf7152f05f6bdf3ac39942201d6440b..cf76fc29d4b76421ba5f2c8dba437882380d2dbd 100644 (file)
@@ -512,7 +512,8 @@ typedef struct TableAmRoutine
        /* see table_tuple_insert() for reference about parameters */
        TupleTableSlot *(*tuple_insert) (Relation rel, TupleTableSlot *slot,
                                                                         CommandId cid, int options,
-                                                                        struct BulkInsertStateData *bistate);
+                                                                        struct BulkInsertStateData *bistate,
+                                                                        bool *insert_indexes);
 
        /* see table_tuple_insert_speculative() for reference about parameters */
        void            (*tuple_insert_speculative) (Relation rel,
@@ -530,7 +531,8 @@ typedef struct TableAmRoutine
 
        /* see table_multi_insert() for reference about parameters */
        void            (*multi_insert) (Relation rel, TupleTableSlot **slots, int nslots,
-                                                                CommandId cid, int options, struct BulkInsertStateData *bistate);
+                                                                CommandId cid, int options, struct BulkInsertStateData *bistate,
+                                                                bool *insert_indexes);
 
        /* see table_tuple_delete() for reference about parameters */
        TM_Result       (*tuple_delete) (Relation rel,
@@ -1384,6 +1386,12 @@ table_index_delete_tuples(Relation rel, TM_IndexDeleteOp *delstate)
  * behavior) is also just passed through to RelationGetBufferForTuple. If
  * `bistate` is provided, table_finish_bulk_insert() needs to be called.
  *
+ * The table AM's implementation of tuple_insert should set `*insert_indexes`
+ * to true if it expects the caller to insert the relevant index tuples
+ * (as heap table AM does).  It should set `*insert_indexes` to false if
+ * it cares about index inserts itself and doesn't want the caller to do
+ * index inserts.
+ *
  * Returns the slot containing the inserted tuple, which may differ from the
  * given slot. For instance, the source slot may be VirtualTupleTableSlot, but
  * the result slot may correspond to the table AM. On return the slot's
@@ -1393,10 +1401,11 @@ table_index_delete_tuples(Relation rel, TM_IndexDeleteOp *delstate)
  */
 static inline TupleTableSlot *
 table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid,
-                                  int options, struct BulkInsertStateData *bistate)
+                                  int options, struct BulkInsertStateData *bistate,
+                                  bool *insert_indexes)
 {
        return rel->rd_tableam->tuple_insert(rel, slot, cid, options,
-                                                                                bistate);
+                                                                                bistate, insert_indexes);
 }
 
 /*
@@ -1448,10 +1457,11 @@ table_tuple_complete_speculative(Relation rel, TupleTableSlot *slot,
  */
 static inline void
 table_multi_insert(Relation rel, TupleTableSlot **slots, int nslots,
-                                  CommandId cid, int options, struct BulkInsertStateData *bistate)
+                                  CommandId cid, int options, struct BulkInsertStateData *bistate,
+                                  bool *insert_indexes)
 {
        rel->rd_tableam->multi_insert(rel, slots, nslots,
-                                                                 cid, options, bistate);
+                                                                 cid, options, bistate, insert_indexes);
 }
 
 /*
@@ -2096,7 +2106,8 @@ table_scan_sample_next_tuple(TableScanDesc scan,
  * ----------------------------------------------------------------------------
  */
 
-extern void simple_table_tuple_insert(Relation rel, TupleTableSlot *slot);
+extern void simple_table_tuple_insert(Relation rel, TupleTableSlot *slot,
+                                                                         bool *insert_indexes);
 extern void simple_table_tuple_delete(Relation rel, ItemPointer tid,
                                                                          Snapshot snapshot,
                                                                          TupleTableSlot *oldSlot);