Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd90d59e

Browse files
committed
Reject attempts to alter composite types used in indexes.
find_composite_type_dependencies() ignored indexes, which is a poordecision because an expression index could have a stored column ofa composite (or other container) type even when the underlying tabledoes not. Teach it to detect such cases and error out. We have towork a bit harder than for other relations because the pg_depend entrywon't identify the specific index column of concern, but it's not muchnew code.This does not address bug #17872's original complaint that droppinga column in such a type might lead to violations of the uniquenessproperty that a unique index is supposed to ensure. That seems ofmuch less concern to me because it won't lead to crashes.Per bug #17872 from Alexander Lakhin. Back-patch to all supportedbranches.Discussion:https://postgr.es/m/17872-d0fbb799dc3fd85d@postgresql.org
1 parent7c48734 commitd90d59e

File tree

3 files changed

+67
-10
lines changed

3 files changed

+67
-10
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6475,6 +6475,7 @@ find_composite_type_dependencies(Oid typeOid, Relation origRelation,
64756475
{
64766476
Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
64776477
Relationrel;
6478+
TupleDesctupleDesc;
64786479
Form_pg_attribute att;
64796480

64806481
/* Check for directly dependent types */
@@ -6491,18 +6492,57 @@ find_composite_type_dependencies(Oid typeOid, Relation origRelation,
64916492
continue;
64926493
}
64936494

6494-
/* Else, ignore dependees that aren't user columns of relations */
6495-
/* (we assume system columns are never of interesting types) */
6496-
if (pg_depend->classid != RelationRelationId ||
6497-
pg_depend->objsubid <= 0)
6495+
/* Else, ignore dependees that aren't relations */
6496+
if (pg_depend->classid != RelationRelationId)
64986497
continue;
64996498

65006499
rel = relation_open(pg_depend->objid, AccessShareLock);
6501-
att =TupleDescAttr(rel->rd_att, pg_depend->objsubid - 1);
6500+
tupleDesc =RelationGetDescr(rel);
65026501

6503-
if (rel->rd_rel->relkind == RELKIND_RELATION ||
6504-
rel->rd_rel->relkind == RELKIND_MATVIEW ||
6505-
rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6502+
/*
6503+
* If objsubid identifies a specific column, refer to that in error
6504+
* messages. Otherwise, search to see if there's a user column of the
6505+
* type. (We assume system columns are never of interesting types.)
6506+
* The search is needed because an index containing an expression
6507+
* column of the target type will just be recorded as a whole-relation
6508+
* dependency. If we do not find a column of the type, the dependency
6509+
* must indicate that the type is transiently referenced in an index
6510+
* expression but not stored on disk, which we assume is OK, just as
6511+
* we do for references in views. (It could also be that the target
6512+
* type is embedded in some container type that is stored in an index
6513+
* column, but the previous recursion should catch such cases.)
6514+
*/
6515+
if (pg_depend->objsubid > 0 && pg_depend->objsubid <= tupleDesc->natts)
6516+
att = TupleDescAttr(tupleDesc, pg_depend->objsubid - 1);
6517+
else
6518+
{
6519+
att = NULL;
6520+
for (int attno = 1; attno <= tupleDesc->natts; attno++)
6521+
{
6522+
att = TupleDescAttr(tupleDesc, attno - 1);
6523+
if (att->atttypid == typeOid && !att->attisdropped)
6524+
break;
6525+
att = NULL;
6526+
}
6527+
if (att == NULL)
6528+
{
6529+
/* No such column, so assume OK */
6530+
relation_close(rel, AccessShareLock);
6531+
continue;
6532+
}
6533+
}
6534+
6535+
/*
6536+
* We definitely should reject if the relation has storage. If it's
6537+
* partitioned, then perhaps we don't have to reject: if there are
6538+
* partitions then we'll fail when we find one, else there is no
6539+
* stored data to worry about. However, it's possible that the type
6540+
* change would affect conclusions about whether the type is sortable
6541+
* or hashable and thus (if it's a partitioning column) break the
6542+
* partitioning rule. For now, reject for partitioned rels too.
6543+
*/
6544+
if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind) ||
6545+
RELKIND_HAS_PARTITIONS(rel->rd_rel->relkind))
65066546
{
65076547
if (origTypeName)
65086548
ereport(ERROR,

‎src/test/regress/expected/alter_table.out

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3093,6 +3093,13 @@ CREATE TYPE test_type1 AS (a int, b text);
30933093
CREATE TABLE test_tbl1 (x int, y test_type1);
30943094
ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails
30953095
ERROR: cannot alter type "test_type1" because column "test_tbl1.y" uses it
3096+
DROP TABLE test_tbl1;
3097+
CREATE TABLE test_tbl1 (x int, y text);
3098+
CREATE INDEX test_tbl1_idx ON test_tbl1((row(x,y)::test_type1));
3099+
ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails
3100+
ERROR: cannot alter type "test_type1" because column "test_tbl1_idx.row" uses it
3101+
DROP TABLE test_tbl1;
3102+
DROP TYPE test_type1;
30963103
CREATE TYPE test_type2 AS (a int, b text);
30973104
CREATE TABLE test_tbl2 OF test_type2;
30983105
CREATE TABLE test_tbl2_subclass () INHERITS (test_tbl2);
@@ -3204,7 +3211,8 @@ Typed table of type: test_type2
32043211
c | text | | |
32053212
Inherits: test_tbl2
32063213

3207-
DROP TABLE test_tbl2_subclass;
3214+
DROP TABLE test_tbl2_subclass, test_tbl2;
3215+
DROP TYPE test_type2;
32083216
CREATE TYPE test_typex AS (a int, b text);
32093217
CREATE TABLE test_tblx (x int, y test_typex check ((y).a > 0));
32103218
ALTER TYPE test_typex DROP ATTRIBUTE a; -- fails

‎src/test/regress/sql/alter_table.sql

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,14 @@ CREATE TYPE test_type1 AS (a int, b text);
19801980
CREATETABLEtest_tbl1 (xint, y test_type1);
19811981
ALTERTYPE test_type1 ALTER ATTRIBUTE b TYPEvarchar;-- fails
19821982

1983+
DROPTABLE test_tbl1;
1984+
CREATETABLEtest_tbl1 (xint, ytext);
1985+
CREATEINDEXtest_tbl1_idxON test_tbl1((row(x,y)::test_type1));
1986+
ALTERTYPE test_type1 ALTER ATTRIBUTE b TYPEvarchar;-- fails
1987+
1988+
DROPTABLE test_tbl1;
1989+
DROPTYPE test_type1;
1990+
19831991
CREATETYPEtest_type2AS (aint, btext);
19841992
CREATETABLEtest_tbl2 OF test_type2;
19851993
CREATETABLEtest_tbl2_subclass () INHERITS (test_tbl2);
@@ -2007,7 +2015,8 @@ ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE;
20072015
\d test_tbl2
20082016
\d test_tbl2_subclass
20092017

2010-
DROPTABLE test_tbl2_subclass;
2018+
DROPTABLE test_tbl2_subclass, test_tbl2;
2019+
DROPTYPE test_type2;
20112020

20122021
CREATETYPEtest_typexAS (aint, btext);
20132022
CREATETABLEtest_tblx (xint, y test_typexcheck ((y).a>0));

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp