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

Commit1978172

Browse files
committed
Make identity sequence management more robust
Some code could get confused when certain catalog state involving bothidentity and serial sequences was present, perhaps during an attemptto upgrade the latter to the former. Specifically, dropping thedefault of a serial column maintains the ownership of the sequence bythe column, and so it would then be possible to afterwards make thecolumn an identity column that would now own two sequences. Thiscauses the code that looks up the identity sequence to error out,making the new identity column inoperable until the ownership of theprevious sequence is released.To fix this, make the identity sequence lookup only consider sequenceswith the appropriate dependency type for an identity sequence, so itonly ever finds one (unless something else is broken). In the aboveexample, the old serial sequence would then be ignored. Reorganizethe various owned-sequence-lookup functions a bit to make thisclearer.Reported-by: Laurenz Albe <laurenz.albe@cybertec.at>Discussion:https://www.postgresql.org/message-id/flat/470c54fc8590be4de0f41b0d295fd6390d5e8a6c.camel@cybertec.at
1 parentefdcca5 commit1978172

File tree

7 files changed

+48
-20
lines changed

7 files changed

+48
-20
lines changed

‎src/backend/catalog/pg_depend.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -705,10 +705,11 @@ sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
705705

706706
/*
707707
* Collect a list of OIDs of all sequences owned by the specified relation,
708-
* and column if specified.
708+
* and column if specified. If deptype is not zero, then only find sequences
709+
* with the specified dependency type.
709710
*/
710-
List*
711-
getOwnedSequences(Oidrelid,AttrNumberattnum)
711+
staticList*
712+
getOwnedSequences_internal(Oidrelid,AttrNumberattnum,chardeptype)
712713
{
713714
List*result=NIL;
714715
RelationdepRel;
@@ -750,7 +751,8 @@ getOwnedSequences(Oid relid, AttrNumber attnum)
750751
(deprec->deptype==DEPENDENCY_AUTO||deprec->deptype==DEPENDENCY_INTERNAL)&&
751752
get_rel_relkind(deprec->objid)==RELKIND_SEQUENCE)
752753
{
753-
result=lappend_oid(result,deprec->objid);
754+
if (!deptype||deprec->deptype==deptype)
755+
result=lappend_oid(result,deprec->objid);
754756
}
755757
}
756758

@@ -762,17 +764,32 @@ getOwnedSequences(Oid relid, AttrNumber attnum)
762764
}
763765

764766
/*
765-
* Get owned sequence, error if not exactly one.
767+
* Collect a list of OIDs of all sequences owned (identity or serial) by the
768+
* specified relation.
769+
*/
770+
List*
771+
getOwnedSequences(Oidrelid)
772+
{
773+
returngetOwnedSequences_internal(relid,0,0);
774+
}
775+
776+
/*
777+
* Get owned identity sequence, error if not exactly one.
766778
*/
767779
Oid
768-
getOwnedSequence(Oidrelid,AttrNumberattnum)
780+
getIdentitySequence(Oidrelid,AttrNumberattnum,boolmissing_ok)
769781
{
770-
List*seqlist=getOwnedSequences(relid,attnum);
782+
List*seqlist=getOwnedSequences_internal(relid,attnum,DEPENDENCY_INTERNAL);
771783

772784
if (list_length(seqlist)>1)
773785
elog(ERROR,"more than one owned sequence found");
774786
elseif (list_length(seqlist)<1)
775-
elog(ERROR,"no owned sequence found");
787+
{
788+
if (missing_ok)
789+
returnInvalidOid;
790+
else
791+
elog(ERROR,"no owned sequence found");
792+
}
776793

777794
returnlinitial_oid(seqlist);
778795
}

‎src/backend/commands/tablecmds.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
16891689
foreach(cell, rels)
16901690
{
16911691
Relationrel = (Relation) lfirst(cell);
1692-
List *seqlist = getOwnedSequences(RelationGetRelid(rel), 0);
1692+
List *seqlist = getOwnedSequences(RelationGetRelid(rel));
16931693
ListCell *seqcell;
16941694

16951695
foreach(seqcell, seqlist)
@@ -6635,7 +6635,7 @@ ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE
66356635
table_close(attrelation, RowExclusiveLock);
66366636

66376637
/* drop the internal sequence */
6638-
seqid =getOwnedSequence(RelationGetRelid(rel), attnum);
6638+
seqid =getIdentitySequence(RelationGetRelid(rel), attnum, false);
66396639
deleteDependencyRecordsForClass(RelationRelationId, seqid,
66406640
RelationRelationId, DEPENDENCY_INTERNAL);
66416641
CommandCounterIncrement();

‎src/backend/parser/parse_utilcmd.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
10831083
* find sequence owned by old column; extract sequence parameters;
10841084
* build new create sequence command
10851085
*/
1086-
seq_relid=getOwnedSequence(RelationGetRelid(relation),attribute->attnum);
1086+
seq_relid=getIdentitySequence(RelationGetRelid(relation),attribute->attnum, false);
10871087
seq_options=sequence_options(seq_relid);
10881088
generateSerialExtraStmts(cxt,def,
10891089
InvalidOid,seq_options, true,
@@ -3165,7 +3165,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
31653165
if (attnum!=InvalidAttrNumber&&
31663166
TupleDescAttr(tupdesc,attnum-1)->attidentity)
31673167
{
3168-
Oidseq_relid=getOwnedSequence(relid,attnum);
3168+
Oidseq_relid=getIdentitySequence(relid,attnum, false);
31693169
OidtypeOid=typenameTypeId(pstate,def->typeName);
31703170
AlterSeqStmt*altseqstmt=makeNode(AlterSeqStmt);
31713171

@@ -3216,7 +3216,6 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
32163216
ListCell*lc;
32173217
List*newseqopts=NIL;
32183218
List*newdef=NIL;
3219-
List*seqlist;
32203219
AttrNumberattnum;
32213220

32223221
/*
@@ -3237,14 +3236,13 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
32373236

32383237
if (attnum)
32393238
{
3240-
seqlist=getOwnedSequences(relid,attnum);
3241-
if (seqlist)
3239+
Oidseq_relid=getIdentitySequence(relid,attnum, true);
3240+
3241+
if (seq_relid)
32423242
{
32433243
AlterSeqStmt*seqstmt;
3244-
Oidseq_relid;
32453244

32463245
seqstmt=makeNode(AlterSeqStmt);
3247-
seq_relid=linitial_oid(seqlist);
32483246
seqstmt->sequence=makeRangeVar(get_namespace_name(get_rel_namespace(seq_relid)),
32493247
get_rel_name(seq_relid),-1);
32503248
seqstmt->options=newseqopts;

‎src/backend/rewrite/rewriteHandler.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,7 @@ build_column_default(Relation rel, int attrno)
11301130
{
11311131
NextValueExpr*nve=makeNode(NextValueExpr);
11321132

1133-
nve->seqid=getOwnedSequence(RelationGetRelid(rel),attrno);
1133+
nve->seqid=getIdentitySequence(RelationGetRelid(rel),attrno, false);
11341134
nve->typeId=att_tup->atttypid;
11351135

11361136
return (Node*)nve;

‎src/include/catalog/dependency.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ extern long changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
209209
externOidgetExtensionOfObject(OidclassId,OidobjectId);
210210

211211
externboolsequenceIsOwned(OidseqId,chardeptype,Oid*tableId,int32*colId);
212-
externList*getOwnedSequences(Oidrelid,AttrNumberattnum);
213-
externOidgetOwnedSequence(Oidrelid,AttrNumberattnum);
212+
externList*getOwnedSequences(Oidrelid);
213+
externOidgetIdentitySequence(Oidrelid,AttrNumberattnum,boolmissing_ok);
214214

215215
externOidget_constraint_index(OidconstraintId);
216216

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,8 @@ CREATE TABLE itest_child PARTITION OF itest_parent (
399399
) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error
400400
ERROR: identity columns are not supported on partitions
401401
DROP TABLE itest_parent;
402+
-- test that sequence of half-dropped serial column is properly ignored
403+
CREATE TABLE itest14 (id serial);
404+
ALTER TABLE itest14 ALTER id DROP DEFAULT;
405+
ALTER TABLE itest14 ALTER id ADD GENERATED BY DEFAULT AS IDENTITY;
406+
INSERT INTO itest14 (id) VALUES (DEFAULT);

‎src/test/regress/sql/identity.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,3 +254,11 @@ CREATE TABLE itest_child PARTITION OF itest_parent (
254254
f3 WITH OPTIONS GENERATED ALWAYSAS IDENTITY
255255
) FORVALUESFROM ('2016-07-01') TO ('2016-08-01');-- error
256256
DROPTABLE itest_parent;
257+
258+
259+
-- test that sequence of half-dropped serial column is properly ignored
260+
261+
CREATETABLEitest14 (idserial);
262+
ALTERTABLE itest14 ALTER id DROP DEFAULT;
263+
ALTERTABLE itest14 ALTER id ADD GENERATED BY DEFAULTAS IDENTITY;
264+
INSERT INTO itest14 (id)VALUES (DEFAULT);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp