mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
Reject system columns as elements of foreign keys.
Up through v11 it was sensible to use the "oid" system column as a foreign key column, but since that was removed there's no visible usefulness in making any of the remaining system columns a foreign key. Moreover, since the TupleTableSlot rewrites in v12, such cases actively fail because of implicit assumptions that only user columns appear in foreign keys. The lack of complaints about that seems like good evidence that no one is trying to do it. Hence, rather than trying to repair those assumptions (of which there are at least two, maybe more), let's just forbid the case up front. Per this patch, a system column in either the referenced or referencing side of a foreign key will draw this error; however, putting one in the referenced side would have failed later anyway, since we don't allow unique indexes to be made on system columns. Per bug #17877 from Alexander Lakhin. Back-patch to v12; the case still appears to work in v11, so we shouldn't break it there. Discussion: https://postgr.es/m/17877-4bcc658e33df6de1@postgresql.org
This commit is contained in:
@ -11271,6 +11271,11 @@ ATExecValidateConstraint(List **wqueue, Relation rel, char *constrName,
|
||||
* transformColumnNameList - transform list of column names
|
||||
*
|
||||
* Lookup each name and return its attnum and, optionally, type OID
|
||||
*
|
||||
* Note: the name of this function suggests that it's general-purpose,
|
||||
* but actually it's only used to look up names appearing in foreign-key
|
||||
* clauses. The error messages would need work to use it in other cases,
|
||||
* and perhaps the validity checks as well.
|
||||
*/
|
||||
static int
|
||||
transformColumnNameList(Oid relId, List *colList,
|
||||
@ -11284,6 +11289,7 @@ transformColumnNameList(Oid relId, List *colList,
|
||||
{
|
||||
char *attname = strVal(lfirst(l));
|
||||
HeapTuple atttuple;
|
||||
Form_pg_attribute attform;
|
||||
|
||||
atttuple = SearchSysCacheAttName(relId, attname);
|
||||
if (!HeapTupleIsValid(atttuple))
|
||||
@ -11291,14 +11297,19 @@ transformColumnNameList(Oid relId, List *colList,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("column \"%s\" referenced in foreign key constraint does not exist",
|
||||
attname)));
|
||||
attform = (Form_pg_attribute) GETSTRUCT(atttuple);
|
||||
if (attform->attnum < 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("system columns cannot be used in foreign keys")));
|
||||
if (attnum >= INDEX_MAX_KEYS)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_TOO_MANY_COLUMNS),
|
||||
errmsg("cannot have more than %d keys in a foreign key",
|
||||
INDEX_MAX_KEYS)));
|
||||
attnums[attnum] = ((Form_pg_attribute) GETSTRUCT(atttuple))->attnum;
|
||||
attnums[attnum] = attform->attnum;
|
||||
if (atttypids != NULL)
|
||||
atttypids[attnum] = ((Form_pg_attribute) GETSTRUCT(atttuple))->atttypid;
|
||||
atttypids[attnum] = attform->atttypid;
|
||||
ReleaseSysCache(atttuple);
|
||||
attnum++;
|
||||
}
|
||||
|
Reference in New Issue
Block a user