mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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
			
			
This commit is contained in:
		@@ -185,8 +185,6 @@ spgGetCache(Relation index)
 | 
			
		||||
		Oid			atttype;
 | 
			
		||||
		spgConfigIn in;
 | 
			
		||||
		FmgrInfo   *procinfo;
 | 
			
		||||
		Buffer		metabuffer;
 | 
			
		||||
		SpGistMetaPageData *metadata;
 | 
			
		||||
 | 
			
		||||
		cache = MemoryContextAllocZero(index->rd_indexcxt,
 | 
			
		||||
									   sizeof(SpGistCache));
 | 
			
		||||
@@ -254,19 +252,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;
 | 
			
		||||
 | 
			
		||||
		metadata = SpGistPageGetMeta(BufferGetPage(metabuffer));
 | 
			
		||||
			metabuffer = ReadBuffer(index, SPGIST_METAPAGE_BLKNO);
 | 
			
		||||
			LockBuffer(metabuffer, BUFFER_LOCK_SHARE);
 | 
			
		||||
 | 
			
		||||
		if (metadata->magicNumber != SPGIST_MAGIC_NUMBER)
 | 
			
		||||
			elog(ERROR, "index \"%s\" is not an SP-GiST index",
 | 
			
		||||
				 RelationGetRelationName(index));
 | 
			
		||||
			metadata = SpGistPageGetMeta(BufferGetPage(metabuffer));
 | 
			
		||||
 | 
			
		||||
		cache->lastUsedPages = metadata->lastUsedPages;
 | 
			
		||||
			if (metadata->magicNumber != SPGIST_MAGIC_NUMBER)
 | 
			
		||||
				elog(ERROR, "index \"%s\" is not an SP-GiST index",
 | 
			
		||||
					 RelationGetRelationName(index));
 | 
			
		||||
 | 
			
		||||
		UnlockReleaseBuffer(metabuffer);
 | 
			
		||||
			cache->lastUsedPages = metadata->lastUsedPages;
 | 
			
		||||
 | 
			
		||||
			UnlockReleaseBuffer(metabuffer);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		index->rd_amcache = (void *) cache;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user