@@ -58,6 +58,17 @@ typedef struct BrinBuildState
58
58
BrinMemTuple * bs_dtuple ;
59
59
}BrinBuildState ;
60
60
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
+
61
72
/*
62
73
* Struct used as "opaque" during index scans
63
74
*/
@@ -72,6 +83,7 @@ typedef struct BrinOpaque
72
83
73
84
static BrinBuildState * initialize_brin_buildstate (Relation idxRel ,
74
85
BrinRevmap * revmap ,BlockNumber pagesPerRange );
86
+ static BrinInsertState * initialize_brin_insertstate (Relation idxRel ,IndexInfo * indexInfo );
75
87
static void terminate_brin_buildstate (BrinBuildState * state );
76
88
static void brinsummarize (Relation index ,Relation heapRel ,BlockNumber pageRange ,
77
89
bool include_partial ,double * numSummarized ,double * numExisting );
@@ -117,6 +129,7 @@ brinhandler(PG_FUNCTION_ARGS)
117
129
amroutine -> ambuild = brinbuild ;
118
130
amroutine -> ambuildempty = brinbuildempty ;
119
131
amroutine -> aminsert = brininsert ;
132
+ amroutine -> aminsertcleanup = brininsertcleanup ;
120
133
amroutine -> ambulkdelete = brinbulkdelete ;
121
134
amroutine -> amvacuumcleanup = brinvacuumcleanup ;
122
135
amroutine -> amcanreturn = NULL ;
@@ -140,6 +153,27 @@ brinhandler(PG_FUNCTION_ARGS)
140
153
PG_RETURN_POINTER (amroutine );
141
154
}
142
155
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
+
143
177
/*
144
178
* A tuple in the heap is being inserted. To keep a brin index up to date,
145
179
* we need to obtain the relevant index tuple and compare its stored values
@@ -162,14 +196,24 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
162
196
BlockNumber pagesPerRange ;
163
197
BlockNumber origHeapBlk ;
164
198
BlockNumber heapBlk ;
165
- BrinDesc * bdesc = (BrinDesc * )indexInfo -> ii_AmCache ;
199
+ BrinInsertState * bistate = (BrinInsertState * )indexInfo -> ii_AmCache ;
166
200
BrinRevmap * revmap ;
201
+ BrinDesc * bdesc ;
167
202
Buffer buf = InvalidBuffer ;
168
203
MemoryContext tupcxt = NULL ;
169
204
MemoryContext oldcxt = CurrentMemoryContext ;
170
205
bool autosummarize = BrinGetAutoSummarize (idxRel );
171
206
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 ;
173
217
174
218
/*
175
219
* origHeapBlk is the block number where the insertion occurred. heapBlk
@@ -228,14 +272,6 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
228
272
if (!brtup )
229
273
break ;
230
274
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
- }
239
275
/* First time through in this brininsert call? */
240
276
if (tupcxt == NULL )
241
277
{
@@ -306,7 +342,6 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
306
342
break ;
307
343
}
308
344
309
- brinRevmapTerminate (revmap );
310
345
if (BufferIsValid (buf ))
311
346
ReleaseBuffer (buf );
312
347
MemoryContextSwitchTo (oldcxt );
@@ -316,6 +351,24 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
316
351
return false;
317
352
}
318
353
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
+
319
372
/*
320
373
* Initialize state for a BRIN index scan.
321
374
*