diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/indexing.c | 4 | ||||
-rw-r--r-- | src/backend/commands/comment.c | 23 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 6 | ||||
-rw-r--r-- | src/backend/commands/trigger.c | 86 | ||||
-rw-r--r-- | src/backend/utils/cache/relcache.c | 78 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 4 | ||||
-rw-r--r-- | src/include/catalog/indexing.h | 8 | ||||
-rw-r--r-- | src/test/regress/expected/foreign_key.out | 2 |
8 files changed, 110 insertions, 101 deletions
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c index 6ccb1ef0b2b..cc26af128ae 100644 --- a/src/backend/catalog/indexing.c +++ b/src/backend/catalog/indexing.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.91 2002/04/18 20:01:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.92 2002/04/19 16:36:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -74,7 +74,7 @@ char *Name_pg_shadow_indices[Num_pg_shadow_indices] = char *Name_pg_statistic_indices[Num_pg_statistic_indices] = {StatisticRelidAttnumIndex}; char *Name_pg_trigger_indices[Num_pg_trigger_indices] = -{TriggerRelidIndex, TriggerConstrNameIndex, TriggerConstrRelidIndex, TriggerOidIndex}; +{TriggerRelidNameIndex, TriggerConstrNameIndex, TriggerConstrRelidIndex, TriggerOidIndex}; char *Name_pg_type_indices[Num_pg_type_indices] = {TypeNameNspIndex, TypeOidIndex}; char *Name_pg_description_indices[Num_pg_description_indices] = diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 07b14ca4fe2..63c023cf0e2 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1999-2001, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.42 2002/04/18 20:01:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.43 2002/04/19 16:36:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -753,7 +753,7 @@ CommentTrigger(List *qualname, char *comment) Relation pg_trigger, relation; HeapTuple triggertuple; - HeapScanDesc scan; + SysScanDesc scan; ScanKeyData entry[2]; Oid oid; @@ -774,17 +774,22 @@ CommentTrigger(List *qualname, char *comment) elog(ERROR, "you are not permitted to comment on trigger '%s' for relation '%s'", trigname, RelationGetRelationName(relation)); - /* Fetch the trigger oid from pg_trigger */ - + /* + * Fetch the trigger tuple from pg_trigger. There can be only one + * because of the unique index. + */ pg_trigger = heap_openr(TriggerRelationName, AccessShareLock); - ScanKeyEntryInitialize(&entry[0], 0x0, Anum_pg_trigger_tgrelid, + ScanKeyEntryInitialize(&entry[0], 0x0, + Anum_pg_trigger_tgrelid, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); - ScanKeyEntryInitialize(&entry[1], 0x0, Anum_pg_trigger_tgname, + ScanKeyEntryInitialize(&entry[1], 0x0, + Anum_pg_trigger_tgname, F_NAMEEQ, CStringGetDatum(trigname)); - scan = heap_beginscan(pg_trigger, 0, SnapshotNow, 2, entry); - triggertuple = heap_getnext(scan, 0); + scan = systable_beginscan(pg_trigger, TriggerRelidNameIndex, true, + SnapshotNow, 2, entry); + triggertuple = systable_getnext(scan); /* If no trigger exists for the relation specified, notify user */ @@ -794,7 +799,7 @@ CommentTrigger(List *qualname, char *comment) oid = triggertuple->t_data->t_oid; - heap_endscan(scan); + systable_endscan(scan); /* Create the comments with the pg_trigger oid */ diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 8abd8cf80de..b0b73af76e4 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.3 2002/04/18 20:01:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.4 2002/04/19 16:36:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2909,10 +2909,10 @@ update_ri_trigger_args(Oid relid, if (fk_scan) irel = index_openr(TriggerConstrRelidIndex); else - irel = index_openr(TriggerRelidIndex); + irel = index_openr(TriggerRelidNameIndex); ScanKeyEntryInitialize(&skey[0], 0x0, - 1, /* always column 1 of index */ + 1, /* column 1 of index in either case */ F_OIDEQ, ObjectIdGetDatum(relid)); idxtgscan = index_beginscan(irel, false, 1, skey); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 891b9f3cfba..c00b4bebac8 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.113 2002/04/12 20:38:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.114 2002/04/19 16:36:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -90,14 +90,15 @@ CreateTrigger(CreateTrigStmt *stmt) elog(ERROR, "permission denied"); /* - * If trigger is a constraint, user trigger name as constraint name + * If trigger is an RI constraint, use trigger name as constraint name * and build a unique trigger name instead. */ if (stmt->isconstraint) { constrname = stmt->trigname; + snprintf(constrtrigname, sizeof(constrtrigname), + "RI_ConstraintTrigger_%u", newoid()); stmt->trigname = constrtrigname; - sprintf(constrtrigname, "RI_ConstraintTrigger_%u", newoid()); if (stmt->constrrel != NULL) constrrelid = RangeVarGetRelid(stmt->constrrel, false); @@ -139,15 +140,20 @@ CreateTrigger(CreateTrigStmt *stmt) } /* - * Scan pg_trigger for existing triggers on relation. NOTE that this - * is cool only because we have AccessExclusiveLock on the relation, - * so the trigger set won't be changing underneath us. + * Scan pg_trigger for existing triggers on relation. We do this mainly + * because we must count them; a secondary benefit is to give a nice + * error message if there's already a trigger of the same name. (The + * unique index on tgrelid/tgname would complain anyway.) + * + * NOTE that this is cool only because we have AccessExclusiveLock on the + * relation, so the trigger set won't be changing underneath us. */ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid, + ScanKeyEntryInitialize(&key, 0, + Anum_pg_trigger_tgrelid, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(rel))); - tgscan = systable_beginscan(tgrel, TriggerRelidIndex, true, + tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, SnapshotNow, 1, &key); while (HeapTupleIsValid(tuple = systable_getnext(tgscan))) { @@ -336,15 +342,20 @@ DropTrigger(Oid relid, const char *trigname) /* * Search pg_trigger, delete target trigger, count remaining triggers - * for relation. Note this is OK only because we have - * AccessExclusiveLock on the rel, so no one else is creating/deleting - * triggers on this rel at the same time. + * for relation. (Although we could fetch and delete the target + * trigger directly, we'd still have to scan the remaining triggers, + * so we may as well do both in one indexscan.) + * + * Note this is OK only because we have AccessExclusiveLock on the rel, + * so no one else is creating/deleting triggers on this rel at the same + * time. */ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid, + ScanKeyEntryInitialize(&key, 0, + Anum_pg_trigger_tgrelid, F_OIDEQ, ObjectIdGetDatum(relid)); - tgscan = systable_beginscan(tgrel, TriggerRelidIndex, true, + tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, SnapshotNow, 1, &key); while (HeapTupleIsValid(tuple = systable_getnext(tgscan))) { @@ -409,10 +420,11 @@ RelationRemoveTriggers(Relation rel) bool found = false; tgrel = heap_openr(TriggerRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid, + ScanKeyEntryInitialize(&key, 0, + Anum_pg_trigger_tgrelid, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(rel))); - tgscan = systable_beginscan(tgrel, TriggerRelidIndex, true, + tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, SnapshotNow, 1, &key); while (HeapTupleIsValid(tup = systable_getnext(tgscan))) @@ -462,7 +474,8 @@ RelationRemoveTriggers(Relation rel) /* * Also drop all constraint triggers referencing this relation */ - ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgconstrrelid, + ScanKeyEntryInitialize(&key, 0, + Anum_pg_trigger_tgconstrrelid, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(rel))); tgscan = systable_beginscan(tgrel, TriggerConstrRelidIndex, true, @@ -502,7 +515,7 @@ RelationBuildTriggers(Relation relation) { TriggerDesc *trigdesc; int ntrigs = relation->rd_rel->reltriggers; - Trigger *triggers = NULL; + Trigger *triggers; int found = 0; Relation tgrel; ScanKeyData skey; @@ -511,6 +524,15 @@ RelationBuildTriggers(Relation relation) struct varlena *val; bool isnull; + triggers = (Trigger *) MemoryContextAlloc(CacheMemoryContext, + ntrigs * sizeof(Trigger)); + + /* + * Note: since we scan the triggers using TriggerRelidNameIndex, + * we will be reading the triggers in name order, except possibly + * during emergency-recovery operations (ie, IsIgnoringSystemIndexes). + * This in turn ensures that triggers will be fired in name order. + */ ScanKeyEntryInitialize(&skey, (bits16) 0x0, (AttrNumber) Anum_pg_trigger_tgrelid, @@ -518,7 +540,7 @@ RelationBuildTriggers(Relation relation) ObjectIdGetDatum(RelationGetRelid(relation))); tgrel = heap_openr(TriggerRelationName, AccessShareLock); - tgscan = systable_beginscan(tgrel, TriggerRelidIndex, true, + tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, SnapshotNow, 1, &skey); while (HeapTupleIsValid(htup = systable_getnext(tgscan))) @@ -526,16 +548,9 @@ RelationBuildTriggers(Relation relation) Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup); Trigger *build; - if (found == ntrigs) + if (found >= ntrigs) elog(ERROR, "RelationBuildTriggers: unexpected record found for rel %s", RelationGetRelationName(relation)); - - if (triggers == NULL) - triggers = (Trigger *) MemoryContextAlloc(CacheMemoryContext, - sizeof(Trigger)); - else - triggers = (Trigger *) repalloc(triggers, - (found + 1) * sizeof(Trigger)); build = &(triggers[found]); build->tgoid = htup->t_data->t_oid; @@ -730,6 +745,9 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2) * We need not examine the "index" data, just the trigger array * itself; if we have the same triggers with the same types, the * derived index data should match. + * + * As of 7.3 we assume trigger set ordering is significant in the + * comparison; so we just compare corresponding slots of the two sets. */ if (trigdesc1 != NULL) { @@ -740,21 +758,9 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2) for (i = 0; i < trigdesc1->numtriggers; i++) { Trigger *trig1 = trigdesc1->triggers + i; - Trigger *trig2 = NULL; + Trigger *trig2 = trigdesc2->triggers + i; - /* - * We can't assume that the triggers are always read from - * pg_trigger in the same order; so use the trigger OIDs to - * identify the triggers to compare. (We assume here that the - * same OID won't appear twice in either trigger set.) - */ - for (j = 0; j < trigdesc2->numtriggers; j++) - { - trig2 = trigdesc2->triggers + j; - if (trig1->tgoid == trig2->tgoid) - break; - } - if (j >= trigdesc2->numtriggers) + if (trig1->tgoid != trig2->tgoid) return false; if (strcmp(trig1->tgname, trig2->tgname) != 0) return false; diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 686fcc8416b..983055ef783 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.161 2002/04/18 20:01:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.162 2002/04/19 16:36:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -635,10 +635,10 @@ RelationBuildRuleLock(Relation relation) { MemoryContext rulescxt; MemoryContext oldcxt; - HeapTuple pg_rewrite_tuple; - Relation pg_rewrite_desc; - TupleDesc pg_rewrite_tupdesc; - SysScanDesc pg_rewrite_scan; + HeapTuple rewrite_tuple; + Relation rewrite_desc; + TupleDesc rewrite_tupdesc; + SysScanDesc rewrite_scan; ScanKeyData key; RuleLock *rulelock; int numlocks; @@ -657,7 +657,7 @@ RelationBuildRuleLock(Relation relation) relation->rd_rulescxt = rulescxt; /* - * form an array to hold the rewrite rules (the array is extended if + * allocate an array to hold the rewrite rules (the array is extended if * necessary) */ maxlocks = 4; @@ -675,18 +675,22 @@ RelationBuildRuleLock(Relation relation) /* * open pg_rewrite and begin a scan - */ - pg_rewrite_desc = heap_openr(RewriteRelationName, AccessShareLock); - pg_rewrite_tupdesc = RelationGetDescr(pg_rewrite_desc); - pg_rewrite_scan = systable_beginscan(pg_rewrite_desc, - RewriteRelRulenameIndex, - criticalRelcachesBuilt, - SnapshotNow, - 1, &key); - - while (HeapTupleIsValid(pg_rewrite_tuple = systable_getnext(pg_rewrite_scan))) + * + * Note: since we scan the rules using RewriteRelRulenameIndex, + * we will be reading the rules in name order, except possibly + * during emergency-recovery operations (ie, IsIgnoringSystemIndexes). + * This in turn ensures that rules will be fired in name order. + */ + rewrite_desc = heap_openr(RewriteRelationName, AccessShareLock); + rewrite_tupdesc = RelationGetDescr(rewrite_desc); + rewrite_scan = systable_beginscan(rewrite_desc, + RewriteRelRulenameIndex, + true, SnapshotNow, + 1, &key); + + while (HeapTupleIsValid(rewrite_tuple = systable_getnext(rewrite_scan))) { - Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(pg_rewrite_tuple); + Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple); bool isnull; Datum ruleaction; Datum rule_evqual; @@ -697,7 +701,7 @@ RelationBuildRuleLock(Relation relation) rule = (RewriteRule *) MemoryContextAlloc(rulescxt, sizeof(RewriteRule)); - rule->ruleId = pg_rewrite_tuple->t_data->t_oid; + rule->ruleId = rewrite_tuple->t_data->t_oid; rule->event = rewrite_form->ev_type - '0'; rule->attrno = rewrite_form->ev_attr; @@ -705,9 +709,9 @@ RelationBuildRuleLock(Relation relation) /* Must use heap_getattr to fetch ev_qual and ev_action */ - ruleaction = heap_getattr(pg_rewrite_tuple, + ruleaction = heap_getattr(rewrite_tuple, Anum_pg_rewrite_ev_action, - pg_rewrite_tupdesc, + rewrite_tupdesc, &isnull); Assert(!isnull); ruleaction_str = DatumGetCString(DirectFunctionCall1(textout, @@ -717,13 +721,13 @@ RelationBuildRuleLock(Relation relation) MemoryContextSwitchTo(oldcxt); pfree(ruleaction_str); - rule_evqual = heap_getattr(pg_rewrite_tuple, + rule_evqual = heap_getattr(rewrite_tuple, Anum_pg_rewrite_ev_qual, - pg_rewrite_tupdesc, + rewrite_tupdesc, &isnull); Assert(!isnull); rule_evqual_str = DatumGetCString(DirectFunctionCall1(textout, - rule_evqual)); + rule_evqual)); oldcxt = MemoryContextSwitchTo(rulescxt); rule->qual = (Node *) stringToNode(rule_evqual_str); MemoryContextSwitchTo(oldcxt); @@ -741,8 +745,8 @@ RelationBuildRuleLock(Relation relation) /* * end the scan and close the attribute relation */ - systable_endscan(pg_rewrite_scan); - heap_close(pg_rewrite_desc, AccessShareLock); + systable_endscan(rewrite_scan); + heap_close(rewrite_desc, AccessShareLock); /* * form a RuleLock and insert into relation @@ -764,9 +768,13 @@ RelationBuildRuleLock(Relation relation) static bool equalRuleLocks(RuleLock *rlock1, RuleLock *rlock2) { - int i, - j; + int i; + /* + * As of 7.3 we assume the rule ordering is repeatable, + * because RelationBuildRuleLock should read 'em in a + * consistent order. So just compare corresponding slots. + */ if (rlock1 != NULL) { if (rlock2 == NULL) @@ -776,21 +784,9 @@ equalRuleLocks(RuleLock *rlock1, RuleLock *rlock2) for (i = 0; i < rlock1->numLocks; i++) { RewriteRule *rule1 = rlock1->rules[i]; - RewriteRule *rule2 = NULL; + RewriteRule *rule2 = rlock2->rules[i]; - /* - * We can't assume that the rules are always read from - * pg_rewrite in the same order; so use the rule OIDs to - * identify the rules to compare. (We assume here that the - * same OID won't appear twice in either ruleset.) - */ - for (j = 0; j < rlock2->numLocks; j++) - { - rule2 = rlock2->rules[j]; - if (rule1->ruleId == rule2->ruleId) - break; - } - if (j >= rlock2->numLocks) + if (rule1->ruleId != rule2->ruleId) return false; if (rule1->event != rule2->event) return false; diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 4d6742fdbd0..73ecb7fc6bd 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.118 2002/04/18 20:01:10 tgl Exp $ + * $Id: catversion.h,v 1.119 2002/04/19 16:36:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200204181 +#define CATALOG_VERSION_NO 200204182 #endif diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h index e08e3aa8e96..0ee35e3525f 100644 --- a/src/include/catalog/indexing.h +++ b/src/include/catalog/indexing.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: indexing.h,v 1.65 2002/04/18 20:01:10 tgl Exp $ + * $Id: indexing.h,v 1.66 2002/04/19 16:36:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -86,7 +86,7 @@ #define StatisticRelidAttnumIndex "pg_statistic_relid_att_index" #define TriggerConstrNameIndex "pg_trigger_tgconstrname_index" #define TriggerConstrRelidIndex "pg_trigger_tgconstrrelid_index" -#define TriggerRelidIndex "pg_trigger_tgrelid_index" +#define TriggerRelidNameIndex "pg_trigger_tgrelid_tgname_index" #define TriggerOidIndex "pg_trigger_oid_index" #define TypeNameNspIndex "pg_type_typname_nsp_index" #define TypeOidIndex "pg_type_oid_index" @@ -182,9 +182,11 @@ DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index on pg_rewrite using btree(ev_ DECLARE_UNIQUE_INDEX(pg_shadow_usename_index on pg_shadow using btree(usename name_ops)); DECLARE_UNIQUE_INDEX(pg_shadow_usesysid_index on pg_shadow using btree(usesysid int4_ops)); DECLARE_UNIQUE_INDEX(pg_statistic_relid_att_index on pg_statistic using btree(starelid oid_ops, staattnum int2_ops)); +/* This following index is not used for a cache and is not unique */ DECLARE_INDEX(pg_trigger_tgconstrname_index on pg_trigger using btree(tgconstrname name_ops)); +/* This following index is not used for a cache and is not unique */ DECLARE_INDEX(pg_trigger_tgconstrrelid_index on pg_trigger using btree(tgconstrrelid oid_ops)); -DECLARE_INDEX(pg_trigger_tgrelid_index on pg_trigger using btree(tgrelid oid_ops)); +DECLARE_UNIQUE_INDEX(pg_trigger_tgrelid_tgname_index on pg_trigger using btree(tgrelid oid_ops, tgname name_ops)); DECLARE_UNIQUE_INDEX(pg_trigger_oid_index on pg_trigger using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_type_oid_index on pg_type using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index on pg_type using btree(typname name_ops, typnamespace oid_ops)); diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out index 0d0b6a6cb83..7f4c5f8561e 100644 --- a/src/test/regress/expected/foreign_key.out +++ b/src/test/regress/expected/foreign_key.out @@ -899,7 +899,7 @@ delete from pktable where base1=2; ERROR: <unnamed> referential integrity violation - key in pktable still referenced from pktable -- fails (1,1) is being referenced (twice) update pktable set base1=3 where base1=1; -ERROR: <unnamed> referential integrity violation - key in pktable still referenced from pktable +ERROR: <unnamed> referential integrity violation - key referenced from pktable not found in pktable -- this sequence of two deletes will work, since after the first there will be no (2,*) references delete from pktable where base2=2; delete from pktable where base1=2; |