aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/spgist/spgutils.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2023-12-21 12:43:36 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2023-12-21 12:43:36 -0500
commit903737c5bf9431c2f983c87ac211082418341805 (patch)
tree440bb2e65621830c13b165e37a88950a00ec4ef2 /src/backend/access/spgist/spgutils.c
parent0590480132bf5db7383a90a29e7b3e29a2a4743a (diff)
downloadpostgresql-903737c5bf9431c2f983c87ac211082418341805.tar.gz
postgresql-903737c5bf9431c2f983c87ac211082418341805.zip
Avoid trying to fetch metapage of an SPGist partitioned index.
This is necessary when spgcanreturn() is invoked on a partitioned index, and the failure might be reachable in other scenarios as well. The rest of what spgGetCache() does is perfectly sensible for a partitioned index, so we should allow it to go through. I think the main takeaway from this is that we lack sufficient test coverage for non-btree partitioned indexes. Therefore, I added simple test cases for brin and gin as well as spgist (hash and gist AMs were covered already in indexing.sql). Per bug #18256 from Alexander Lakhin. Although the known test case only fails since v16 (3c569049b), I've got no faith at all that there aren't other ways to reach this problem; so back-patch to all supported branches. Discussion: https://postgr.es/m/18256-0b0e1b6e4a620f1b@postgresql.org
Diffstat (limited to 'src/backend/access/spgist/spgutils.c')
-rw-r--r--src/backend/access/spgist/spgutils.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c
index fd4b6157101..a8055c51a2d 100644
--- a/src/backend/access/spgist/spgutils.c
+++ b/src/backend/access/spgist/spgutils.c
@@ -188,8 +188,6 @@ spgGetCache(Relation index)
Oid atttype;
spgConfigIn in;
FmgrInfo *procinfo;
- Buffer metabuffer;
- SpGistMetaPageData *metadata;
cache = MemoryContextAllocZero(index->rd_indexcxt,
sizeof(SpGistCache));
@@ -257,19 +255,28 @@ spgGetCache(Relation index)
fillTypeDesc(&cache->attPrefixType, cache->config.prefixType);
fillTypeDesc(&cache->attLabelType, cache->config.labelType);
- /* Last, get the lastUsedPages data from the metapage */
- metabuffer = ReadBuffer(index, SPGIST_METAPAGE_BLKNO);
- LockBuffer(metabuffer, BUFFER_LOCK_SHARE);
+ /*
+ * Finally, if it's a real index (not a partitioned one), get the
+ * lastUsedPages data from the metapage
+ */
+ if (index->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
+ {
+ Buffer metabuffer;
+ SpGistMetaPageData *metadata;
+
+ metabuffer = ReadBuffer(index, SPGIST_METAPAGE_BLKNO);
+ LockBuffer(metabuffer, BUFFER_LOCK_SHARE);
- metadata = SpGistPageGetMeta(BufferGetPage(metabuffer));
+ metadata = SpGistPageGetMeta(BufferGetPage(metabuffer));
- if (metadata->magicNumber != SPGIST_MAGIC_NUMBER)
- elog(ERROR, "index \"%s\" is not an SP-GiST index",
- RelationGetRelationName(index));
+ if (metadata->magicNumber != SPGIST_MAGIC_NUMBER)
+ elog(ERROR, "index \"%s\" is not an SP-GiST index",
+ RelationGetRelationName(index));
- cache->lastUsedPages = metadata->lastUsedPages;
+ cache->lastUsedPages = metadata->lastUsedPages;
- UnlockReleaseBuffer(metabuffer);
+ UnlockReleaseBuffer(metabuffer);
+ }
index->rd_amcache = (void *) cache;
}