@@ -58,6 +58,17 @@ typedef struct BrinBuildState
5858 BrinMemTuple * bs_dtuple ;
5959} BrinBuildState ;
6060
61+ /*
62+ * We use a BrinInsertState to capture running state spanning multiple
63+ * brininsert invocations, within the same command.
64+ */
65+ typedef struct BrinInsertState
66+ {
67+ BrinRevmap * bis_rmAccess ;
68+ BrinDesc * bis_desc ;
69+ BlockNumber bis_pages_per_range ;
70+ } BrinInsertState ;
71+
6172/*
6273 * Struct used as "opaque" during index scans
6374 */
@@ -72,6 +83,7 @@ typedef struct BrinOpaque
7283
7384static BrinBuildState * initialize_brin_buildstate (Relation idxRel ,
7485 BrinRevmap * revmap , BlockNumber pagesPerRange );
86+ static BrinInsertState * initialize_brin_insertstate (Relation idxRel , IndexInfo * indexInfo );
7587static void terminate_brin_buildstate (BrinBuildState * state );
7688static void brinsummarize (Relation index , Relation heapRel , BlockNumber pageRange ,
7789 bool include_partial , double * numSummarized , double * numExisting );
@@ -117,6 +129,7 @@ brinhandler(PG_FUNCTION_ARGS)
117129 amroutine -> ambuild = brinbuild ;
118130 amroutine -> ambuildempty = brinbuildempty ;
119131 amroutine -> aminsert = brininsert ;
132+ amroutine -> aminsertcleanup = brininsertcleanup ;
120133 amroutine -> ambulkdelete = brinbulkdelete ;
121134 amroutine -> amvacuumcleanup = brinvacuumcleanup ;
122135 amroutine -> amcanreturn = NULL ;
@@ -140,6 +153,27 @@ brinhandler(PG_FUNCTION_ARGS)
140153 PG_RETURN_POINTER (amroutine );
141154}
142155
156+ /*
157+ * Initialize a BrinInsertState to maintain state to be used across multiple
158+ * tuple inserts, within the same command.
159+ */
160+ static BrinInsertState *
161+ initialize_brin_insertstate (Relation idxRel , IndexInfo * indexInfo )
162+ {
163+ BrinInsertState * bistate ;
164+ MemoryContext oldcxt ;
165+
166+ oldcxt = MemoryContextSwitchTo (indexInfo -> ii_Context );
167+ bistate = palloc0 (sizeof (BrinInsertState ));
168+ bistate -> bis_desc = brin_build_desc (idxRel );
169+ bistate -> bis_rmAccess = brinRevmapInitialize (idxRel ,
170+ & bistate -> bis_pages_per_range );
171+ indexInfo -> ii_AmCache = bistate ;
172+ MemoryContextSwitchTo (oldcxt );
173+
174+ return bistate ;
175+ }
176+
143177/*
144178 * A tuple in the heap is being inserted. To keep a brin index up to date,
145179 * we need to obtain the relevant index tuple and compare its stored values
@@ -162,14 +196,24 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
162196 BlockNumber pagesPerRange ;
163197 BlockNumber origHeapBlk ;
164198 BlockNumber heapBlk ;
165- BrinDesc * bdesc = (BrinDesc * ) indexInfo -> ii_AmCache ;
199+ BrinInsertState * bistate = (BrinInsertState * ) indexInfo -> ii_AmCache ;
166200 BrinRevmap * revmap ;
201+ BrinDesc * bdesc ;
167202 Buffer buf = InvalidBuffer ;
168203 MemoryContext tupcxt = NULL ;
169204 MemoryContext oldcxt = CurrentMemoryContext ;
170205 bool autosummarize = BrinGetAutoSummarize (idxRel );
171206
172- revmap = brinRevmapInitialize (idxRel , & pagesPerRange );
207+ /*
208+ * If firt time through in this statement, initialize the insert state
209+ * that we keep for all the inserts in the command.
210+ */
211+ if (!bistate )
212+ bistate = initialize_brin_insertstate (idxRel , indexInfo );
213+
214+ revmap = bistate -> bis_rmAccess ;
215+ bdesc = bistate -> bis_desc ;
216+ pagesPerRange = bistate -> bis_pages_per_range ;
173217
174218 /*
175219 * origHeapBlk is the block number where the insertion occurred. heapBlk
@@ -228,14 +272,6 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
228272 if (!brtup )
229273 break ;
230274
231- /* First time through in this statement? */
232- if (bdesc == NULL )
233- {
234- MemoryContextSwitchTo (indexInfo -> ii_Context );
235- bdesc = brin_build_desc (idxRel );
236- indexInfo -> ii_AmCache = (void * ) bdesc ;
237- MemoryContextSwitchTo (oldcxt );
238- }
239275 /* First time through in this brininsert call? */
240276 if (tupcxt == NULL )
241277 {
@@ -306,7 +342,6 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
306342 break ;
307343 }
308344
309- brinRevmapTerminate (revmap );
310345 if (BufferIsValid (buf ))
311346 ReleaseBuffer (buf );
312347 MemoryContextSwitchTo (oldcxt );
@@ -316,6 +351,24 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
316351 return false;
317352}
318353
354+ /*
355+ * Callback to clean up the BrinInsertState once all tuple inserts are done.
356+ */
357+ void
358+ brininsertcleanup (IndexInfo * indexInfo )
359+ {
360+ BrinInsertState * bistate = (BrinInsertState * ) indexInfo -> ii_AmCache ;
361+
362+ Assert (bistate );
363+ /*
364+ * Clean up the revmap. Note that the brinDesc has already been cleaned up
365+ * as part of its own memory context.
366+ */
367+ brinRevmapTerminate (bistate -> bis_rmAccess );
368+ bistate -> bis_rmAccess = NULL ;
369+ bistate -> bis_desc = NULL ;
370+ }
371+
319372/*
320373 * Initialize state for a BRIN index scan.
321374 *
0 commit comments