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

Commitc7d2ce7

Browse files
committed
Repair problems with duplicate index names generated when CREATE TABLE
specifies redundant UNIQUE conditions.
1 parent4a66f9d commitc7d2ce7

File tree

1 file changed

+76
-73
lines changed

1 file changed

+76
-73
lines changed

‎src/backend/parser/analyze.c

Lines changed: 76 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
*$Id: analyze.c,v 1.179 2001/02/1421:35:01 tgl Exp $
9+
*$Id: analyze.c,v 1.180 2001/02/1423:32:38 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -606,7 +606,8 @@ makeObjectName(char *name1, char *name2, char *typename)
606606
}
607607

608608
staticchar*
609-
CreateIndexName(char*table_name,char*column_name,char*label,List*indices)
609+
CreateIndexName(char*table_name,char*column_name,
610+
char*label,List*indices)
610611
{
611612
intpass=0;
612613
char*iname=NULL;
@@ -617,7 +618,8 @@ CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
617618
* The type name for makeObjectName is label, or labelN if that's
618619
* necessary to prevent collisions among multiple indexes for the same
619620
* table. Note there is no check for collisions with already-existing
620-
* indexes; this ought to be rethought someday.
621+
* indexes, only among the indexes we're about to create now; this ought
622+
* to be improved someday.
621623
*/
622624
strcpy(typename,label);
623625

@@ -629,14 +631,15 @@ CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
629631
{
630632
IndexStmt*index=lfirst(ilist);
631633

632-
if (strcmp(iname,index->idxname)==0)
634+
if (index->idxname!=NULL&&
635+
strcmp(iname,index->idxname)==0)
633636
break;
634637
}
635638
/* ran through entire list? then no name conflict found so done */
636639
if (ilist==NIL)
637640
break;
638641

639-
/*the last one conflicted, so try a new name component */
642+
/*found a conflict, so try a new name component */
640643
pfree(iname);
641644
sprintf(typename,"%s%d",label,++pass);
642645
}
@@ -745,9 +748,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
745748

746749
constraint=makeNode(Constraint);
747750
constraint->contype=CONSTR_UNIQUE;
748-
constraint->name=makeObjectName(stmt->relname,
749-
column->colname,
750-
"key");
751+
constraint->name=NULL;/* assign later */
751752
column->constraints=lappend(column->constraints,
752753
constraint);
753754

@@ -919,13 +920,9 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
919920
stmt->constraints=constraints;
920921

921922
/* Now run through the "deferred list" to complete the query transformation.
922-
* For PRIMARY KEYs, mark each column as NOT NULL and create an index.
923-
* For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
924-
*
925-
* Note that this code does not currently look for all possible redundant cases
926-
*and either ignore or stop with warning. The create might fail later when
927-
*names for indices turn out to be duplicated, or a user might have specified
928-
*extra useless indices which might hurt performance. - thomas 1997-12-08
923+
* For PRIMARY KEY, mark each column as NOT NULL and create an index.
924+
* For UNIQUE, create an index as for PRIMARY KEY, but do not insist on
925+
* NOT NULL.
929926
*/
930927
while (dlist!=NIL)
931928
{
@@ -943,15 +940,15 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
943940
if (pkey!=NULL)
944941
elog(ERROR,"CREATE TABLE/PRIMARY KEY multiple primary keys"
945942
" for table '%s' are not allowed",stmt->relname);
946-
pkey=(IndexStmt*)index;
943+
pkey=index;
947944
}
948945

949946
if (constraint->name!=NULL)
950947
index->idxname=pstrdup(constraint->name);
951948
elseif (constraint->contype==CONSTR_PRIMARY)
952949
index->idxname=makeObjectName(stmt->relname,NULL,"pkey");
953950
else
954-
index->idxname=NULL;
951+
index->idxname=NULL;/* will set it later */
955952

956953
index->relname=stmt->relname;
957954
index->accessMethod="btree";
@@ -995,10 +992,10 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
995992
intcount;
996993

997994
Assert(IsA(inh,String));
998-
rel=heap_openr(inh->val.str,AccessShareLock);
995+
rel=heap_openr(strVal(inh),AccessShareLock);
999996
if (rel->rd_rel->relkind!=RELKIND_RELATION)
1000997
elog(ERROR,"inherited table \"%s\" is not a relation",
1001-
inh->val.str);
998+
strVal(inh));
1002999
for (count=0;count<rel->rd_att->natts;count++)
10031000
{
10041001
Form_pg_attributeinhattr=rel->rd_att->attrs[count];
@@ -1020,7 +1017,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
10201017
* error if the inherited column won't be NOT NULL.
10211018
* (Would a NOTICE be more reasonable?)
10221019
*/
1023-
if (!inhattr->attnotnull)
1020+
if (constraint->contype==CONSTR_PRIMARY&&
1021+
!inhattr->attnotnull)
10241022
elog(ERROR,"inherited attribute \"%s\" cannot be a PRIMARY KEY because it is not marked NOT NULL",
10251023
inhname);
10261024
break;
@@ -1041,78 +1039,85 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
10411039
iparam->args=NIL;
10421040
iparam->class=NULL;
10431041
index->indexParams=lappend(index->indexParams,iparam);
1044-
1045-
if (index->idxname==NULL)
1046-
index->idxname=CreateIndexName(stmt->relname,iparam->name,
1047-
"key",ilist);
10481042
}
10491043

1050-
if (index->idxname==NULL)/* should not happen */
1051-
elog(ERROR,"CREATE TABLE: failed to make implicit index name");
1052-
10531044
ilist=lappend(ilist,index);
10541045
dlist=lnext(dlist);
10551046
}
10561047

1057-
/* OK, now finally, if there is a primary key, then make sure that there aren't any redundant
1058-
* unique indices defined on columns. This can arise if someone specifies UNIQUE explicitly
1059-
* or if a SERIAL column was defined along with a table PRIMARY KEY constraint.
1060-
* - thomas 1999-05-11
1061-
*/
1048+
/*
1049+
* Scan the index list and remove any redundant index specifications.
1050+
* This can happen if, for instance, the user writes SERIAL PRIMARY KEY
1051+
* or SERIAL UNIQUE. A strict reading of SQL92 would suggest raising
1052+
* an error instead, but that strikes me as too anal-retentive.
1053+
* - tgl 2001-02-14
1054+
*/
1055+
dlist=ilist;
1056+
ilist=NIL;
10621057
if (pkey!=NULL)
10631058
{
1064-
dlist=ilist;
1065-
ilist=NIL;
1066-
while (dlist!=NIL)
1067-
{
1068-
List*pcols,
1069-
*icols;
1070-
intplen,
1071-
ilen;
1072-
intkeep= TRUE;
1073-
1074-
index=lfirst(dlist);
1075-
pcols=pkey->indexParams;
1076-
icols=index->indexParams;
1059+
/* Make sure we keep the PKEY index in preference to others... */
1060+
ilist=makeList1(pkey);
1061+
}
1062+
while (dlist!=NIL)
1063+
{
1064+
index=lfirst(dlist);
10771065

1078-
plen=length(pcols);
1079-
ilen=length(icols);
1066+
/* if it's pkey, it's already in ilist */
1067+
if (index!=pkey)
1068+
{
1069+
boolkeep= true;
1070+
List*priorlist;
10801071

1081-
/* Not the same as the primary key? Then we should look... */
1082-
if ((index!=pkey)&& (ilen==plen))
1072+
foreach(priorlist,ilist)
10831073
{
1084-
keep= FALSE;
1085-
while ((pcols!=NIL)&& (icols!=NIL))
1086-
{
1087-
IndexElem*pcol=lfirst(pcols);
1088-
IndexElem*icol=lfirst(icols);
1089-
char*pname=pcol->name;
1090-
char*iname=icol->name;
1074+
IndexStmt*priorindex=lfirst(priorlist);
10911075

1092-
/* different names? then no match... */
1093-
if (strcmp(iname,pname)!=0)
1094-
{
1095-
keep= TRUE;
1096-
break;
1097-
}
1098-
pcols=lnext(pcols);
1099-
icols=lnext(icols);
1076+
if (equal(index->indexParams,priorindex->indexParams))
1077+
{
1078+
/*
1079+
* If the prior index is as yet unnamed, and this one
1080+
* is named, then transfer the name to the prior index.
1081+
* This ensures that if we have named and unnamed
1082+
* constraints, we'll use (at least one of) the names
1083+
* for the index.
1084+
*/
1085+
if (priorindex->idxname==NULL)
1086+
priorindex->idxname=index->idxname;
1087+
keep= false;
1088+
break;
11001089
}
11011090
}
11021091

11031092
if (keep)
11041093
ilist=lappend(ilist,index);
1105-
dlist=lnext(dlist);
11061094
}
1095+
1096+
dlist=lnext(dlist);
11071097
}
11081098

1099+
/*
1100+
* Finally, select unique names for all not-previously-named indices,
1101+
* and display notice messages.
1102+
*/
11091103
dlist=ilist;
11101104
while (dlist!=NIL)
11111105
{
11121106
index=lfirst(dlist);
1107+
1108+
if (index->idxname==NULL&&index->indexParams!=NIL)
1109+
{
1110+
iparam=lfirst(index->indexParams);
1111+
index->idxname=CreateIndexName(stmt->relname,iparam->name,
1112+
"key",ilist);
1113+
}
1114+
if (index->idxname==NULL)/* should not happen */
1115+
elog(ERROR,"CREATE TABLE: failed to make implicit index name");
1116+
11131117
elog(NOTICE,"CREATE TABLE/%s will create implicit index '%s' for table '%s'",
11141118
(index->primary ?"PRIMARY KEY" :"UNIQUE"),
11151119
index->idxname,stmt->relname);
1120+
11161121
dlist=lnext(dlist);
11171122
}
11181123

@@ -1123,7 +1128,6 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
11231128
/*
11241129
* Now process the FOREIGN KEY constraints and add appropriate queries
11251130
* to the extras_after statements list.
1126-
*
11271131
*/
11281132
if (fkconstraints!=NIL)
11291133
{
@@ -1173,16 +1177,15 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
11731177
List*inhRelnames=stmt->inhRelnames;
11741178
Relationrel;
11751179
foreach (inher,inhRelnames) {
1176-
intcount=0;
11771180
Value*inh=lfirst(inher);
1178-
if (inh->type!=T_String) {
1179-
elog(ERROR,"inherited table name list returns a non-string");
1180-
}
1181-
rel=heap_openr(inh->val.str,AccessShareLock);
1181+
intcount;
1182+
1183+
Assert(IsA(inh,String));
1184+
rel=heap_openr(strVal(inh),AccessShareLock);
11821185
if (rel->rd_rel->relkind!=RELKIND_RELATION)
11831186
elog(ERROR,"inherited table \"%s\" is not a relation",
1184-
inh->val.str);
1185-
for (;count<rel->rd_att->natts;count++) {
1187+
strVal(inh));
1188+
for (count=0;count<rel->rd_att->natts;count++) {
11861189
char*name=NameStr(rel->rd_att->attrs[count]->attname);
11871190
if (strcmp(fkattr->name,name)==0) {
11881191
found=1;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp