Skip to content

Commit 30ec316

Browse files
committed
Add code to extract dependencies from an expression tree, and use it
to build dependencies for rules, constraint expressions, and default expressions. Repair some problems in the original design of recursiveDeletion() exposed by more complex dependency sets. Fix regression tests that were deleting things in illegal sequences.
1 parent 1e07ab7 commit 30ec316

File tree

13 files changed

+768
-140
lines changed

13 files changed

+768
-140
lines changed

src/backend/catalog/dependency.c

Lines changed: 596 additions & 53 deletions
Large diffs are not rendered by default.

src/backend/catalog/heap.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.207 2002/07/15 16:33:31 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.208 2002/07/16 05:53:33 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1157,10 +1157,15 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
11571157
colobject.objectSubId = attnum;
11581158

11591159
recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
1160+
1161+
/*
1162+
* Record dependencies on objects used in the expression, too.
1163+
*/
1164+
recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
11601165
}
11611166

11621167
/*
1163-
* Store a constraint expression for the given relation.
1168+
* Store a check-constraint expression for the given relation.
11641169
* The expression must be presented as a nodeToString() string.
11651170
*
11661171
* Caller is responsible for updating the count of constraints
@@ -1191,6 +1196,10 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin)
11911196

11921197
/*
11931198
* Find columns of rel that are used in ccbin
1199+
*
1200+
* NB: pull_var_clause is okay here only because we don't allow
1201+
* subselects in check constraints; it would fail to examine the
1202+
* contents of subselects.
11941203
*/
11951204
varList = pull_var_clause(expr, false);
11961205
keycount = length(varList);
@@ -1226,15 +1235,16 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin)
12261235
false, /* Is Deferrable */
12271236
false, /* Is Deferred */
12281237
RelationGetRelid(rel), /* relation */
1229-
attNos, /* List of attributes in the constraint */
1230-
keycount, /* # attributes in the constraint */
1238+
attNos, /* attrs in the constraint */
1239+
keycount, /* # attrs in the constraint */
12311240
InvalidOid, /* not a domain constraint */
12321241
InvalidOid, /* Foreign key fields */
12331242
NULL,
12341243
0,
12351244
' ',
12361245
' ',
12371246
' ',
1247+
expr, /* Tree form check constraint */
12381248
ccbin, /* Binary form check constraint */
12391249
ccsrc); /* Source form check constraint */
12401250

src/backend/catalog/index.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.183 2002/07/14 21:08:08 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.184 2002/07/16 05:53:33 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -712,7 +712,8 @@ index_create(Oid heapRelationId,
712712
' ',
713713
' ',
714714
' ',
715-
NULL, /* Constraint Bin & Src */
715+
NULL, /* no check constraint */
716+
NULL,
716717
NULL);
717718

718719
referenced.classId = get_system_catalog_relid(ConstraintRelationName);

src/backend/catalog/pg_constraint.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.1 2002/07/12 18:43:15 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.2 2002/07/16 05:53:33 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -52,6 +52,7 @@ CreateConstraintEntry(const char *constraintName,
5252
char foreignUpdateType,
5353
char foreignDeleteType,
5454
char foreignMatchType,
55+
Node *conExpr,
5556
const char *conBin,
5657
const char *conSrc)
5758
{
@@ -227,6 +228,24 @@ CreateConstraintEntry(const char *constraintName,
227228
}
228229
}
229230

231+
if (conExpr != NULL)
232+
{
233+
/*
234+
* Register dependencies from constraint to objects mentioned
235+
* in CHECK expression. We gin up a rather bogus rangetable
236+
* list to handle any Vars in the constraint.
237+
*/
238+
RangeTblEntry rte;
239+
240+
MemSet(&rte, 0, sizeof(rte));
241+
rte.type = T_RangeTblEntry;
242+
rte.rtekind = RTE_RELATION;
243+
rte.relid = relId;
244+
245+
recordDependencyOnExpr(&conobject, conExpr, makeList1(&rte),
246+
DEPENDENCY_NORMAL);
247+
}
248+
230249
return conOid;
231250
}
232251

src/backend/catalog/pg_depend.c

Lines changed: 56 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.1 2002/07/12 18:43:15 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.2 2002/07/16 05:53:33 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -38,13 +38,30 @@ void
3838
recordDependencyOn(const ObjectAddress *depender,
3939
const ObjectAddress *referenced,
4040
DependencyType behavior)
41+
{
42+
recordMultipleDependencies(depender, referenced, 1, behavior);
43+
}
44+
45+
/*
46+
* Record multiple dependencies (of the same kind) for a single dependent
47+
* object. This has a little less overhead than recording each separately.
48+
*/
49+
void
50+
recordMultipleDependencies(const ObjectAddress *depender,
51+
const ObjectAddress *referenced,
52+
int nreferenced,
53+
DependencyType behavior)
4154
{
4255
Relation dependDesc;
4356
HeapTuple tup;
4457
int i;
4558
char nulls[Natts_pg_depend];
4659
Datum values[Natts_pg_depend];
4760
Relation idescs[Num_pg_depend_indices];
61+
bool indices_opened = false;
62+
63+
if (nreferenced <= 0)
64+
return; /* nothing to do */
4865

4966
/*
5067
* During bootstrap, do nothing since pg_depend may not exist yet.
@@ -55,44 +72,51 @@ recordDependencyOn(const ObjectAddress *depender,
5572

5673
dependDesc = heap_openr(DependRelationName, RowExclusiveLock);
5774

58-
/*
59-
* If the referenced object is pinned by the system, there's no real
60-
* need to record dependencies on it. This saves lots of space in
61-
* pg_depend, so it's worth the time taken to check.
62-
*/
63-
if (!isObjectPinned(referenced, dependDesc))
75+
memset(nulls, ' ', sizeof(nulls));
76+
77+
for (i = 0; i < nreferenced; i++, referenced++)
6478
{
6579
/*
66-
* Record the Dependency. Note we don't bother to check for
67-
* duplicate dependencies; there's no harm in them.
80+
* If the referenced object is pinned by the system, there's no real
81+
* need to record dependencies on it. This saves lots of space in
82+
* pg_depend, so it's worth the time taken to check.
6883
*/
69-
for (i = 0; i < Natts_pg_depend; ++i)
84+
if (!isObjectPinned(referenced, dependDesc))
7085
{
71-
nulls[i] = ' ';
72-
values[i] = (Datum) 0;
86+
/*
87+
* Record the Dependency. Note we don't bother to check for
88+
* duplicate dependencies; there's no harm in them.
89+
*/
90+
values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
91+
values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
92+
values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
93+
94+
values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
95+
values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
96+
values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
97+
98+
values[Anum_pg_depend_deptype -1] = CharGetDatum((char) behavior);
99+
100+
tup = heap_formtuple(dependDesc->rd_att, values, nulls);
101+
102+
simple_heap_insert(dependDesc, tup);
103+
104+
/*
105+
* Keep indices current
106+
*/
107+
if (!indices_opened)
108+
{
109+
CatalogOpenIndices(Num_pg_depend_indices, Name_pg_depend_indices, idescs);
110+
indices_opened = true;
111+
}
112+
CatalogIndexInsert(idescs, Num_pg_depend_indices, dependDesc, tup);
113+
114+
heap_freetuple(tup);
73115
}
116+
}
74117

75-
values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
76-
values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
77-
values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
78-
79-
values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
80-
values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
81-
values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
82-
83-
values[Anum_pg_depend_deptype -1] = CharGetDatum((char) behavior);
84-
85-
tup = heap_formtuple(dependDesc->rd_att, values, nulls);
86-
87-
simple_heap_insert(dependDesc, tup);
88-
89-
/*
90-
* Keep indices current
91-
*/
92-
CatalogOpenIndices(Num_pg_depend_indices, Name_pg_depend_indices, idescs);
93-
CatalogIndexInsert(idescs, Num_pg_depend_indices, dependDesc, tup);
118+
if (indices_opened)
94119
CatalogCloseIndices(Num_pg_depend_indices, idescs);
95-
}
96120

97121
heap_close(dependDesc, RowExclusiveLock);
98122
}

src/backend/commands/tablecmds.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.21 2002/07/15 16:33:31 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.22 2002/07/16 05:53:33 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2708,6 +2708,7 @@ createForeignKeyConstraint(Relation rel, Relation pkrel,
27082708
fkconstraint->fk_upd_action,
27092709
fkconstraint->fk_del_action,
27102710
fkconstraint->fk_matchtype,
2711+
NULL, /* no check constraint */
27112712
NULL,
27122713
NULL);
27132714
}

src/backend/rewrite/rewriteDefine.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.74 2002/07/12 18:43:17 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.75 2002/07/16 05:53:34 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -47,9 +47,11 @@ InsertRule(char *rulname,
4747
Oid eventrel_oid,
4848
AttrNumber evslot_index,
4949
bool evinstead,
50-
char *evqual,
51-
char *actiontree)
50+
Node *event_qual,
51+
List *action)
5252
{
53+
char *evqual = nodeToString(event_qual);
54+
char *actiontree = nodeToString((Node *) action);
5355
int i;
5456
Datum values[Natts_pg_rewrite];
5557
char nulls[Natts_pg_rewrite];
@@ -123,6 +125,21 @@ InsertRule(char *rulname,
123125
recordDependencyOn(&myself, &referenced,
124126
(evtype == CMD_SELECT) ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO);
125127

128+
/*
129+
* Also install dependencies on objects referenced in action and qual.
130+
*/
131+
recordDependencyOnExpr(&myself, (Node *) action, NIL,
132+
DEPENDENCY_NORMAL);
133+
if (event_qual != NULL)
134+
{
135+
/* Find query containing OLD/NEW rtable entries */
136+
Query *qry = (Query *) lfirst(action);
137+
138+
qry = getInsertSelectQuery(qry, NULL);
139+
recordDependencyOnExpr(&myself, event_qual, qry->rtable,
140+
DEPENDENCY_NORMAL);
141+
}
142+
126143
heap_close(pg_rewrite_desc, RowExclusiveLock);
127144

128145
return rewriteObjectId;
@@ -141,8 +158,6 @@ DefineQueryRewrite(RuleStmt *stmt)
141158
Oid ruleId;
142159
int event_attno;
143160
Oid event_attype;
144-
char *actionP,
145-
*event_qualP;
146161
List *l;
147162
Query *query;
148163
AclResult aclresult;
@@ -342,16 +357,13 @@ DefineQueryRewrite(RuleStmt *stmt)
342357
/* discard rule if it's null action and not INSTEAD; it's a no-op */
343358
if (action != NIL || is_instead)
344359
{
345-
event_qualP = nodeToString(event_qual);
346-
actionP = nodeToString(action);
347-
348360
ruleId = InsertRule(stmt->rulename,
349361
event_type,
350362
ev_relid,
351363
event_attno,
352364
is_instead,
353-
event_qualP,
354-
actionP);
365+
event_qual,
366+
action);
355367

356368
/*
357369
* Set pg_class 'relhasrules' field TRUE for event relation. If

src/include/catalog/dependency.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: dependency.h,v 1.1 2002/07/12 18:43:19 tgl Exp $
10+
* $Id: dependency.h,v 1.2 2002/07/16 05:53:34 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -83,10 +83,19 @@ typedef struct ObjectAddress
8383
extern void performDeletion(const ObjectAddress *object,
8484
DropBehavior behavior);
8585

86+
extern void recordDependencyOnExpr(const ObjectAddress *depender,
87+
Node *expr, List *rtable,
88+
DependencyType behavior);
89+
8690
/* in pg_depend.c */
8791

8892
extern void recordDependencyOn(const ObjectAddress *depender,
8993
const ObjectAddress *referenced,
9094
DependencyType behavior);
9195

96+
extern void recordMultipleDependencies(const ObjectAddress *depender,
97+
const ObjectAddress *referenced,
98+
int nreferenced,
99+
DependencyType behavior);
100+
92101
#endif /* DEPENDENCY_H */

src/include/catalog/pg_constraint.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $Id: pg_constraint.h,v 1.1 2002/07/12 18:43:19 tgl Exp $
11+
* $Id: pg_constraint.h,v 1.2 2002/07/16 05:53:34 tgl Exp $
1212
*
1313
* NOTES
1414
* the genbki.sh script reads this file and generates .bki
@@ -158,6 +158,7 @@ extern Oid CreateConstraintEntry(const char *constraintName,
158158
char foreignUpdateType,
159159
char foreignDeleteType,
160160
char foreignMatchType,
161+
Node *conExpr,
161162
const char *conBin,
162163
const char *conSrc);
163164

src/test/regress/expected/privileges.out

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -544,13 +544,19 @@ from (select oid from pg_class where relname = 'atest1') as t1;
544544
\c regression
545545
DROP FUNCTION testfunc2(int);
546546
DROP FUNCTION testfunc4(boolean);
547-
DROP TABLE atest1;
548-
DROP TABLE atest2;
549-
DROP TABLE atest3;
550547
DROP VIEW atestv1;
551548
DROP VIEW atestv2;
552-
DROP VIEW atestv3;
549+
-- this should cascade to drop atestv4
550+
DROP VIEW atestv3 CASCADE;
551+
NOTICE: Drop cascades to rule _RETURN on view atestv3
552+
NOTICE: Drop cascades to rule _RETURN on view atestv4
553+
NOTICE: Drop cascades to view atestv4
554+
-- this should complain "does not exist"
553555
DROP VIEW atestv4;
556+
ERROR: view "atestv4" does not exist
557+
DROP TABLE atest1;
558+
DROP TABLE atest2;
559+
DROP TABLE atest3;
554560
DROP GROUP regressgroup1;
555561
DROP GROUP regressgroup2;
556562
DROP USER regressuser1;

0 commit comments

Comments
 (0)