diff --git a/.github/workflows/mest-check.yml b/.github/workflows/mest-check.yml index d008141..f71dbfd 100644 --- a/.github/workflows/mest-check.yml +++ b/.github/workflows/mest-check.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - pg: [16] + pg: [17] name: PostgreSQL ${{ matrix.pg }} runs-on: ubuntu-latest steps: diff --git a/README.md b/README.md index 4585ab6..a3a659e 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ For more information about each extension, please refer to their associated READ Dependencies ------------ -- [PostgreSQL 16](https://www.postgresql.org/) +- [PostgreSQL 17](https://www.postgresql.org/) Installation ------------ diff --git a/contrib/mobilitydb/README.md b/contrib/mobilitydb/README.md index d669340..f1edbcc 100644 --- a/contrib/mobilitydb/README.md +++ b/contrib/mobilitydb/README.md @@ -5,15 +5,15 @@ This directory contains an implementation of Multi-Entry Search Trees for Mobili Dependencies ------------ -- [PostgreSQL 16](https://www.postgresql.org/) -- [MobilityDB 1.1 (latest version of the master branch)](https://github.com/MobilityDB/MobilityDB) -- [MEOS (latest version of the master branch of MobilityDB)](https://www.libmeos.org/) +- [PostgreSQL 17](https://www.postgresql.org/) +- [MobilityDB 1.2](https://github.com/MobilityDB/MobilityDB) +- [MEOS 1.2](https://www.libmeos.org/) - [mest](https://github.com/MobilityDB/mest) -You should also set the following in postgresql.conf depending on the version of PostGIS and MobilityDB you have installed (below we use PostGIS 3, MobilityDB 1.1): +You should also set the following in postgresql.conf depending on the version of PostGIS and MobilityDB you have installed (below we use PostGIS 3, MobilityDB 1.2): ``` -shared_preload_libraries = 'postgis-3,libMobilityDB-1.1' +shared_preload_libraries = 'postgis-3,libMobilityDB-1.2' ``` Installation diff --git a/contrib/postgis/README.md b/contrib/postgis/README.md index 51149b5..c099689 100644 --- a/contrib/postgis/README.md +++ b/contrib/postgis/README.md @@ -10,7 +10,7 @@ However, the PostGIS support functions are not yet implemented for MGiST indexes Dependencies ------------ -- [PostgreSQL 16](https://www.postgresql.org/) +- [PostgreSQL 17](https://www.postgresql.org/) - [PostGIS 3.4](https://postgis.net/) - [mgist](../mgist) diff --git a/src/mgist/mgist.c b/src/mgist/mgist.c index fc53654..f96a4b5 100644 --- a/src/mgist/mgist.c +++ b/src/mgist/mgist.c @@ -21,9 +21,8 @@ #include "commands/vacuum.h" #include "miscadmin.h" #include "nodes/execnodes.h" -#include "storage/lmgr.h" #include "storage/predicate.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/index_selfuncs.h" #include "utils/memutils.h" #include "utils/rel.h" @@ -48,7 +47,7 @@ static void gistprunepage(Relation rel, Page page, Buffer buffer, #define ROTATEDIST(d) do { \ - SplitedPageLayout *tmp=(SplitedPageLayout*)palloc0(sizeof(SplitedPageLayout)); \ + SplitPageLayout *tmp=(SplitPageLayout*)palloc0(sizeof(SplitPageLayout)); \ tmp->block.blkno = InvalidBlockNumber; \ tmp->buffer = InvalidBuffer; \ tmp->next = (d); \ @@ -81,6 +80,7 @@ mgisthandler(PG_FUNCTION_ARGS) amroutine->amclusterable = true; amroutine->ampredlocks = true; amroutine->amcanparallel = false; + amroutine->amcanbuildparallel = false; amroutine->amcaninclude = true; amroutine->amusemaintenanceworkmem = false; amroutine->amsummarizing = false; @@ -91,6 +91,7 @@ mgisthandler(PG_FUNCTION_ARGS) amroutine->ambuild = mgistbuild; amroutine->ambuildempty = gistbuildempty; amroutine->aminsert = mgistinsert; + amroutine->aminsertcleanup = NULL; amroutine->ambulkdelete = gistbulkdelete; amroutine->amvacuumcleanup = gistvacuumcleanup; amroutine->amcanreturn = gistcanreturn; @@ -290,11 +291,11 @@ mgistplacetopage(Relation rel, Size freespace, MGISTSTATE *mgiststate, /* no space for insertion */ IndexTuple *itvec; int tlen; - SplitedPageLayout *dist = NULL, + SplitPageLayout *dist = NULL, *ptr; BlockNumber oldrlink = InvalidBlockNumber; GistNSN oldnsn = 0; - SplitedPageLayout rootpg; + SplitPageLayout rootpg; bool is_rootsplit; int npage; @@ -1087,7 +1088,7 @@ gistFindCorrectParent(Relation r, GISTInsertStack *child, bool is_build) { /* * End of chain and still didn't find parent. It's a very-very - * rare situation when root splitted. + * rare situation when root was split. */ break; } @@ -1442,7 +1443,7 @@ mgistfinishsplit(GISTInsertState *state, GISTInsertStack *stack, * used for XLOG and real writes buffers. Function is recursive, ie * it will split page until keys will fit in every page. */ -SplitedPageLayout * +SplitPageLayout * mgistSplit(Relation r, Page page, IndexTuple *itup, /* contains compressed entry */ @@ -1453,7 +1454,7 @@ mgistSplit(Relation r, *rvectup; GistSplitVector v; int i; - SplitedPageLayout *res = NULL; + SplitPageLayout *res = NULL; /* this should never recurse very deeply, but better safe than sorry */ check_stack_depth(); @@ -1503,7 +1504,7 @@ mgistSplit(Relation r, if (!gistfitpage(lvectup, v.splitVector.spl_nleft)) { - SplitedPageLayout *resptr, + SplitPageLayout *resptr, *subres; resptr = subres = mgistSplit(r, page, lvectup, v.splitVector.spl_nleft, mgiststate); diff --git a/src/mgist/mgist.h b/src/mgist/mgist.h index 7c5983c..f06c8d4 100644 --- a/src/mgist/mgist.h +++ b/src/mgist/mgist.h @@ -165,7 +165,7 @@ extern bool mgistplacetopage(Relation rel, Size freespace, MGISTSTATE *mgiststat Relation heapRel, bool is_build); -extern SplitedPageLayout *mgistSplit(Relation r, Page page, IndexTuple *itup, +extern SplitPageLayout *mgistSplit(Relation r, Page page, IndexTuple *itup, int len, MGISTSTATE *mgiststate); /* mgistget.c */ @@ -188,9 +188,9 @@ extern IndexTuple mgistgetadjusted(Relation r, IndexTuple addtup, MGISTSTATE *mgiststate); extern IndexTuple mgistFormTuple(MGISTSTATE *mgiststate, - Relation r, Datum *attdata, bool *isnull, bool isleaf); + Relation r, const Datum *attdata, bool *isnull, bool isleaf); extern void mgistCompressValues(MGISTSTATE *mgiststate, Relation r, - Datum *attdata, bool *isnull, bool isleaf, Datum *compatt); + const Datum *attdata, bool *isnull, bool isleaf, Datum *compatt); extern OffsetNumber mgistchoose(Relation r, Page p, IndexTuple it, MGISTSTATE *mgiststate); diff --git a/src/mgist/mgistbuild.c b/src/mgist/mgistbuild.c index e2b116e..02f264c 100644 --- a/src/mgist/mgistbuild.c +++ b/src/mgist/mgistbuild.c @@ -36,14 +36,13 @@ #include "access/genam.h" #include "access/gist_private.h" -#include "access/gistxlog.h" #include "access/tableam.h" #include "access/xloginsert.h" -#include "catalog/index.h" #include "miscadmin.h" +#include "nodes/execnodes.h" #include "optimizer/optimizer.h" #include "storage/bufmgr.h" -#include "storage/smgr.h" +#include "storage/bulk_write.h" #include "utils/memutils.h" #include "utils/rel.h" #include "utils/tuplesort.h" @@ -77,7 +76,7 @@ typedef enum GIST_BUFFERING_STATS, /* gathering statistics of index tuple size * before switching to the buffering build * mode */ - GIST_BUFFERING_ACTIVE /* in buffering build mode */ + GIST_BUFFERING_ACTIVE, /* in buffering build mode */ } GistBuildMode; /* Working state for gistbuild and its callback */ @@ -108,11 +107,7 @@ typedef struct Tuplesortstate *sortstate; /* state data for tuplesort.c */ BlockNumber pages_allocated; - BlockNumber pages_written; - - int ready_num_pages; - BlockNumber ready_blknos[XLR_MAX_BLOCK_ID]; - Page ready_pages[XLR_MAX_BLOCK_ID]; + BulkWriteState *bulkstate; } MGISTBuildState; #define GIST_SORTED_BUILD_PAGE_NUM 4 @@ -144,7 +139,6 @@ static void mgist_indexsortbuild_levelstate_add(MGISTBuildState *state, IndexTuple itup); static void mgist_indexsortbuild_levelstate_flush(MGISTBuildState *state, GistSortedBuildLevelState *levelstate); -static void mgist_indexsortbuild_flush_ready_pages(MGISTBuildState *state); static void mgistInitBuffering(MGISTBuildState *buildstate); static int mecalculatePagesPerBuffer(MGISTBuildState *buildstate, int levelStep); @@ -407,27 +401,18 @@ mgist_indexsortbuild(MGISTBuildState *mebuildstate) { IndexTuple itup; GistSortedBuildLevelState *levelstate; - Page page; + BulkWriteBuffer rootbuf; - mebuildstate->pages_allocated = 0; - mebuildstate->pages_written = 0; - mebuildstate->ready_num_pages = 0; + /* Reserve block 0 for the root page */ + mebuildstate->pages_allocated = 1; - /* - * Write an empty page as a placeholder for the root page. It will be - * replaced with the real root page at the end. - */ - page = palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, MCXT_ALLOC_ZERO); - smgrextend(RelationGetSmgr(mebuildstate->indexrel), MAIN_FORKNUM, GIST_ROOT_BLKNO, - page, true); - mebuildstate->pages_allocated++; - mebuildstate->pages_written++; + mebuildstate->bulkstate = smgr_bulk_start_rel(mebuildstate->indexrel, MAIN_FORKNUM); /* Allocate a temporary buffer for the first leaf page batch. */ levelstate = palloc0(sizeof(GistSortedBuildLevelState)); - levelstate->pages[0] = page; + levelstate->pages[0] = palloc(BLCKSZ);; levelstate->parent = NULL; - gistinitpage(page, F_LEAF); + gistinitpage(levelstate->pages[0], F_LEAF); /* * Fill index pages with tuples in the sorted order. @@ -457,31 +442,14 @@ mgist_indexsortbuild(MGISTBuildState *mebuildstate) levelstate = parent; } - mgist_indexsortbuild_flush_ready_pages(mebuildstate); - /* Write out the root */ - PageSetLSN(levelstate->pages[0], GistBuildLSN); - PageSetChecksumInplace(levelstate->pages[0], GIST_ROOT_BLKNO); - smgrwrite(RelationGetSmgr(mebuildstate->indexrel), MAIN_FORKNUM, GIST_ROOT_BLKNO, - levelstate->pages[0], true); - if (RelationNeedsWAL(mebuildstate->indexrel)) - log_newpage(&mebuildstate->indexrel->rd_locator, MAIN_FORKNUM, GIST_ROOT_BLKNO, - levelstate->pages[0], true); - - pfree(levelstate->pages[0]); + rootbuf = smgr_bulk_get_buf(mebuildstate->bulkstate); + memcpy(rootbuf, levelstate->pages[0], BLCKSZ); + smgr_bulk_write(mebuildstate->bulkstate, GIST_ROOT_BLKNO, rootbuf, true); + pfree(levelstate); - /* - * When we WAL-logged index pages, we must nonetheless fsync index files. - * Since we're building outside shared buffers, a CHECKPOINT occurring - * during the build has no way to flush the previously written data to - * disk (indeed it won't know the index even exists). A crash later on - * would replay WAL from the checkpoint, therefore it wouldn't replay our - * earlier WAL entries. If we do not fsync those pages here, they might - * still not be on disk when the crash occurs. - */ - if (RelationNeedsWAL(mebuildstate->indexrel)) - smgrimmedsync(RelationGetSmgr(mebuildstate->indexrel), MAIN_FORKNUM); + smgr_bulk_finish(mebuildstate->bulkstate); } /* @@ -511,8 +479,7 @@ mgist_indexsortbuild_levelstate_add(MGISTBuildState *mebuildstate, levelstate->current_page++; if (levelstate->pages[levelstate->current_page] == NULL) - levelstate->pages[levelstate->current_page] = - palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, 0); + levelstate->pages[levelstate->current_page] = palloc0(BLCKSZ); newPage = levelstate->pages[levelstate->current_page]; gistinitpage(newPage, old_page_flags); @@ -529,7 +496,7 @@ mgist_indexsortbuild_levelstate_flush(MGISTBuildState *state, BlockNumber blkno; MemoryContext oldCtx; IndexTuple union_tuple; - SplitedPageLayout *dist; + SplitPageLayout *dist; IndexTuple *itvec; int vect_len; bool isleaf = GistPageIsLeaf(levelstate->pages[0]); @@ -557,8 +524,8 @@ mgist_indexsortbuild_levelstate_flush(MGISTBuildState *state, } else { - /* Create splitted layout from single page */ - dist = (SplitedPageLayout *) palloc0(sizeof(SplitedPageLayout)); + /* Create split layout from single page */ + dist = (SplitPageLayout *) palloc0(sizeof(SplitPageLayout)); union_tuple = mgistunion(state->indexrel, itvec, vect_len, state->mgiststate); dist->itup = union_tuple; @@ -575,6 +542,7 @@ mgist_indexsortbuild_levelstate_flush(MGISTBuildState *state, for (; dist != NULL; dist = dist->next) { char *data; + BulkWriteBuffer buf; Page target; /* check once per page */ @@ -582,7 +550,8 @@ mgist_indexsortbuild_levelstate_flush(MGISTBuildState *state, /* Create page and copy data */ data = (char *) (dist->list); - target = palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, MCXT_ALLOC_ZERO); + buf = smgr_bulk_get_buf(state->bulkstate); + target = (Page) buf; gistinitpage(target, isleaf ? F_LEAF : 0); for (int i = 0; i < dist->block.num; i++) { @@ -595,20 +564,6 @@ mgist_indexsortbuild_levelstate_flush(MGISTBuildState *state, } union_tuple = dist->itup; - if (state->ready_num_pages == XLR_MAX_BLOCK_ID) - mgist_indexsortbuild_flush_ready_pages(state); - - /* - * The page is now complete. Assign a block number to it, and add it - * to the list of finished pages. (We don't write it out immediately, - * because we want to WAL-log the pages in batches.) - */ - blkno = state->pages_allocated++; - state->ready_blknos[state->ready_num_pages] = blkno; - state->ready_pages[state->ready_num_pages] = target; - state->ready_num_pages++; - ItemPointerSetBlockNumber(&(union_tuple->t_tid), blkno); - /* * Set the right link to point to the previous page. This is just for * debugging purposes: GiST only follows the right link if a page is @@ -623,6 +578,15 @@ mgist_indexsortbuild_levelstate_flush(MGISTBuildState *state, */ if (levelstate->last_blkno) GistPageGetOpaque(target)->rightlink = levelstate->last_blkno; + + /* + * The page is now complete. Assign a block number to it, and pass it + * to the bulk writer. + */ + blkno = state->pages_allocated++; + PageSetLSN(target, GistBuildLSN); + smgr_bulk_write(state->bulkstate, blkno, buf, true); + ItemPointerSetBlockNumber(&(union_tuple->t_tid), blkno); levelstate->last_blkno = blkno; /* @@ -633,7 +597,7 @@ mgist_indexsortbuild_levelstate_flush(MGISTBuildState *state, if (parent == NULL) { parent = palloc0(sizeof(GistSortedBuildLevelState)); - parent->pages[0] = (Page) palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, 0); + parent->pages[0] = palloc(BLCKSZ); parent->parent = NULL; gistinitpage(parent->pages[0], 0); @@ -643,39 +607,6 @@ mgist_indexsortbuild_levelstate_flush(MGISTBuildState *state, } } -static void -mgist_indexsortbuild_flush_ready_pages(MGISTBuildState *state) -{ - if (state->ready_num_pages == 0) - return; - - for (int i = 0; i < state->ready_num_pages; i++) - { - Page page = state->ready_pages[i]; - BlockNumber blkno = state->ready_blknos[i]; - - /* Currently, the blocks must be buffered in order. */ - if (blkno != state->pages_written) - elog(ERROR, "unexpected block number to flush GiST sorting build"); - - PageSetLSN(page, GistBuildLSN); - PageSetChecksumInplace(page, blkno); - smgrextend(RelationGetSmgr(state->indexrel), MAIN_FORKNUM, blkno, page, - true); - - state->pages_written++; - } - - if (RelationNeedsWAL(state->indexrel)) - log_newpages(&state->indexrel->rd_locator, MAIN_FORKNUM, state->ready_num_pages, - state->ready_blknos, state->ready_pages, true); - - for (int i = 0; i < state->ready_num_pages; i++) - pfree(state->ready_pages[i]); - - state->ready_num_pages = 0; -} - /*------------------------------------------------------------------------- * Routines for non-sorted build diff --git a/src/mgist/mgistbuildbuffers.c b/src/mgist/mgistbuildbuffers.c index ad0c48e..5c75714 100644 --- a/src/mgist/mgistbuildbuffers.c +++ b/src/mgist/mgistbuildbuffers.c @@ -14,13 +14,9 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/gist_private.h" -#include "catalog/index.h" -#include "miscadmin.h" #include "storage/buffile.h" #include "storage/bufmgr.h" -#include "utils/memutils.h" #include "utils/rel.h" #include "mgist.h" @@ -165,7 +161,7 @@ mgistGetNodeBuffer(GISTBuildBuffers *gfbb, MGISTSTATE *mgiststate, * not arbitrary that the new buffer is put to the beginning of the * list: in the final emptying phase we loop through all buffers at * each level, and flush them. If a page is split during the emptying, - * it's more efficient to flush the new splitted pages first, before + * it's more efficient to flush the new split pages first, before * moving on to pre-existing pages on the level. The buffers just * created during the page split are likely still in cache, so * flushing them immediately is more efficient than putting them to @@ -520,7 +516,7 @@ gistFreeBuildBuffers(GISTBuildBuffers *gfbb) /* * Data structure representing information about node buffer for index tuples - * relocation from splitted node buffer. + * relocation from split node buffer. */ typedef struct { @@ -551,12 +547,12 @@ mgistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb, MGISTSTATE *mgiststate, GISTNodeBuffer oldBuf; ListCell *lc; - /* If the splitted page doesn't have buffers, we have nothing to do. */ + /* If the split page doesn't have buffers, we have nothing to do. */ if (!LEVEL_HAS_BUFFERS(level, gfbb)) return; /* - * Get the node buffer of the splitted page. + * Get the node buffer of the split page. */ blocknum = BufferGetBlockNumber(buffer); nodeBuffer = hash_search(gfbb->nodeBuffersTab, &blocknum, diff --git a/src/mgist/mgistget.c b/src/mgist/mgistget.c index 1d468ad..64224a8 100644 --- a/src/mgist/mgistget.c +++ b/src/mgist/mgistget.c @@ -20,7 +20,6 @@ #include "lib/pairingheap.h" #include "miscadmin.h" #include "pgstat.h" -#include "storage/lmgr.h" #include "storage/predicate.h" #include "utils/float.h" #include "utils/memutils.h" @@ -384,7 +383,6 @@ mgistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, PredicateLockPage(r, BufferGetBlockNumber(buffer), scan->xs_snapshot); gistcheckpage(scan->indexRelation, buffer); page = BufferGetPage(buffer); - TestForOldSnapshot(scan->xs_snapshot, r, page); opaque = GistPageGetOpaque(page); /* * Check if we need to follow the rightlink. We need to follow it if the diff --git a/src/mgist/mgistutil.c b/src/mgist/mgistutil.c index 6667266..0e10def 100644 --- a/src/mgist/mgistutil.c +++ b/src/mgist/mgistutil.c @@ -18,12 +18,11 @@ #include "access/gist_private.h" #include "access/htup_details.h" #include "access/reloptions.h" -#include "catalog/pg_opclass.h" #include "common/pg_prng.h" #include "storage/indexfsm.h" -#include "storage/lmgr.h" #include "utils/float.h" #include "utils/lsyscache.h" +#include "utils/rel.h" #include "utils/snapmgr.h" #include "utils/syscache.h" @@ -575,7 +574,7 @@ mgistdentryinit(MGISTSTATE *mgiststate, int nkey, GISTENTRY *e, IndexTuple mgistFormTuple(MGISTSTATE *mgiststate, Relation r, - Datum *attdata, bool *isnull, bool isleaf) + const Datum *attdata, bool *isnull, bool isleaf) { Datum compatt[INDEX_MAX_KEYS]; IndexTuple res; @@ -596,7 +595,7 @@ mgistFormTuple(MGISTSTATE *mgiststate, Relation r, void mgistCompressValues(MGISTSTATE *mgiststate, Relation r, - Datum *attdata, bool *isnull, bool isleaf, Datum *compatt) + const Datum *attdata, bool *isnull, bool isleaf, Datum *compatt) { int i; diff --git a/src/mgist/mgistvalidate.c b/src/mgist/mgistvalidate.c index e027a25..0e3ee3c 100644 --- a/src/mgist/mgistvalidate.c +++ b/src/mgist/mgistvalidate.c @@ -21,7 +21,6 @@ #include "catalog/pg_opclass.h" #include "catalog/pg_opfamily.h" #include "catalog/pg_type.h" -#include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/regproc.h" #include "utils/syscache.h" diff --git a/src/mspgist/mspgdoinsert.c b/src/mspgist/mspgdoinsert.c index cbfa314..1aab15f 100644 --- a/src/mspgist/mspgdoinsert.c +++ b/src/mspgist/mspgdoinsert.c @@ -4,7 +4,7 @@ * implementation of insert algorithm * * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -19,6 +19,7 @@ #include "access/spgist_private.h" #include "access/spgxlog.h" #include "access/xloginsert.h" +#include "common/int.h" #include "common/pg_prng.h" #include "miscadmin.h" #include "storage/bufmgr.h" @@ -111,9 +112,7 @@ addNode(SpGistState *state, SpGistInnerTuple tuple, Datum label, int offset) static int cmpOffsetNumbers(const void *a, const void *b) { - if (*(const OffsetNumber *) a == *(const OffsetNumber *) b) - return 0; - return (*(const OffsetNumber *) a > *(const OffsetNumber *) b) ? 1 : -1; + return pg_cmp_u16(*(const OffsetNumber *) a, *(const OffsetNumber *) b); } /* diff --git a/src/mspgist/mspginsert.c b/src/mspgist/mspginsert.c index 8f203d9..f9204a2 100644 --- a/src/mspgist/mspginsert.c +++ b/src/mspgist/mspginsert.c @@ -5,7 +5,7 @@ * * All the actual insertion logic is in spgdoinsert.c. * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -18,14 +18,12 @@ #include "access/genam.h" #include "access/spgist_private.h" -#include "access/spgxlog.h" #include "access/tableam.h" -#include "access/xlog.h" #include "access/xloginsert.h" -#include "catalog/index.h" #include "miscadmin.h" +#include "nodes/execnodes.h" #include "storage/bufmgr.h" -#include "storage/smgr.h" +#include "storage/bulk_write.h" #include "utils/memutils.h" #include "utils/rel.h" diff --git a/src/mspgist/mspgist.h b/src/mspgist/mspgist.h index 89003ca..c882a62 100644 --- a/src/mspgist/mspgist.h +++ b/src/mspgist/mspgist.h @@ -4,7 +4,7 @@ * Public header file for ME-SP-GiST access method. * * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/spgist.h diff --git a/src/mspgist/mspgscan.c b/src/mspgist/mspgscan.c index cbf39a7..4694583 100644 --- a/src/mspgist/mspgscan.c +++ b/src/mspgist/mspgscan.c @@ -4,7 +4,7 @@ * routines for scanning SP-GiST indexes * * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -850,7 +850,7 @@ enum SpGistSpecialOffsetNumbers { SpGistBreakOffsetNumber = InvalidOffsetNumber, SpGistRedirectOffsetNumber = MaxOffsetNumber + 1, - SpGistErrorOffsetNumber = MaxOffsetNumber + 2 + SpGistErrorOffsetNumber = MaxOffsetNumber + 2, }; static OffsetNumber @@ -909,7 +909,7 @@ spgTestLeafTuple(MSpGistScanOpaque so, */ static void mspgWalk(Relation index, MSpGistScanOpaque so, bool scanWholeIndex, - storeRes_func storeRes, Snapshot snapshot) + storeRes_func storeRes) { Buffer buffer = InvalidBuffer; bool reportedSome = false; @@ -963,7 +963,6 @@ mspgWalk(Relation index, MSpGistScanOpaque so, bool scanWholeIndex, /* else new pointer points to the same page, no work needed */ page = BufferGetPage(buffer); - TestForOldSnapshot(snapshot, index, page); isnull = SpGistPageStoresNulls(page) ? true : false; @@ -1051,7 +1050,7 @@ mspggetbitmap(IndexScanDesc scan, TIDBitmap *tbm) so->tbm = tbm; so->ntids = 0; - mspgWalk(scan->indexRelation, so, true, storeBitmap, scan->xs_snapshot); + mspgWalk(scan->indexRelation, so, true, storeBitmap); return so->ntids; } @@ -1172,8 +1171,7 @@ mspggettuple(IndexScanDesc scan, ScanDirection dir) } so->iPtr = so->nPtrs = 0; - mspgWalk(scan->indexRelation, so, false, storeGettuple, - scan->xs_snapshot); + mspgWalk(scan->indexRelation, so, false, storeGettuple); if (so->nPtrs == 0) break; /* must have completed scan */ diff --git a/src/mspgist/mspgutils.c b/src/mspgist/mspgutils.c index cf20f1a..f49d476 100644 --- a/src/mspgist/mspgutils.c +++ b/src/mspgist/mspgutils.c @@ -4,7 +4,7 @@ * various support functions for SP-GiST * * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -28,11 +28,11 @@ #include "parser/parse_coerce.h" #include "storage/bufmgr.h" #include "storage/indexfsm.h" -#include "storage/lmgr.h" -#include "utils/builtins.h" #include "utils/catcache.h" +#include "utils/fmgrprotos.h" #include "utils/index_selfuncs.h" #include "utils/lsyscache.h" +#include "utils/rel.h" #include "utils/syscache.h" #include "mspgist.h" @@ -64,6 +64,7 @@ mspghandler(PG_FUNCTION_ARGS) amroutine->amclusterable = false; amroutine->ampredlocks = false; amroutine->amcanparallel = false; + amroutine->amcanbuildparallel = false; amroutine->amcaninclude = true; amroutine->amusemaintenanceworkmem = false; amroutine->amsummarizing = false; @@ -74,6 +75,7 @@ mspghandler(PG_FUNCTION_ARGS) amroutine->ambuild = mspgbuild; amroutine->ambuildempty = spgbuildempty; amroutine->aminsert = mspginsert; + amroutine->aminsertcleanup = NULL; amroutine->ambulkdelete = spgbulkdelete; amroutine->amvacuumcleanup = spgvacuumcleanup; amroutine->amcanreturn = spgcanreturn; @@ -428,7 +430,7 @@ memcpyInnerDatum(void *target, SpGistTypeDesc *att, Datum datum) */ Size SpGistGetLeafTupleSize(TupleDesc tupleDescriptor, - Datum *datums, bool *isnulls) + const Datum *datums, const bool *isnulls) { Size size; Size data_size; @@ -481,7 +483,7 @@ SpGistGetLeafTupleSize(TupleDesc tupleDescriptor, */ SpGistLeafTuple spgFormLeafTuple(SpGistState *state, ItemPointer heapPtr, - Datum *datums, bool *isnulls) + const Datum *datums, const bool *isnulls) { SpGistLeafTuple tup; TupleDesc tupleDescriptor = state->leafTupDesc; @@ -706,8 +708,7 @@ spgFormDeadTuple(SpGistState *state, int tupstate, if (tupstate == SPGIST_REDIRECT) { ItemPointerSet(&tuple->pointer, blkno, offnum); - Assert(TransactionIdIsValid(state->myXid)); - tuple->xid = state->myXid; + tuple->xid = state->redirectXid; } else { diff --git a/src/mspgist/mspgvacuum.c b/src/mspgist/mspgvacuum.c index 7c98ab5..8454f2b 100644 --- a/src/mspgist/mspgvacuum.c +++ b/src/mspgist/mspgvacuum.c @@ -4,7 +4,7 @@ * vacuum for SP-GiST * * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -20,7 +20,6 @@ #include "access/spgxlog.h" #include "access/transam.h" #include "access/xloginsert.h" -#include "catalog/storage_xlog.h" #include "commands/vacuum.h" #include "miscadmin.h" #include "storage/bufmgr.h" @@ -189,7 +188,9 @@ vacuumLeafPage(spgBulkDeleteState *bds, Relation index, Buffer buffer, /* * Add target TID to pending list if the redirection could have - * happened since VACUUM started. + * happened since VACUUM started. (If xid is invalid, assume it + * must have happened before VACUUM started, since REINDEX + * CONCURRENTLY locks out VACUUM.) * * Note: we could make a tighter test by seeing if the xid is * "running" according to the active snapshot; but snapmgr.c @@ -524,8 +525,17 @@ vacuumRedirectAndPlaceholder(Relation index, Relation heaprel, Buffer buffer) dt = (SpGistDeadTuple) PageGetItem(page, PageGetItemId(page, i)); + /* + * We can convert a REDIRECT to a PLACEHOLDER if there could no longer + * be any index scans "in flight" to it. Such an index scan would + * have to be in a transaction whose snapshot sees the REDIRECT's XID + * as still running, so comparing the XID against global xmin is a + * conservatively safe test. If the XID is invalid, it must have been + * inserted by REINDEX CONCURRENTLY, so we can zap it immediately. + */ if (dt->tupstate == SPGIST_REDIRECT && - GlobalVisTestIsRemovableXid(vistest, dt->xid)) + (!TransactionIdIsValid(dt->xid) || + GlobalVisTestIsRemovableXid(vistest, dt->xid))) { dt->tupstate = SPGIST_PLACEHOLDER; Assert(opaque->nRedirection > 0); diff --git a/src/mspgist/mspgvalidate.c b/src/mspgist/mspgvalidate.c index cad5b34..2815b9a 100644 --- a/src/mspgist/mspgvalidate.c +++ b/src/mspgist/mspgvalidate.c @@ -3,7 +3,7 @@ * spgvalidate.c * Opclass validator for SP-GiST. * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,7 +15,7 @@ #include "access/amvalidate.h" #include "access/htup_details.h" -#include "access/spgist_private.h" +#include "access/spgist.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" diff --git a/src/mspgist/mspgxlog.c b/src/mspgist/mspgxlog.c index 20165bc..4e31d33 100644 --- a/src/mspgist/mspgxlog.c +++ b/src/mspgist/mspgxlog.c @@ -4,7 +4,7 @@ * WAL replay logic for SP-GiST * * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,8 +17,6 @@ #include "access/bufmask.h" #include "access/spgist_private.h" #include "access/spgxlog.h" -#include "access/transam.h" -#include "access/xlog.h" #include "access/xlogutils.h" #include "storage/standby.h" #include "utils/memutils.h" @@ -38,7 +36,7 @@ fillFakeState(SpGistState *state, spgxlogState stateSrc) { memset(state, 0, sizeof(*state)); - state->myXid = stateSrc.myXid; + state->redirectXid = stateSrc.redirectXid; state->isBuild = stateSrc.isBuild; state->deadTupleStorage = palloc0(SGDTSIZE); } diff --git a/src/multirangetypes_mest.c b/src/multirangetypes_mest.c index 3b05d6e..db016a5 100644 --- a/src/multirangetypes_mest.c +++ b/src/multirangetypes_mest.c @@ -18,7 +18,7 @@ #include "access/reloptions.h" #include "access/spgist.h" #include "access/stratnum.h" -#include +#include "utils/array.h" #include "utils/datum.h" #include "utils/fmgrprotos.h" #include "utils/multirangetypes.h" diff --git a/src/path_mest.c b/src/path_mest.c index 0bbe119..9ed4ba3 100644 --- a/src/path_mest.c +++ b/src/path_mest.c @@ -24,8 +24,8 @@ #include "access/spgist_private.h" #include "access/reloptions.h" #include "access/stratnum.h" -#include "utils/builtins.h" #include "utils/float.h" +#include "utils/fmgrprotos.h" #include "utils/fmgroids.h" #include "utils/array.h" #include "utils/lsyscache.h" diff --git a/src/text_mspgist.c b/src/text_mspgist.c index cf386ca..edbf4d7 100644 --- a/src/text_mspgist.c +++ b/src/text_mspgist.c @@ -41,9 +41,10 @@ #include "access/spgist.h" #include "catalog/pg_type.h" +#include "common/int.h" #include "mb/pg_wchar.h" -#include "utils/builtins.h" #include "utils/datum.h" +#include "utils/fmgrprotos.h" #include "utils/pg_locale.h" #include "utils/varlena.h" #include "varatt.h" @@ -325,7 +326,7 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + return pg_cmp_s16(aa->c, bb->c); } Datum