Skip to content

Commit 7bddca3

Browse files
committed
Fix up foreign-key mechanism so that there is a sound semantic basis for the
equality checks it applies, instead of a random dependence on whatever operators might be named "=". The equality operators will now be selected from the opfamily of the unique index that the FK constraint depends on to enforce uniqueness of the referenced columns; therefore they are certain to be consistent with that index's notion of equality. Among other things this should fix the problem noted awhile back that pg_dump may fail for foreign-key constraints on user-defined types when the required operators aren't in the search path. This also means that the former warning condition about "foreign key constraint will require costly sequential scans" is gone: if the comparison condition isn't indexable then we'll reject the constraint entirely. All per past discussions. Along the way, make the RI triggers look into pg_constraint for their information, instead of using pg_trigger.tgargs; and get rid of the always error-prone fixed-size string buffers in ri_triggers.c in favor of building up the RI queries in StringInfo buffers. initdb forced due to columns added to pg_constraint and pg_trigger.
1 parent 65e2f55 commit 7bddca3

33 files changed

+1709
-1643
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.144 2007/01/31 20:56:16 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.145 2007/02/14 01:58:55 tgl Exp $ -->
22
<!--
33
Documentation of the system catalogs, directed toward PostgreSQL developers
44
-->
@@ -1870,6 +1870,27 @@
18701870
<entry>If a foreign key, list of the referenced columns</entry>
18711871
</row>
18721872

1873+
<row>
1874+
<entry><structfield>conpfeqop</structfield></entry>
1875+
<entry><type>oid[]</type></entry>
1876+
<entry><literal><link linkend="catalog-pg-operator"><structname>pg_operator</structname></link>.oid</></entry>
1877+
<entry>If a foreign key, list of the equality operators for PK = FK comparisons</entry>
1878+
</row>
1879+
1880+
<row>
1881+
<entry><structfield>conppeqop</structfield></entry>
1882+
<entry><type>oid[]</type></entry>
1883+
<entry><literal><link linkend="catalog-pg-operator"><structname>pg_operator</structname></link>.oid</></entry>
1884+
<entry>If a foreign key, list of the equality operators for PK = PK comparisons</entry>
1885+
</row>
1886+
1887+
<row>
1888+
<entry><structfield>conffeqop</structfield></entry>
1889+
<entry><type>oid[]</type></entry>
1890+
<entry><literal><link linkend="catalog-pg-operator"><structname>pg_operator</structname></link>.oid</></entry>
1891+
<entry>If a foreign key, list of the equality operators for FK = FK comparisons</entry>
1892+
</row>
1893+
18731894
<row>
18741895
<entry><structfield>conbin</structfield></entry>
18751896
<entry><type>text</type></entry>
@@ -1899,8 +1920,8 @@
18991920
<note>
19001921
<para>
19011922
<literal>pg_class.relchecks</literal> needs to agree with the
1902-
number of check-constraint entries found in this table for the
1903-
given relation.
1923+
number of check-constraint entries found in this table for each
1924+
relation.
19041925
</para>
19051926
</note>
19061927

@@ -4166,35 +4187,42 @@
41664187
<entry><structfield>tgisconstraint</structfield></entry>
41674188
<entry><type>bool</type></entry>
41684189
<entry></entry>
4169-
<entry>True if trigger implements a referential integrity constraint</entry>
4190+
<entry>True if trigger is a <quote>constraint trigger</></entry>
41704191
</row>
41714192

41724193
<row>
41734194
<entry><structfield>tgconstrname</structfield></entry>
41744195
<entry><type>name</type></entry>
41754196
<entry></entry>
4176-
<entry>Referential integrity constraint name</entry>
4197+
<entry>Constraint name, if a constraint trigger</entry>
41774198
</row>
41784199

41794200
<row>
41804201
<entry><structfield>tgconstrrelid</structfield></entry>
41814202
<entry><type>oid</type></entry>
41824203
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
4183-
<entry>The table referenced by an referential integrity constraint</entry>
4204+
<entry>The table referenced by a referential integrity constraint</entry>
4205+
</row>
4206+
4207+
<row>
4208+
<entry><structfield>tgconstraint</structfield></entry>
4209+
<entry><type>oid</type></entry>
4210+
<entry><literal><link linkend="catalog-pg-constraint"><structname>pg_constraint</structname></link>.oid</literal></entry>
4211+
<entry>The <structname>pg_constraint</> entry owning the trigger, if any</entry>
41844212
</row>
41854213

41864214
<row>
41874215
<entry><structfield>tgdeferrable</structfield></entry>
41884216
<entry><type>bool</type></entry>
41894217
<entry></entry>
4190-
<entry>True if deferrable</entry>
4218+
<entry>True if constraint trigger is deferrable</entry>
41914219
</row>
41924220

41934221
<row>
41944222
<entry><structfield>tginitdeferred</structfield></entry>
41954223
<entry><type>bool</type></entry>
41964224
<entry></entry>
4197-
<entry>True if initially deferred</entry>
4225+
<entry>True if constraint trigger is initially deferred</entry>
41984226
</row>
41994227

42004228
<row>
@@ -4221,10 +4249,22 @@
42214249
</tgroup>
42224250
</table>
42234251

4252+
<note>
4253+
<para>
4254+
When <structfield>tgconstraint</> is nonzero,
4255+
<structfield>tgisconstraint</> must be true, and
4256+
<structfield>tgconstrname</>, <structfield>tgconstrrelid</>,
4257+
<structfield>tgdeferrable</>, <structfield>tginitdeferred</> are redundant
4258+
with the referenced <structname>pg_constraint</> entry. The reason we
4259+
keep these fields is that we support <quote>stand-alone</> constraint
4260+
triggers with no corresponding <structname>pg_constraint</> entry.
4261+
</para>
4262+
</note>
4263+
42244264
<note>
42254265
<para>
42264266
<literal>pg_class.reltriggers</literal> needs to agree with the
4227-
number of triggers found in this table for the given relation.
4267+
number of triggers found in this table for each relation.
42284268
</para>
42294269
</note>
42304270

doc/src/sgml/trigger.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.49 2007/02/01 00:28:18 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.50 2007/02/14 01:58:56 tgl Exp $ -->
22

33
<chapter id="triggers">
44
<title>Triggers</title>
@@ -467,6 +467,7 @@ typedef struct Trigger
467467
bool tgenabled;
468468
bool tgisconstraint;
469469
Oid tgconstrrelid;
470+
Oid tgconstraint;
470471
bool tgdeferrable;
471472
bool tginitdeferred;
472473
int16 tgnargs;

src/backend/catalog/aclchk.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.136 2007/02/01 19:10:25 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.137 2007/02/14 01:58:56 tgl Exp $
1212
*
1313
* NOTES
1414
* See acl.h.
@@ -2314,7 +2314,7 @@ pg_conversion_ownercheck(Oid conv_oid, Oid roleid)
23142314
if (superuser_arg(roleid))
23152315
return true;
23162316

2317-
tuple = SearchSysCache(CONOID,
2317+
tuple = SearchSysCache(CONVOID,
23182318
ObjectIdGetDatum(conv_oid),
23192319
0, 0, 0);
23202320
if (!HeapTupleIsValid(tuple))

src/backend/catalog/dependency.c

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.63 2007/02/01 19:10:25 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.64 2007/02/14 01:58:56 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1758,29 +1758,16 @@ getObjectDescription(const ObjectAddress *object)
17581758

17591759
case OCLASS_CONSTRAINT:
17601760
{
1761-
Relation conDesc;
1762-
ScanKeyData skey[1];
1763-
SysScanDesc rcscan;
1764-
HeapTuple tup;
1761+
HeapTuple conTup;
17651762
Form_pg_constraint con;
17661763

1767-
conDesc = heap_open(ConstraintRelationId, AccessShareLock);
1768-
1769-
ScanKeyInit(&skey[0],
1770-
ObjectIdAttributeNumber,
1771-
BTEqualStrategyNumber, F_OIDEQ,
1772-
ObjectIdGetDatum(object->objectId));
1773-
1774-
rcscan = systable_beginscan(conDesc, ConstraintOidIndexId, true,
1775-
SnapshotNow, 1, skey);
1776-
1777-
tup = systable_getnext(rcscan);
1778-
1779-
if (!HeapTupleIsValid(tup))
1780-
elog(ERROR, "could not find tuple for constraint %u",
1764+
conTup = SearchSysCache(CONSTROID,
1765+
ObjectIdGetDatum(object->objectId),
1766+
0, 0, 0);
1767+
if (!HeapTupleIsValid(conTup))
1768+
elog(ERROR, "cache lookup failed for constraint %u",
17811769
object->objectId);
1782-
1783-
con = (Form_pg_constraint) GETSTRUCT(tup);
1770+
con = (Form_pg_constraint) GETSTRUCT(conTup);
17841771

17851772
if (OidIsValid(con->conrelid))
17861773
{
@@ -1794,16 +1781,15 @@ getObjectDescription(const ObjectAddress *object)
17941781
NameStr(con->conname));
17951782
}
17961783

1797-
systable_endscan(rcscan);
1798-
heap_close(conDesc, AccessShareLock);
1784+
ReleaseSysCache(conTup);
17991785
break;
18001786
}
18011787

18021788
case OCLASS_CONVERSION:
18031789
{
18041790
HeapTuple conTup;
18051791

1806-
conTup = SearchSysCache(CONOID,
1792+
conTup = SearchSysCache(CONVOID,
18071793
ObjectIdGetDatum(object->objectId),
18081794
0, 0, 0);
18091795
if (!HeapTupleIsValid(conTup))

src/backend/catalog/heap.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.316 2007/01/05 22:19:24 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.317 2007/02/14 01:58:56 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1463,6 +1463,9 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin)
14631463
InvalidOid, /* not a domain constraint */
14641464
InvalidOid, /* Foreign key fields */
14651465
NULL,
1466+
NULL,
1467+
NULL,
1468+
NULL,
14661469
0,
14671470
' ',
14681471
' ',

src/backend/catalog/index.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.278 2007/02/01 19:10:25 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.279 2007/02/14 01:58:56 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -680,6 +680,9 @@ index_create(Oid heapRelationId,
680680
InvalidOid, /* no domain */
681681
InvalidOid, /* no foreign key */
682682
NULL,
683+
NULL,
684+
NULL,
685+
NULL,
683686
0,
684687
' ',
685688
' ',

src/backend/catalog/namespace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.91 2007/02/01 19:10:25 momjian Exp $
16+
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.92 2007/02/14 01:58:56 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -1199,7 +1199,7 @@ ConversionIsVisible(Oid conid)
11991199
Oid connamespace;
12001200
bool visible;
12011201

1202-
contup = SearchSysCache(CONOID,
1202+
contup = SearchSysCache(CONVOID,
12031203
ObjectIdGetDatum(conid),
12041204
0, 0, 0);
12051205
if (!HeapTupleIsValid(contup))

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy