LCOV - differential code coverage report
Current view: top level - src/backend/access/spgist - spginsert.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 98.6 % 69 68 1 4 64 4
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 4 4 1 3
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (240..) days: 98.5 % 68 67 1 3 64
Function coverage date bins:
(240..) days: 100.0 % 4 4 1 3

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * spginsert.c
                                  4                 :  *    Externally visible index creation/insertion routines
                                  5                 :  *
                                  6                 :  * All the actual insertion logic is in spgdoinsert.c.
                                  7                 :  *
                                  8                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  9                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                 10                 :  *
                                 11                 :  * IDENTIFICATION
                                 12                 :  *          src/backend/access/spgist/spginsert.c
                                 13                 :  *
                                 14                 :  *-------------------------------------------------------------------------
                                 15                 :  */
                                 16                 : 
                                 17                 : #include "postgres.h"
                                 18                 : 
                                 19                 : #include "access/genam.h"
                                 20                 : #include "access/spgist_private.h"
                                 21                 : #include "access/spgxlog.h"
                                 22                 : #include "access/tableam.h"
                                 23                 : #include "access/xlog.h"
                                 24                 : #include "access/xloginsert.h"
                                 25                 : #include "catalog/index.h"
                                 26                 : #include "miscadmin.h"
                                 27                 : #include "storage/bufmgr.h"
                                 28                 : #include "storage/smgr.h"
                                 29                 : #include "utils/memutils.h"
                                 30                 : #include "utils/rel.h"
                                 31                 : 
                                 32                 : 
                                 33                 : typedef struct
                                 34                 : {
                                 35                 :     SpGistState spgstate;       /* SPGiST's working state */
                                 36                 :     int64       indtuples;      /* total number of tuples indexed */
                                 37                 :     MemoryContext tmpCtx;       /* per-tuple temporary context */
                                 38                 : } SpGistBuildState;
                                 39                 : 
                                 40                 : 
                                 41                 : /* Callback to process one heap tuple during table_index_build_scan */
                                 42                 : static void
 1248 andres                     43 CBC      281361 : spgistBuildCallback(Relation index, ItemPointer tid, Datum *values,
                                 44                 :                     bool *isnull, bool tupleIsAlive, void *state)
                                 45                 : {
 4131 tgl                        46          281361 :     SpGistBuildState *buildstate = (SpGistBuildState *) state;
                                 47                 :     MemoryContext oldCtx;
                                 48                 : 
                                 49                 :     /* Work in temp context, and reset it after each tuple */
 4046                            50          281361 :     oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
                                 51                 : 
                                 52                 :     /*
                                 53                 :      * Even though no concurrent insertions can be happening, we still might
                                 54                 :      * get a buffer-locking failure due to bgwriter or checkpointer taking a
                                 55                 :      * lock on some buffer.  So we need to be willing to retry.  We can flush
                                 56                 :      * any temp data when retrying.
                                 57                 :      */
 1248 andres                     58          281363 :     while (!spgdoinsert(index, &buildstate->spgstate, tid,
                                 59                 :                         values, isnull))
                                 60                 :     {
 3445 tgl                        61               2 :         MemoryContextReset(buildstate->tmpCtx);
                                 62                 :     }
                                 63                 : 
                                 64                 :     /* Update total tuple count */
 1844                            65          281361 :     buildstate->indtuples += 1;
                                 66                 : 
 4046                            67          281361 :     MemoryContextSwitchTo(oldCtx);
                                 68          281361 :     MemoryContextReset(buildstate->tmpCtx);
 4131                            69          281361 : }
                                 70                 : 
                                 71                 : /*
                                 72                 :  * Build an SP-GiST index.
                                 73                 :  */
                                 74                 : IndexBuildResult *
 2639                            75             100 : spgbuild(Relation heap, Relation index, IndexInfo *indexInfo)
                                 76                 : {
                                 77                 :     IndexBuildResult *result;
                                 78                 :     double      reltuples;
                                 79                 :     SpGistBuildState buildstate;
                                 80                 :     Buffer      metabuffer,
                                 81                 :                 rootbuffer,
                                 82                 :                 nullbuffer;
                                 83                 : 
 4131                            84             100 :     if (RelationGetNumberOfBlocks(index) != 0)
 4131 tgl                        85 UBC           0 :         elog(ERROR, "index \"%s\" already contains data",
                                 86                 :              RelationGetRelationName(index));
                                 87                 : 
                                 88                 :     /*
                                 89                 :      * Initialize the meta page and root pages
                                 90                 :      */
 4131 tgl                        91 CBC         100 :     metabuffer = SpGistNewBuffer(index);
                                 92             100 :     rootbuffer = SpGistNewBuffer(index);
 4046                            93             100 :     nullbuffer = SpGistNewBuffer(index);
                                 94                 : 
 4131                            95             100 :     Assert(BufferGetBlockNumber(metabuffer) == SPGIST_METAPAGE_BLKNO);
 4046                            96             100 :     Assert(BufferGetBlockNumber(rootbuffer) == SPGIST_ROOT_BLKNO);
                                 97             100 :     Assert(BufferGetBlockNumber(nullbuffer) == SPGIST_NULL_BLKNO);
                                 98                 : 
 4131                            99             100 :     START_CRIT_SECTION();
                                100                 : 
 2545 kgrittn                   101             100 :     SpGistInitMetapage(BufferGetPage(metabuffer));
 4131 tgl                       102             100 :     MarkBufferDirty(metabuffer);
                                103             100 :     SpGistInitBuffer(rootbuffer, SPGIST_LEAF);
                                104             100 :     MarkBufferDirty(rootbuffer);
 4046                           105             100 :     SpGistInitBuffer(nullbuffer, SPGIST_LEAF | SPGIST_NULLS);
                                106             100 :     MarkBufferDirty(nullbuffer);
                                107                 : 
                                108                 : 
 4131                           109             100 :     END_CRIT_SECTION();
                                110                 : 
                                111             100 :     UnlockReleaseBuffer(metabuffer);
                                112             100 :     UnlockReleaseBuffer(rootbuffer);
 4046                           113             100 :     UnlockReleaseBuffer(nullbuffer);
                                114                 : 
                                115                 :     /*
                                116                 :      * Now insert all the heap data into the index
                                117                 :      */
 4131                           118             100 :     initSpGistState(&buildstate.spgstate, index);
                                119             100 :     buildstate.spgstate.isBuild = true;
 1844                           120             100 :     buildstate.indtuples = 0;
                                121                 : 
 4131                           122             100 :     buildstate.tmpCtx = AllocSetContextCreate(CurrentMemoryContext,
                                123                 :                                               "SP-GiST build temporary context",
                                124                 :                                               ALLOCSET_DEFAULT_SIZES);
                                125                 : 
 1468 alvherre                  126             100 :     reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
                                127                 :                                        spgistBuildCallback, (void *) &buildstate,
                                128                 :                                        NULL);
                                129                 : 
 4131 tgl                       130             100 :     MemoryContextDelete(buildstate.tmpCtx);
                                131                 : 
                                132             100 :     SpGistUpdateMetaPage(index);
                                133                 : 
                                134                 :     /*
                                135                 :      * We didn't write WAL records as we built the index, so if WAL-logging is
                                136                 :      * required, write all pages to the WAL now.
                                137                 :      */
 1467 heikki.linnakangas        138             100 :     if (RelationNeedsWAL(index))
                                139                 :     {
                                140              34 :         log_newpage_range(index, MAIN_FORKNUM,
                                141                 :                           0, RelationGetNumberOfBlocks(index),
                                142                 :                           true);
                                143                 :     }
                                144                 : 
 4131 tgl                       145             100 :     result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
 1844                           146             100 :     result->heap_tuples = reltuples;
                                147             100 :     result->index_tuples = buildstate.indtuples;
                                148                 : 
 2639                           149             100 :     return result;
                                150                 : }
                                151                 : 
                                152                 : /*
                                153                 :  * Build an empty SPGiST index in the initialization fork
                                154                 :  */
                                155                 : void
                                156               4 : spgbuildempty(Relation index)
                                157                 : {
                                158                 :     Page        page;
                                159                 : 
                                160                 :     /* Construct metapage. */
    1 tmunro                    161 GNC           4 :     page = (Page) palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, 0);
 4131 tgl                       162 CBC           4 :     SpGistInitMetapage(page);
                                163                 : 
                                164                 :     /*
                                165                 :      * Write the page and log it unconditionally.  This is important
                                166                 :      * particularly for indexes created on tablespaces and databases whose
                                167                 :      * creation happened after the last redo pointer as recovery removes any
                                168                 :      * of their existing content when the corresponding create records are
                                169                 :      * replayed.
                                170                 :      */
 3670 simon                     171               4 :     PageSetChecksumInplace(page, SPGIST_METAPAGE_BLKNO);
  636 tgl                       172               4 :     smgrwrite(RelationGetSmgr(index), INIT_FORKNUM, SPGIST_METAPAGE_BLKNO,
                                173                 :               page, true);
  277 rhaas                     174 GNC           4 :     log_newpage(&(RelationGetSmgr(index))->smgr_rlocator.locator, INIT_FORKNUM,
                                175                 :                 SPGIST_METAPAGE_BLKNO, page, true);
                                176                 : 
                                177                 :     /* Likewise for the root page. */
 4131 tgl                       178 CBC           4 :     SpGistInitPage(page, SPGIST_LEAF);
                                179                 : 
 3670 simon                     180               4 :     PageSetChecksumInplace(page, SPGIST_ROOT_BLKNO);
  636 tgl                       181               4 :     smgrwrite(RelationGetSmgr(index), INIT_FORKNUM, SPGIST_ROOT_BLKNO,
                                182                 :               page, true);
  277 rhaas                     183 GNC           4 :     log_newpage(&(RelationGetSmgr(index))->smgr_rlocator.locator, INIT_FORKNUM,
                                184                 :                 SPGIST_ROOT_BLKNO, page, true);
                                185                 : 
                                186                 :     /* Likewise for the null-tuples root page. */
 4046 tgl                       187 CBC           4 :     SpGistInitPage(page, SPGIST_LEAF | SPGIST_NULLS);
                                188                 : 
 3670 simon                     189               4 :     PageSetChecksumInplace(page, SPGIST_NULL_BLKNO);
  636 tgl                       190               4 :     smgrwrite(RelationGetSmgr(index), INIT_FORKNUM, SPGIST_NULL_BLKNO,
                                191                 :               page, true);
  277 rhaas                     192 GNC           4 :     log_newpage(&(RelationGetSmgr(index))->smgr_rlocator.locator, INIT_FORKNUM,
                                193                 :                 SPGIST_NULL_BLKNO, page, true);
                                194                 : 
                                195                 :     /*
                                196                 :      * An immediate sync is required even if we xlog'd the pages, because the
                                197                 :      * writes did not go through shared buffers and therefore a concurrent
                                198                 :      * checkpoint may have moved the redo pointer past our xlog record.
                                199                 :      */
  636 tgl                       200 CBC           4 :     smgrimmedsync(RelationGetSmgr(index), INIT_FORKNUM);
 4131                           201               4 : }
                                202                 : 
                                203                 : /*
                                204                 :  * Insert one new tuple into an SPGiST index.
                                205                 :  */
                                206                 : bool
 2639                           207          121225 : spginsert(Relation index, Datum *values, bool *isnull,
                                208                 :           ItemPointer ht_ctid, Relation heapRel,
                                209                 :           IndexUniqueCheck checkUnique,
                                210                 :           bool indexUnchanged,
                                211                 :           IndexInfo *indexInfo)
                                212                 : {
                                213                 :     SpGistState spgstate;
                                214                 :     MemoryContext oldCtx;
                                215                 :     MemoryContext insertCtx;
                                216                 : 
 4131                           217          121225 :     insertCtx = AllocSetContextCreate(CurrentMemoryContext,
                                218                 :                                       "SP-GiST insert temporary context",
                                219                 :                                       ALLOCSET_DEFAULT_SIZES);
                                220          121225 :     oldCtx = MemoryContextSwitchTo(insertCtx);
                                221                 : 
                                222          121225 :     initSpGistState(&spgstate, index);
                                223                 : 
                                224                 :     /*
                                225                 :      * We might have to repeat spgdoinsert() multiple times, if conflicts
                                226                 :      * occur with concurrent insertions.  If so, reset the insertCtx each time
                                227                 :      * to avoid cumulative memory consumption.  That means we also have to
                                228                 :      * redo initSpGistState(), but it's cheap enough not to matter.
                                229                 :      */
  734                           230          121821 :     while (!spgdoinsert(index, &spgstate, ht_ctid, values, isnull))
                                231                 :     {
 3586                           232             596 :         MemoryContextReset(insertCtx);
                                233             596 :         initSpGistState(&spgstate, index);
                                234                 :     }
                                235                 : 
 4131                           236          121223 :     SpGistUpdateMetaPage(index);
                                237                 : 
                                238          121223 :     MemoryContextSwitchTo(oldCtx);
                                239          121223 :     MemoryContextDelete(insertCtx);
                                240                 : 
                                241                 :     /* return false since we've not done any unique check */
 2639                           242          121223 :     return false;
                                243                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a