Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 01b73d3

Browse files
committed
Fix foreign keys on system columns.
1 parent 57dd2ce commit 01b73d3

File tree

4 files changed

+70
-196
lines changed

4 files changed

+70
-196
lines changed

src/backend/commands/command.c

Lines changed: 22 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.144 2001/10/12 00:07:14 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.145 2001/10/23 17:39:02 tgl Exp $
1212
*
1313
* NOTES
1414
* The PerformAddAttribute() code, like most of the relation
@@ -1347,9 +1347,7 @@ AlterTableAddConstraint(char *relationName,
13471347
bool istemp = is_temp_rel_name(relationName);
13481348
List *indexoidlist;
13491349
List *indexoidscan;
1350-
Form_pg_attribute *rel_attrs;
1351-
int num_keys = 0;
1352-
int keys_matched = 0;
1350+
int num_keys;
13531351
bool index_found = false;
13541352
bool index_found_unique = false;
13551353
bool index_found_primary = false;
@@ -1394,15 +1392,9 @@ AlterTableAddConstraint(char *relationName,
13941392
* constraint
13951393
*/
13961394

1397-
rel_attrs = rel->rd_att->attrs;
1398-
1399-
/* Retrieve the oids of all indices on the relation */
1395+
/* Loop over all indices on the relation */
14001396
indexoidlist = RelationGetIndexList(rel);
1401-
index_found = false;
1402-
index_found_unique = false;
1403-
index_found_primary = false;
14041397

1405-
/* Loop over all indices on the relation */
14061398
foreach(indexoidscan, indexoidlist)
14071399
{
14081400
Oid indexoid = lfirsti(indexoidscan);
@@ -1424,43 +1416,41 @@ AlterTableAddConstraint(char *relationName,
14241416
* Make sure this index has the same number of
14251417
* keys as the constraint -- It obviously won't match otherwise.
14261418
*/
1427-
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
1419+
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
1420+
;
14281421
num_keys = length(constr->keys);
1429-
keys_matched = 0;
14301422

14311423
if (i == num_keys)
14321424
{
14331425
/* Loop over each key in the constraint and check that there is a
14341426
corresponding key in the index. */
1427+
int keys_matched = 0;
1428+
14351429
i = 0;
14361430
foreach(keyl, constr->keys)
14371431
{
14381432
Ident *key = lfirst(keyl);
1433+
int keyno = indexStruct->indkey[i];
14391434

14401435
/* Look at key[i] in the index and check that it is over the same column
14411436
as key[i] in the constraint. This is to differentiate between (a,b)
14421437
and (b,a) */
1443-
if (i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0)
1444-
{
1445-
int keyno = indexStruct->indkey[i];
1446-
1447-
if (keyno > 0)
1448-
{
1449-
char *name = NameStr(rel_attrs[keyno - 1]->attname);
1450-
if (strcmp(name, key->name) == 0) keys_matched++;
1451-
}
1452-
}
1453-
else elog(ERROR, "ALTER TABLE/ADD CONSTRAINT: Key \"%u[%u]\" not found", indexoid, i);
1438+
if (namestrcmp(attnumAttName(rel, keyno),
1439+
key->name) == 0)
1440+
keys_matched++;
1441+
else
1442+
break;
14541443
i++;
14551444
}
14561445
if (keys_matched == num_keys) {
14571446
index_found = true;
14581447
index_found_unique = indexStruct->indisunique;
14591448
index_found_primary = indexStruct->indisprimary;
1460-
if (index_found_unique || index_found_primary) break;
14611449
}
14621450
}
14631451
ReleaseSysCache(indexTuple);
1452+
if (index_found_unique || index_found_primary)
1453+
break;
14641454
}
14651455

14661456
freeList(indexoidlist);
@@ -1504,19 +1494,7 @@ AlterTableAddConstraint(char *relationName,
15041494
Trigger trig;
15051495
List *list;
15061496
int count;
1507-
List *indexoidlist,
1508-
*indexoidscan;
1509-
Form_pg_attribute *rel_attrs = NULL;
1510-
int i;
1511-
bool found = false;
1512-
1513-
Oid fktypoid[INDEX_MAX_KEYS];
1514-
Oid pktypoid[INDEX_MAX_KEYS];
1515-
int attloc;
15161497

1517-
for (i=0; i<INDEX_MAX_KEYS; i++)
1518-
fktypoid[i]=pktypoid[i]=0;
1519-
15201498
if (is_temp_rel_name(fkconstraint->pktable_name) &&
15211499
!is_temp_rel_name(relationName))
15221500
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
@@ -1530,140 +1508,21 @@ AlterTableAddConstraint(char *relationName,
15301508
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
15311509
elog(ERROR, "referenced table \"%s\" not a relation",
15321510
fkconstraint->pktable_name);
1511+
heap_close(pkrel, NoLock);
15331512

15341513
/*
1514+
* First we check for limited correctness of the constraint.
1515+
*
1516+
* NOTE: we assume parser has already checked for existence
1517+
* of an appropriate unique index on the referenced relation,
1518+
* and that the column datatypes are comparable.
1519+
*
15351520
* Scan through each tuple, calling the RI_FKey_Match_Ins
15361521
* (insert trigger) as if that tuple had just been
15371522
* inserted. If any of those fail, it should elog(ERROR)
15381523
* and that's that.
15391524
*/
15401525

1541-
/*
1542-
* First we check for limited correctness of the
1543-
* constraint
1544-
*/
1545-
1546-
rel_attrs = pkrel->rd_att->attrs;
1547-
indexoidlist = RelationGetIndexList(pkrel);
1548-
1549-
foreach(indexoidscan, indexoidlist)
1550-
{
1551-
Oid indexoid = lfirsti(indexoidscan);
1552-
HeapTuple indexTuple;
1553-
Form_pg_index indexStruct;
1554-
1555-
indexTuple = SearchSysCache(INDEXRELID,
1556-
ObjectIdGetDatum(indexoid),
1557-
0, 0, 0);
1558-
if (!HeapTupleIsValid(indexTuple))
1559-
elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found",
1560-
indexoid);
1561-
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
1562-
1563-
if (indexStruct->indisunique)
1564-
{
1565-
List *attrl;
1566-
1567-
/*
1568-
* Make sure this index has the same number of
1569-
* keys -- It obviously won't match otherwise.
1570-
*/
1571-
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
1572-
if (i != length(fkconstraint->pk_attrs))
1573-
found = false;
1574-
else
1575-
{
1576-
attloc=0;
1577-
/* go through the fkconstraint->pk_attrs list */
1578-
foreach(attrl, fkconstraint->pk_attrs)
1579-
{
1580-
Ident *attr = lfirst(attrl);
1581-
1582-
found = false;
1583-
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
1584-
{
1585-
int pkattno = indexStruct->indkey[i];
1586-
1587-
if (pkattno > 0)
1588-
{
1589-
char *name = NameStr(rel_attrs[pkattno - 1]->attname);
1590-
1591-
if (strcmp(name, attr->name) == 0)
1592-
{
1593-
/* We get the type of this attribute here and
1594-
* store it so we can use it later for making
1595-
* sure the types are comparable.
1596-
*/
1597-
pktypoid[attloc++]=rel_attrs[pkattno-1]->atttypid;
1598-
found = true;
1599-
break;
1600-
}
1601-
}
1602-
}
1603-
if (!found)
1604-
break;
1605-
}
1606-
}
1607-
}
1608-
ReleaseSysCache(indexTuple);
1609-
if (found)
1610-
break;
1611-
}
1612-
1613-
if (!found)
1614-
elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
1615-
fkconstraint->pktable_name);
1616-
1617-
freeList(indexoidlist);
1618-
heap_close(pkrel, NoLock);
1619-
1620-
rel_attrs = rel->rd_att->attrs;
1621-
if (fkconstraint->fk_attrs != NIL)
1622-
{
1623-
List *fkattrs;
1624-
Ident *fkattr;
1625-
1626-
found = false;
1627-
attloc = 0;
1628-
foreach(fkattrs, fkconstraint->fk_attrs)
1629-
{
1630-
int count;
1631-
1632-
found = false;
1633-
fkattr = lfirst(fkattrs);
1634-
for (count = 0; count < rel->rd_att->natts; count++)
1635-
{
1636-
char *name = NameStr(rel->rd_att->attrs[count]->attname);
1637-
1638-
if (strcmp(name, fkattr->name) == 0)
1639-
{
1640-
/*
1641-
* Here once again we get the types, this
1642-
* time for the fk table's attributes
1643-
*/
1644-
fktypoid[attloc++]=rel->rd_att->attrs[count]->atttypid;
1645-
found = true;
1646-
break;
1647-
}
1648-
}
1649-
if (!found)
1650-
break;
1651-
}
1652-
if (!found)
1653-
elog(ERROR, "columns referenced in foreign key constraint not found.");
1654-
}
1655-
1656-
for (i=0; i < INDEX_MAX_KEYS && fktypoid[i] !=0; i++) {
1657-
/*
1658-
* fktypoid[i] is the foreign key table's i'th element's type oid
1659-
* pktypoid[i] is the primary key table's i'th element's type oid
1660-
* We let oper() do our work for us, including elog(ERROR) if the
1661-
* types can't compare with =
1662-
*/
1663-
Operator o=oper("=", fktypoid[i], pktypoid[i], false);
1664-
ReleaseSysCache(o);
1665-
}
1666-
16671526
trig.tgoid = 0;
16681527
if (fkconstraint->constr_name)
16691528
trig.tgname = fkconstraint->constr_name;
@@ -1706,7 +1565,6 @@ AlterTableAddConstraint(char *relationName,
17061565
trig.tgnargs = count - 1;
17071566

17081567
scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL);
1709-
AssertState(scan != NULL);
17101568

17111569
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
17121570
{

0 commit comments

Comments
 (0)