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

Commit334cc4c

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 parent11213d4 commit334cc4c

File tree

3 files changed

+68
-10
lines changed

3 files changed

+68
-10
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6296,6 +6296,7 @@ find_composite_type_dependencies(Oid typeOid, Relation origRelation,
62966296
{
62976297
Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
62986298
Relationrel;
6299+
TupleDesctupleDesc;
62996300
Form_pg_attribute att;
63006301

63016302
/* Check for directly dependent types */
@@ -6312,18 +6313,58 @@ find_composite_type_dependencies(Oid typeOid, Relation origRelation,
63126313
continue;
63136314
}
63146315

6315-
/* Else, ignore dependees that aren't user columns of relations */
6316-
/* (we assume system columns are never of interesting types) */
6317-
if (pg_depend->classid != RelationRelationId ||
6318-
pg_depend->objsubid <= 0)
6316+
/* Else, ignore dependees that aren't relations */
6317+
if (pg_depend->classid != RelationRelationId)
63196318
continue;
63206319

63216320
rel = relation_open(pg_depend->objid, AccessShareLock);
6322-
att =TupleDescAttr(rel->rd_att, pg_depend->objsubid - 1);
6321+
tupleDesc =RelationGetDescr(rel);
63236322

6324-
if (rel->rd_rel->relkind == RELKIND_RELATION ||
6325-
rel->rd_rel->relkind == RELKIND_MATVIEW ||
6326-
rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6323+
/*
6324+
* If objsubid identifies a specific column, refer to that in error
6325+
* messages. Otherwise, search to see if there's a user column of the
6326+
* type. (We assume system columns are never of interesting types.)
6327+
* The search is needed because an index containing an expression
6328+
* column of the target type will just be recorded as a whole-relation
6329+
* dependency. If we do not find a column of the type, the dependency
6330+
* must indicate that the type is transiently referenced in an index
6331+
* expression but not stored on disk, which we assume is OK, just as
6332+
* we do for references in views. (It could also be that the target
6333+
* type is embedded in some container type that is stored in an index
6334+
* column, but the previous recursion should catch such cases.)
6335+
*/
6336+
if (pg_depend->objsubid > 0 && pg_depend->objsubid <= tupleDesc->natts)
6337+
att = TupleDescAttr(tupleDesc, pg_depend->objsubid - 1);
6338+
else
6339+
{
6340+
att = NULL;
6341+
for (int attno = 1; attno <= tupleDesc->natts; attno++)
6342+
{
6343+
att = TupleDescAttr(tupleDesc, attno - 1);
6344+
if (att->atttypid == typeOid && !att->attisdropped)
6345+
break;
6346+
att = NULL;
6347+
}
6348+
if (att == NULL)
6349+
{
6350+
/* No such column, so assume OK */
6351+
relation_close(rel, AccessShareLock);
6352+
continue;
6353+
}
6354+
}
6355+
6356+
/*
6357+
* We definitely should reject if the relation has storage. If it's
6358+
* partitioned, then perhaps we don't have to reject: if there are
6359+
* partitions then we'll fail when we find one, else there is no
6360+
* stored data to worry about. However, it's possible that the type
6361+
* change would affect conclusions about whether the type is sortable
6362+
* or hashable and thus (if it's a partitioning column) break the
6363+
* partitioning rule. For now, reject for partitioned rels too.
6364+
*/
6365+
if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind) ||
6366+
rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
6367+
rel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
63276368
{
63286369
if (origTypeName)
63296370
ereport(ERROR,

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3095,6 +3095,13 @@ CREATE TYPE test_type1 AS (a int, b text);
30953095
CREATE TABLE test_tbl1 (x int, y test_type1);
30963096
ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails
30973097
ERROR: cannot alter type "test_type1" because column "test_tbl1.y" uses it
3098+
DROP TABLE test_tbl1;
3099+
CREATE TABLE test_tbl1 (x int, y text);
3100+
CREATE INDEX test_tbl1_idx ON test_tbl1((row(x,y)::test_type1));
3101+
ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails
3102+
ERROR: cannot alter type "test_type1" because column "test_tbl1_idx.row" uses it
3103+
DROP TABLE test_tbl1;
3104+
DROP TYPE test_type1;
30983105
CREATE TYPE test_type2 AS (a int, b text);
30993106
CREATE TABLE test_tbl2 OF test_type2;
31003107
CREATE TABLE test_tbl2_subclass () INHERITS (test_tbl2);
@@ -3206,7 +3213,8 @@ Typed table of type: test_type2
32063213
c | text | | |
32073214
Inherits: test_tbl2
32083215

3209-
DROP TABLE test_tbl2_subclass;
3216+
DROP TABLE test_tbl2_subclass, test_tbl2;
3217+
DROP TYPE test_type2;
32103218
CREATE TYPE test_typex AS (a int, b text);
32113219
CREATE TABLE test_tblx (x int, y test_typex check ((y).a > 0));
32123220
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
@@ -1984,6 +1984,14 @@ CREATE TYPE test_type1 AS (a int, b text);
19841984
CREATETABLEtest_tbl1 (xint, y test_type1);
19851985
ALTERTYPE test_type1 ALTER ATTRIBUTE b TYPEvarchar;-- fails
19861986

1987+
DROPTABLE test_tbl1;
1988+
CREATETABLEtest_tbl1 (xint, ytext);
1989+
CREATEINDEXtest_tbl1_idxON test_tbl1((row(x,y)::test_type1));
1990+
ALTERTYPE test_type1 ALTER ATTRIBUTE b TYPEvarchar;-- fails
1991+
1992+
DROPTABLE test_tbl1;
1993+
DROPTYPE test_type1;
1994+
19871995
CREATETYPEtest_type2AS (aint, btext);
19881996
CREATETABLEtest_tbl2 OF test_type2;
19891997
CREATETABLEtest_tbl2_subclass () INHERITS (test_tbl2);
@@ -2011,7 +2019,8 @@ ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE;
20112019
\d test_tbl2
20122020
\d test_tbl2_subclass
20132021

2014-
DROPTABLE test_tbl2_subclass;
2022+
DROPTABLE test_tbl2_subclass, test_tbl2;
2023+
DROPTYPE test_type2;
20152024

20162025
CREATETYPEtest_typexAS (aint, btext);
20172026
CREATETABLEtest_tblx (xint, y test_typexcheck ((y).a>0));

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp