mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Reset relhassubclass upon attaching table as a partition
We don't allow inheritance parents as partitions, and have checks to prevent this; but if a table _was_ in the past an inheritance parents and all their children are removed, the pg_class.relhassubclass flag may remain set, which confuses the partition pruning code (most obviously, it results in an assertion failure; in production builds it may be worse.) Fix by resetting relhassubclass on attach. Backpatch to all supported versions. Reported-by: Alexander Lakhin <exclusion@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/18550-d5e047e9a897a889@postgresql.org
This commit is contained in:
		@@ -3518,6 +3518,14 @@ StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound)
 | 
			
		||||
								 new_val, new_null, new_repl);
 | 
			
		||||
	/* Also set the flag */
 | 
			
		||||
	((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * We already checked for no inheritance children, but reset
 | 
			
		||||
	 * relhassubclass in case it was left over.
 | 
			
		||||
	 */
 | 
			
		||||
	if (rel->rd_rel->relkind == RELKIND_RELATION && rel->rd_rel->relhassubclass)
 | 
			
		||||
		((Form_pg_class) GETSTRUCT(newtuple))->relhassubclass = false;
 | 
			
		||||
 | 
			
		||||
	CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
 | 
			
		||||
	heap_freetuple(newtuple);
 | 
			
		||||
	table_close(classRel, RowExclusiveLock);
 | 
			
		||||
 
 | 
			
		||||
@@ -3909,8 +3909,16 @@ ALTER TABLE list_parted ATTACH PARTITION child FOR VALUES IN (1);
 | 
			
		||||
ERROR:  cannot attach inheritance child as partition
 | 
			
		||||
ALTER TABLE list_parted ATTACH PARTITION parent FOR VALUES IN (1);
 | 
			
		||||
ERROR:  cannot attach inheritance parent as partition
 | 
			
		||||
DROP TABLE child;
 | 
			
		||||
-- now it should work, with a little tweak
 | 
			
		||||
ALTER TABLE parent ADD CONSTRAINT check_a CHECK (a > 0);
 | 
			
		||||
ALTER TABLE list_parted ATTACH PARTITION parent FOR VALUES IN (1);
 | 
			
		||||
-- test insert/update, per bug #18550
 | 
			
		||||
INSERT INTO parent VALUES (1);
 | 
			
		||||
UPDATE parent SET a = 2 WHERE a = 1;
 | 
			
		||||
ERROR:  new row for relation "parent" violates partition constraint
 | 
			
		||||
DETAIL:  Failing row contains (2, null).
 | 
			
		||||
DROP TABLE parent CASCADE;
 | 
			
		||||
NOTICE:  drop cascades to table child
 | 
			
		||||
-- check any TEMP-ness
 | 
			
		||||
CREATE TEMP TABLE temp_parted (a int) PARTITION BY LIST (a);
 | 
			
		||||
CREATE TABLE perm_part (a int);
 | 
			
		||||
 
 | 
			
		||||
@@ -2410,6 +2410,13 @@ CREATE TABLE parent (LIKE list_parted);
 | 
			
		||||
CREATE TABLE child () INHERITS (parent);
 | 
			
		||||
ALTER TABLE list_parted ATTACH PARTITION child FOR VALUES IN (1);
 | 
			
		||||
ALTER TABLE list_parted ATTACH PARTITION parent FOR VALUES IN (1);
 | 
			
		||||
DROP TABLE child;
 | 
			
		||||
-- now it should work, with a little tweak
 | 
			
		||||
ALTER TABLE parent ADD CONSTRAINT check_a CHECK (a > 0);
 | 
			
		||||
ALTER TABLE list_parted ATTACH PARTITION parent FOR VALUES IN (1);
 | 
			
		||||
-- test insert/update, per bug #18550
 | 
			
		||||
INSERT INTO parent VALUES (1);
 | 
			
		||||
UPDATE parent SET a = 2 WHERE a = 1;
 | 
			
		||||
DROP TABLE parent CASCADE;
 | 
			
		||||
 | 
			
		||||
-- check any TEMP-ness
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user