PostgreSQL Source Code  git master
spginsert.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/spgist_private.h"
#include "access/tableam.h"
#include "access/xloginsert.h"
#include "miscadmin.h"
#include "nodes/execnodes.h"
#include "storage/bufmgr.h"
#include "storage/bulk_write.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for spginsert.c:

Go to the source code of this file.

Data Structures

struct  SpGistBuildState
 

Functions

static void spgistBuildCallback (Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
 
IndexBuildResultspgbuild (Relation heap, Relation index, IndexInfo *indexInfo)
 
void spgbuildempty (Relation index)
 
bool spginsert (Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
 

Function Documentation

◆ spgbuild()

IndexBuildResult* spgbuild ( Relation  heap,
Relation  index,
IndexInfo indexInfo 
)

Definition at line 73 of file spginsert.c.

74 {
75  IndexBuildResult *result;
76  double reltuples;
77  SpGistBuildState buildstate;
78  Buffer metabuffer,
79  rootbuffer,
80  nullbuffer;
81 
83  elog(ERROR, "index \"%s\" already contains data",
85 
86  /*
87  * Initialize the meta page and root pages
88  */
89  metabuffer = SpGistNewBuffer(index);
90  rootbuffer = SpGistNewBuffer(index);
91  nullbuffer = SpGistNewBuffer(index);
92 
96 
98 
99  SpGistInitMetapage(BufferGetPage(metabuffer));
100  MarkBufferDirty(metabuffer);
101  SpGistInitBuffer(rootbuffer, SPGIST_LEAF);
102  MarkBufferDirty(rootbuffer);
104  MarkBufferDirty(nullbuffer);
105 
106 
108 
109  UnlockReleaseBuffer(metabuffer);
110  UnlockReleaseBuffer(rootbuffer);
111  UnlockReleaseBuffer(nullbuffer);
112 
113  /*
114  * Now insert all the heap data into the index
115  */
116  initSpGistState(&buildstate.spgstate, index);
117  buildstate.spgstate.isBuild = true;
118  buildstate.indtuples = 0;
119 
121  "SP-GiST build temporary context",
123 
124  reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
125  spgistBuildCallback, (void *) &buildstate,
126  NULL);
127 
128  MemoryContextDelete(buildstate.tmpCtx);
129 
131 
132  /*
133  * We didn't write WAL records as we built the index, so if WAL-logging is
134  * required, write all pages to the WAL now.
135  */
136  if (RelationNeedsWAL(index))
137  {
140  true);
141  }
142 
143  result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
144  result->heap_tuples = reltuples;
145  result->index_tuples = buildstate.indtuples;
146 
147  return result;
148 }
int Buffer
Definition: buf.h:23
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3667
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4867
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2474
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:277
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:404
#define Assert(condition)
Definition: c.h:858
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
void * palloc0(Size size)
Definition: mcxt.c:1346
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
#define RelationGetRelationName(relation)
Definition: rel.h:539
#define RelationNeedsWAL(relation)
Definition: rel.h:628
@ MAIN_FORKNUM
Definition: relpath.h:50
static void spgistBuildCallback(Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: spginsert.c:41
#define SPGIST_NULL_BLKNO
#define SPGIST_METAPAGE_BLKNO
#define SPGIST_NULLS
#define SPGIST_LEAF
#define SPGIST_ROOT_BLKNO
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:340
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:431
Buffer SpGistNewBuffer(Relation index)
Definition: spgutils.c:375
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:703
void SpGistInitMetapage(Page page)
Definition: spgutils.c:713
double heap_tuples
Definition: genam.h:32
double index_tuples
Definition: genam.h:33
MemoryContext tmpCtx
Definition: spginsert.c:35
SpGistState spgstate
Definition: spginsert.c:33
Definition: type.h:95
static double table_index_build_scan(Relation table_rel, Relation index_rel, struct IndexInfo *index_info, bool allow_sync, bool progress, IndexBuildCallback callback, void *callback_state, TableScanDesc scan)
Definition: tableam.h:1785
void log_newpage_range(Relation rel, ForkNumber forknum, BlockNumber startblk, BlockNumber endblk, bool page_std)
Definition: xloginsert.c:1270

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BufferGetBlockNumber(), BufferGetPage(), CurrentMemoryContext, elog, END_CRIT_SECTION, ERROR, IndexBuildResult::heap_tuples, IndexBuildResult::index_tuples, SpGistBuildState::indtuples, initSpGistState(), SpGistState::isBuild, log_newpage_range(), MAIN_FORKNUM, MarkBufferDirty(), MemoryContextDelete(), palloc0(), RelationGetNumberOfBlocks, RelationGetRelationName, RelationNeedsWAL, SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, spgistBuildCallback(), SpGistInitBuffer(), SpGistInitMetapage(), SpGistNewBuffer(), SpGistUpdateMetaPage(), SpGistBuildState::spgstate, START_CRIT_SECTION, table_index_build_scan(), SpGistBuildState::tmpCtx, and UnlockReleaseBuffer().

Referenced by spghandler().

◆ spgbuildempty()

void spgbuildempty ( Relation  index)

Definition at line 154 of file spginsert.c.

155 {
156  BulkWriteState *bulkstate;
158 
159  bulkstate = smgr_bulk_start_rel(index, INIT_FORKNUM);
160 
161  /* Construct metapage. */
162  buf = smgr_bulk_get_buf(bulkstate);
164  smgr_bulk_write(bulkstate, SPGIST_METAPAGE_BLKNO, buf, true);
165 
166  /* Likewise for the root page. */
167  buf = smgr_bulk_get_buf(bulkstate);
169  smgr_bulk_write(bulkstate, SPGIST_ROOT_BLKNO, buf, true);
170 
171  /* Likewise for the null-tuples root page. */
172  buf = smgr_bulk_get_buf(bulkstate);
174  smgr_bulk_write(bulkstate, SPGIST_NULL_BLKNO, buf, true);
175 
176  smgr_bulk_finish(bulkstate);
177 }
Pointer Page
Definition: bufpage.h:78
void smgr_bulk_write(BulkWriteState *bulkstate, BlockNumber blocknum, BulkWriteBuffer buf, bool page_std)
Definition: bulk_write.c:271
BulkWriteBuffer smgr_bulk_get_buf(BulkWriteState *bulkstate)
Definition: bulk_write.c:295
void smgr_bulk_finish(BulkWriteState *bulkstate)
Definition: bulk_write.c:129
BulkWriteState * smgr_bulk_start_rel(Relation rel, ForkNumber forknum)
Definition: bulk_write.c:86
static char * buf
Definition: pg_test_fsync.c:73
@ INIT_FORKNUM
Definition: relpath.h:53
void SpGistInitPage(Page page, uint16 f)
Definition: spgutils.c:689

References buf, INIT_FORKNUM, smgr_bulk_finish(), smgr_bulk_get_buf(), smgr_bulk_start_rel(), smgr_bulk_write(), SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, SpGistInitMetapage(), and SpGistInitPage().

Referenced by spghandler().

◆ spginsert()

bool spginsert ( Relation  index,
Datum values,
bool isnull,
ItemPointer  ht_ctid,
Relation  heapRel,
IndexUniqueCheck  checkUnique,
bool  indexUnchanged,
IndexInfo indexInfo 
)

Definition at line 183 of file spginsert.c.

188 {
189  SpGistState spgstate;
190  MemoryContext oldCtx;
191  MemoryContext insertCtx;
192 
194  "SP-GiST insert temporary context",
196  oldCtx = MemoryContextSwitchTo(insertCtx);
197 
198  initSpGistState(&spgstate, index);
199 
200  /*
201  * We might have to repeat spgdoinsert() multiple times, if conflicts
202  * occur with concurrent insertions. If so, reset the insertCtx each time
203  * to avoid cumulative memory consumption. That means we also have to
204  * redo initSpGistState(), but it's cheap enough not to matter.
205  */
206  while (!spgdoinsert(index, &spgstate, ht_ctid, values, isnull))
207  {
208  MemoryContextReset(insertCtx);
209  initSpGistState(&spgstate, index);
210  }
211 
213 
214  MemoryContextSwitchTo(oldCtx);
215  MemoryContextDelete(insertCtx);
216 
217  /* return false since we've not done any unique check */
218  return false;
219 }
static Datum values[MAXATTR]
Definition: bootstrap.c:152
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
MemoryContextSwitchTo(old_ctx)
bool spgdoinsert(Relation index, SpGistState *state, ItemPointer heapPtr, Datum *datums, bool *isnulls)
Definition: spgdoinsert.c:1914

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, initSpGistState(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), spgdoinsert(), SpGistUpdateMetaPage(), and values.

Referenced by spghandler().

◆ spgistBuildCallback()

static void spgistBuildCallback ( Relation  index,
ItemPointer  tid,
Datum values,
bool isnull,
bool  tupleIsAlive,
void *  state 
)
static

Definition at line 41 of file spginsert.c.

43 {
44  SpGistBuildState *buildstate = (SpGistBuildState *) state;
45  MemoryContext oldCtx;
46 
47  /* Work in temp context, and reset it after each tuple */
48  oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
49 
50  /*
51  * Even though no concurrent insertions can be happening, we still might
52  * get a buffer-locking failure due to bgwriter or checkpointer taking a
53  * lock on some buffer. So we need to be willing to retry. We can flush
54  * any temp data when retrying.
55  */
56  while (!spgdoinsert(index, &buildstate->spgstate, tid,
57  values, isnull))
58  {
59  MemoryContextReset(buildstate->tmpCtx);
60  }
61 
62  /* Update total tuple count */
63  buildstate->indtuples += 1;
64 
65  MemoryContextSwitchTo(oldCtx);
66  MemoryContextReset(buildstate->tmpCtx);
67 }
Definition: regguts.h:323

References SpGistBuildState::indtuples, MemoryContextReset(), MemoryContextSwitchTo(), spgdoinsert(), SpGistBuildState::spgstate, SpGistBuildState::tmpCtx, and values.

Referenced by spgbuild().