1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-16 06:01:02 +03:00

Be more clear when a new column name collides with a system column name.

We now use the same error message for ALTER TABLE .. ADD COLUMN or
ALTER TABLE .. RENAME COLUMN that we do for CREATE TABLE.  The old
message was accurate, but might be confusing to users not aware of our
system columns.

Vik Reykja, with some changes by me, and further proofreading by Tom Lane
This commit is contained in:
Robert Haas
2012-01-26 12:44:30 -05:00
parent d4bad4e1e1
commit 2d1371d3ee
4 changed files with 49 additions and 21 deletions

View File

@ -304,6 +304,7 @@ static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recu
static void ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
ColumnDef *colDef, bool isOid,
bool recurse, bool recursing, LOCKMODE lockmode);
static void check_for_column_name_collision(Relation rel, const char *colname);
static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid);
static void add_column_collation_dependency(Oid relid, int32 attnum, Oid collid);
static void ATPrepAddOids(List **wqueue, Relation rel, bool recurse,
@ -2257,15 +2258,7 @@ renameatt_internal(Oid myrelid,
oldattname)));
/* new name should not already exist */
/* this test is deliberately not attisdropped-aware */
if (SearchSysCacheExists2(ATTNAME,
ObjectIdGetDatum(myrelid),
PointerGetDatum(newattname)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_COLUMN),
errmsg("column \"%s\" of relation \"%s\" already exists",
newattname, RelationGetRelationName(targetrelation))));
check_for_column_name_collision(targetrelation, newattname);
/* apply the update */
namestrcpy(&(attform->attname), newattname);
@ -4310,17 +4303,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
elog(ERROR, "cache lookup failed for relation %u", myrelid);
relkind = ((Form_pg_class) GETSTRUCT(reltup))->relkind;
/*
* this test is deliberately not attisdropped-aware, since if one tries to
* add a column matching a dropped column name, it's gonna fail anyway.
*/
if (SearchSysCacheExists2(ATTNAME,
ObjectIdGetDatum(myrelid),
PointerGetDatum(colDef->colname)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_COLUMN),
errmsg("column \"%s\" of relation \"%s\" already exists",
colDef->colname, RelationGetRelationName(rel))));
/* new name should not already exist */
check_for_column_name_collision(rel, colDef->colname);
/* Determine the new attribute's number */
if (isOid)
@ -4562,6 +4546,46 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
}
}
/*
* If a new or renamed column will collide with the name of an existing
* column, error out.
*/
static void
check_for_column_name_collision(Relation rel, const char *colname)
{
HeapTuple attTuple;
int attnum;
/*
* this test is deliberately not attisdropped-aware, since if one tries to
* add a column matching a dropped column name, it's gonna fail anyway.
*/
attTuple = SearchSysCache2(ATTNAME,
ObjectIdGetDatum(RelationGetRelid(rel)),
PointerGetDatum(colname));
if (!HeapTupleIsValid(attTuple))
return;
attnum = ((Form_pg_attribute) GETSTRUCT(attTuple))->attnum;
ReleaseSysCache(attTuple);
/*
* We throw a different error message for conflicts with system column
* names, since they are normally not shown and the user might otherwise
* be confused about the reason for the conflict.
*/
if (attnum <= 0)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_COLUMN),
errmsg("column name \"%s\" conflicts with a system column name",
colname)));
else
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_COLUMN),
errmsg("column \"%s\" of relation \"%s\" already exists",
colname, RelationGetRelationName(rel))));
}
/*
* Install a column's dependency on its datatype.
*/