00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "postgres.h"
00018
00019 #include "access/genam.h"
00020 #include "access/heapam_xlog.h"
00021 #include "access/spgist_private.h"
00022 #include "catalog/index.h"
00023 #include "miscadmin.h"
00024 #include "storage/bufmgr.h"
00025 #include "storage/smgr.h"
00026 #include "utils/memutils.h"
00027 #include "utils/rel.h"
00028
00029
00030 typedef struct
00031 {
00032 SpGistState spgstate;
00033 MemoryContext tmpCtx;
00034 } SpGistBuildState;
00035
00036
00037
00038 static void
00039 spgistBuildCallback(Relation index, HeapTuple htup, Datum *values,
00040 bool *isnull, bool tupleIsAlive, void *state)
00041 {
00042 SpGistBuildState *buildstate = (SpGistBuildState *) state;
00043 MemoryContext oldCtx;
00044
00045
00046 oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
00047
00048 spgdoinsert(index, &buildstate->spgstate, &htup->t_self, *values, *isnull);
00049
00050 MemoryContextSwitchTo(oldCtx);
00051 MemoryContextReset(buildstate->tmpCtx);
00052 }
00053
00054
00055
00056
00057 Datum
00058 spgbuild(PG_FUNCTION_ARGS)
00059 {
00060 Relation heap = (Relation) PG_GETARG_POINTER(0);
00061 Relation index = (Relation) PG_GETARG_POINTER(1);
00062 IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2);
00063 IndexBuildResult *result;
00064 double reltuples;
00065 SpGistBuildState buildstate;
00066 Buffer metabuffer,
00067 rootbuffer,
00068 nullbuffer;
00069
00070 if (RelationGetNumberOfBlocks(index) != 0)
00071 elog(ERROR, "index \"%s\" already contains data",
00072 RelationGetRelationName(index));
00073
00074
00075
00076
00077 metabuffer = SpGistNewBuffer(index);
00078 rootbuffer = SpGistNewBuffer(index);
00079 nullbuffer = SpGistNewBuffer(index);
00080
00081 Assert(BufferGetBlockNumber(metabuffer) == SPGIST_METAPAGE_BLKNO);
00082 Assert(BufferGetBlockNumber(rootbuffer) == SPGIST_ROOT_BLKNO);
00083 Assert(BufferGetBlockNumber(nullbuffer) == SPGIST_NULL_BLKNO);
00084
00085 START_CRIT_SECTION();
00086
00087 SpGistInitMetapage(BufferGetPage(metabuffer));
00088 MarkBufferDirty(metabuffer);
00089 SpGistInitBuffer(rootbuffer, SPGIST_LEAF);
00090 MarkBufferDirty(rootbuffer);
00091 SpGistInitBuffer(nullbuffer, SPGIST_LEAF | SPGIST_NULLS);
00092 MarkBufferDirty(nullbuffer);
00093
00094 if (RelationNeedsWAL(index))
00095 {
00096 XLogRecPtr recptr;
00097 XLogRecData rdata;
00098
00099
00100 rdata.data = (char *) &(index->rd_node);
00101 rdata.len = sizeof(RelFileNode);
00102 rdata.buffer = InvalidBuffer;
00103 rdata.next = NULL;
00104
00105 recptr = XLogInsert(RM_SPGIST_ID, XLOG_SPGIST_CREATE_INDEX, &rdata);
00106
00107 PageSetLSN(BufferGetPage(metabuffer), recptr);
00108 PageSetLSN(BufferGetPage(rootbuffer), recptr);
00109 PageSetLSN(BufferGetPage(nullbuffer), recptr);
00110 }
00111
00112 END_CRIT_SECTION();
00113
00114 UnlockReleaseBuffer(metabuffer);
00115 UnlockReleaseBuffer(rootbuffer);
00116 UnlockReleaseBuffer(nullbuffer);
00117
00118
00119
00120
00121 initSpGistState(&buildstate.spgstate, index);
00122 buildstate.spgstate.isBuild = true;
00123
00124 buildstate.tmpCtx = AllocSetContextCreate(CurrentMemoryContext,
00125 "SP-GiST build temporary context",
00126 ALLOCSET_DEFAULT_MINSIZE,
00127 ALLOCSET_DEFAULT_INITSIZE,
00128 ALLOCSET_DEFAULT_MAXSIZE);
00129
00130 reltuples = IndexBuildHeapScan(heap, index, indexInfo, true,
00131 spgistBuildCallback, (void *) &buildstate);
00132
00133 MemoryContextDelete(buildstate.tmpCtx);
00134
00135 SpGistUpdateMetaPage(index);
00136
00137 result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
00138 result->heap_tuples = result->index_tuples = reltuples;
00139
00140 PG_RETURN_POINTER(result);
00141 }
00142
00143
00144
00145
00146 Datum
00147 spgbuildempty(PG_FUNCTION_ARGS)
00148 {
00149 Relation index = (Relation) PG_GETARG_POINTER(0);
00150 Page page;
00151
00152
00153 page = (Page) palloc(BLCKSZ);
00154 SpGistInitMetapage(page);
00155
00156
00157 PageSetChecksumInplace(page, SPGIST_METAPAGE_BLKNO);
00158 smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_METAPAGE_BLKNO,
00159 (char *) page, true);
00160 if (XLogIsNeeded())
00161 log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
00162 SPGIST_METAPAGE_BLKNO, page);
00163
00164
00165 SpGistInitPage(page, SPGIST_LEAF);
00166
00167 PageSetChecksumInplace(page, SPGIST_ROOT_BLKNO);
00168 smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_ROOT_BLKNO,
00169 (char *) page, true);
00170 if (XLogIsNeeded())
00171 log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
00172 SPGIST_ROOT_BLKNO, page);
00173
00174
00175 SpGistInitPage(page, SPGIST_LEAF | SPGIST_NULLS);
00176
00177 PageSetChecksumInplace(page, SPGIST_NULL_BLKNO);
00178 smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_NULL_BLKNO,
00179 (char *) page, true);
00180 if (XLogIsNeeded())
00181 log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
00182 SPGIST_NULL_BLKNO, page);
00183
00184
00185
00186
00187
00188
00189 smgrimmedsync(index->rd_smgr, INIT_FORKNUM);
00190
00191 PG_RETURN_VOID();
00192 }
00193
00194
00195
00196
00197 Datum
00198 spginsert(PG_FUNCTION_ARGS)
00199 {
00200 Relation index = (Relation) PG_GETARG_POINTER(0);
00201 Datum *values = (Datum *) PG_GETARG_POINTER(1);
00202 bool *isnull = (bool *) PG_GETARG_POINTER(2);
00203 ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
00204
00205 #ifdef NOT_USED
00206 Relation heapRel = (Relation) PG_GETARG_POINTER(4);
00207 IndexUniqueCheck checkUnique = (IndexUniqueCheck) PG_GETARG_INT32(5);
00208 #endif
00209 SpGistState spgstate;
00210 MemoryContext oldCtx;
00211 MemoryContext insertCtx;
00212
00213 insertCtx = AllocSetContextCreate(CurrentMemoryContext,
00214 "SP-GiST insert temporary context",
00215 ALLOCSET_DEFAULT_MINSIZE,
00216 ALLOCSET_DEFAULT_INITSIZE,
00217 ALLOCSET_DEFAULT_MAXSIZE);
00218 oldCtx = MemoryContextSwitchTo(insertCtx);
00219
00220 initSpGistState(&spgstate, index);
00221
00222 spgdoinsert(index, &spgstate, ht_ctid, *values, *isnull);
00223
00224 SpGistUpdateMetaPage(index);
00225
00226 MemoryContextSwitchTo(oldCtx);
00227 MemoryContextDelete(insertCtx);
00228
00229
00230 PG_RETURN_BOOL(false);
00231 }