diff options
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 563 |
1 files changed, 130 insertions, 433 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 001bc571548..cea8ddeabf9 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.213 2007/02/02 00:07:02 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.214 2007/02/14 01:58:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,7 @@ #include "catalog/pg_depend.h" #include "catalog/pg_inherits.h" #include "catalog/pg_namespace.h" +#include "catalog/pg_opclass.h" #include "catalog/pg_trigger.h" #include "catalog/pg_type.h" #include "catalog/toasting.h" @@ -139,6 +140,7 @@ typedef struct NewConstraint char *name; /* Constraint name, or NULL if none */ ConstrType contype; /* CHECK or FOREIGN */ Oid refrelid; /* PK rel, if FOREIGN */ + Oid conid; /* OID of pg_constraint entry, if FOREIGN */ Node *qual; /* Check expr or FkConstraint struct */ List *qualstate; /* Execution state for CHECK */ } NewConstraint; @@ -186,10 +188,9 @@ static Oid transformFkeyCheckAttrs(Relation pkrel, int numattrs, int16 *attnums, Oid *opclasses); static void validateForeignKeyConstraint(FkConstraint *fkconstraint, - Relation rel, Relation pkrel); + Relation rel, Relation pkrel, Oid constraintOid); static void createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint, - Oid constrOid); -static char *fkMatchTypeToString(char match_type); + Oid constraintOid); static void ATController(Relation rel, List *cmds, bool recurse); static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, bool recurse, bool recursing); @@ -256,11 +257,6 @@ static void ATExecEnableDisableTrigger(Relation rel, char *trigname, static void ATExecAddInherit(Relation rel, RangeVar *parent); static void ATExecDropInherit(Relation rel, RangeVar *parent); static void copy_relation_data(Relation rel, SMgrRelation dst); -static void update_ri_trigger_args(Oid relid, - const char *oldname, - const char *newname, - bool fk_scan, - bool update_relname); /* ---------------------------------------------------------------- @@ -1615,21 +1611,6 @@ renameatt(Oid myrelid, heap_close(attrelation, RowExclusiveLock); - /* - * Update att name in any RI triggers associated with the relation. - */ - if (targetrelation->rd_rel->reltriggers > 0) - { - /* update tgargs column reference where att is primary key */ - update_ri_trigger_args(RelationGetRelid(targetrelation), - oldattname, newattname, - false, false); - /* update tgargs column reference where att is foreign key */ - update_ri_trigger_args(RelationGetRelid(targetrelation), - oldattname, newattname, - true, false); - } - relation_close(targetrelation, NoLock); /* close rel but keep lock */ } @@ -1709,226 +1690,12 @@ renamerel(Oid myrelid, const char *newrelname) TypeRename(oldrelname, namespaceId, newrelname); /* - * Update rel name in any RI triggers associated with the relation. - */ - if (relhastriggers) - { - /* update tgargs where relname is primary key */ - update_ri_trigger_args(myrelid, - oldrelname, - newrelname, - false, true); - /* update tgargs where relname is foreign key */ - update_ri_trigger_args(myrelid, - oldrelname, - newrelname, - true, true); - } - - /* * Close rel, but keep exclusive lock! */ relation_close(targetrelation, NoLock); } /* - * Scan pg_trigger for RI triggers that are on the specified relation - * (if fk_scan is false) or have it as the tgconstrrel (if fk_scan - * is true). Update RI trigger args fields matching oldname to contain - * newname instead. If update_relname is true, examine the relname - * fields; otherwise examine the attname fields. - */ -static void -update_ri_trigger_args(Oid relid, - const char *oldname, - const char *newname, - bool fk_scan, - bool update_relname) -{ - Relation tgrel; - ScanKeyData skey[1]; - SysScanDesc trigscan; - HeapTuple tuple; - Datum values[Natts_pg_trigger]; - char nulls[Natts_pg_trigger]; - char replaces[Natts_pg_trigger]; - - tgrel = heap_open(TriggerRelationId, RowExclusiveLock); - if (fk_scan) - { - ScanKeyInit(&skey[0], - Anum_pg_trigger_tgconstrrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid)); - trigscan = systable_beginscan(tgrel, TriggerConstrRelidIndexId, - true, SnapshotNow, - 1, skey); - } - else - { - ScanKeyInit(&skey[0], - Anum_pg_trigger_tgrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid)); - trigscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, - true, SnapshotNow, - 1, skey); - } - - while ((tuple = systable_getnext(trigscan)) != NULL) - { - Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple); - bytea *val; - bytea *newtgargs; - bool isnull; - int tg_type; - bool examine_pk; - bool changed; - int tgnargs; - int i; - int newlen; - const char *arga[RI_MAX_ARGUMENTS]; - const char *argp; - - tg_type = RI_FKey_trigger_type(pg_trigger->tgfoid); - if (tg_type == RI_TRIGGER_NONE) - { - /* Not an RI trigger, forget it */ - continue; - } - - /* - * It is an RI trigger, so parse the tgargs bytea. - * - * NB: we assume the field will never be compressed or moved out of - * line; so does trigger.c ... - */ - tgnargs = pg_trigger->tgnargs; - val = DatumGetByteaP(fastgetattr(tuple, - Anum_pg_trigger_tgargs, - tgrel->rd_att, &isnull)); - if (isnull || tgnargs < RI_FIRST_ATTNAME_ARGNO || - tgnargs > RI_MAX_ARGUMENTS) - { - /* This probably shouldn't happen, but ignore busted triggers */ - continue; - } - argp = (const char *) VARDATA(val); - for (i = 0; i < tgnargs; i++) - { - arga[i] = argp; - argp += strlen(argp) + 1; - } - - /* - * Figure out which item(s) to look at. If the trigger is primary-key - * type and attached to my rel, I should look at the PK fields; if it - * is foreign-key type and attached to my rel, I should look at the FK - * fields. But the opposite rule holds when examining triggers found - * by tgconstrrel search. - */ - examine_pk = (tg_type == RI_TRIGGER_PK) == (!fk_scan); - - changed = false; - if (update_relname) - { - /* Change the relname if needed */ - i = examine_pk ? RI_PK_RELNAME_ARGNO : RI_FK_RELNAME_ARGNO; - if (strcmp(arga[i], oldname) == 0) - { - arga[i] = newname; - changed = true; - } - } - else - { - /* Change attname(s) if needed */ - i = examine_pk ? RI_FIRST_ATTNAME_ARGNO + RI_KEYPAIR_PK_IDX : - RI_FIRST_ATTNAME_ARGNO + RI_KEYPAIR_FK_IDX; - for (; i < tgnargs; i += 2) - { - if (strcmp(arga[i], oldname) == 0) - { - arga[i] = newname; - changed = true; - } - } - } - - if (!changed) - { - /* Don't need to update this tuple */ - continue; - } - - /* - * Construct modified tgargs bytea. - */ - newlen = VARHDRSZ; - for (i = 0; i < tgnargs; i++) - newlen += strlen(arga[i]) + 1; - newtgargs = (bytea *) palloc(newlen); - VARATT_SIZEP(newtgargs) = newlen; - newlen = VARHDRSZ; - for (i = 0; i < tgnargs; i++) - { - strcpy(((char *) newtgargs) + newlen, arga[i]); - newlen += strlen(arga[i]) + 1; - } - - /* - * Build modified tuple. - */ - for (i = 0; i < Natts_pg_trigger; i++) - { - values[i] = (Datum) 0; - replaces[i] = ' '; - nulls[i] = ' '; - } - values[Anum_pg_trigger_tgargs - 1] = PointerGetDatum(newtgargs); - replaces[Anum_pg_trigger_tgargs - 1] = 'r'; - - tuple = heap_modifytuple(tuple, RelationGetDescr(tgrel), values, nulls, replaces); - - /* - * Update pg_trigger and its indexes - */ - simple_heap_update(tgrel, &tuple->t_self, tuple); - - CatalogUpdateIndexes(tgrel, tuple); - - /* - * Invalidate trigger's relation's relcache entry so that other - * backends (and this one too!) are sent SI message to make them - * rebuild relcache entries. (Ideally this should happen - * automatically...) - * - * We can skip this for triggers on relid itself, since that relcache - * flush will happen anyway due to the table or column rename. We - * just need to catch the far ends of RI relationships. - */ - pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple); - if (pg_trigger->tgrelid != relid) - CacheInvalidateRelcacheByRelid(pg_trigger->tgrelid); - - /* free up our scratch memory */ - pfree(newtgargs); - heap_freetuple(tuple); - } - - systable_endscan(trigscan); - - heap_close(tgrel, RowExclusiveLock); - - /* - * Increment cmd counter to make updates visible; this is needed in case - * the same tuple has to be updated again by next pass (can happen in case - * of a self-referential FK relationship). - */ - CommandCounterIncrement(); -} - -/* * AlterTable * Execute ALTER TABLE, which can be a list of subcommands * @@ -2552,7 +2319,8 @@ ATRewriteTables(List **wqueue) refrel = heap_open(con->refrelid, RowShareLock); - validateForeignKeyConstraint(fkconstraint, rel, refrel); + validateForeignKeyConstraint(fkconstraint, rel, refrel, + con->conid); heap_close(refrel, NoLock); } @@ -4061,6 +3829,9 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, Oid pktypoid[INDEX_MAX_KEYS]; Oid fktypoid[INDEX_MAX_KEYS]; Oid opclasses[INDEX_MAX_KEYS]; + Oid pfeqoperators[INDEX_MAX_KEYS]; + Oid ppeqoperators[INDEX_MAX_KEYS]; + Oid ffeqoperators[INDEX_MAX_KEYS]; int i; int numfks, numpks; @@ -4138,6 +3909,9 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, MemSet(pktypoid, 0, sizeof(pktypoid)); MemSet(fktypoid, 0, sizeof(fktypoid)); MemSet(opclasses, 0, sizeof(opclasses)); + MemSet(pfeqoperators, 0, sizeof(pfeqoperators)); + MemSet(ppeqoperators, 0, sizeof(ppeqoperators)); + MemSet(ffeqoperators, 0, sizeof(ffeqoperators)); numfks = transformColumnNameList(RelationGetRelid(rel), fkconstraint->fk_attrs, @@ -4166,7 +3940,15 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, opclasses); } - /* Be sure referencing and referenced column types are comparable */ + /* + * Look up the equality operators to use in the constraint. + * + * Note that we look for operator(s) with the PK type on the left; when + * the types are different this is the right choice because the PK index + * will need operators with the indexkey on the left. Also, we take the + * PK type as being the declared input type of the opclass, which might be + * binary-compatible but not identical to the PK column type. + */ if (numfks != numpks) ereport(ERROR, (errcode(ERRCODE_INVALID_FOREIGN_KEY), @@ -4174,24 +3956,71 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, for (i = 0; i < numpks; i++) { + HeapTuple cla_ht; + Form_pg_opclass cla_tup; + Oid amid; + Oid opfamily; + Oid pktype; + Oid fktype; + Oid pfeqop; + Oid ppeqop; + Oid ffeqop; + int16 eqstrategy; + + /* We need several fields out of the pg_opclass entry */ + cla_ht = SearchSysCache(CLAOID, + ObjectIdGetDatum(opclasses[i]), + 0, 0, 0); + if (!HeapTupleIsValid(cla_ht)) + elog(ERROR, "cache lookup failed for opclass %u", opclasses[i]); + cla_tup = (Form_pg_opclass) GETSTRUCT(cla_ht); + amid = cla_tup->opcmethod; + opfamily = cla_tup->opcfamily; + pktype = cla_tup->opcintype; + ReleaseSysCache(cla_ht); + /* - * pktypoid[i] is the primary key table's i'th key's type fktypoid[i] - * is the foreign key table's i'th key's type - * - * Note that we look for an operator with the PK type on the left; - * when the types are different this is critical because the PK index - * will need operators with the indexkey on the left. (Ordinarily both - * commutator operators will exist if either does, but we won't get - * the right answer from the test below on opclass membership unless - * we select the proper operator.) + * Check it's a btree; currently this can never fail since no other + * index AMs support unique indexes. If we ever did have other + * types of unique indexes, we'd need a way to determine which + * operator strategy number is equality. (Is it reasonable to + * insist that every such index AM use btree's number for equality?) + */ + if (amid != BTREE_AM_OID) + elog(ERROR, "only b-tree indexes are supported for foreign keys"); + eqstrategy = BTEqualStrategyNumber; + + /* + * There had better be a PK = PK operator for the index. + */ + ppeqop = get_opfamily_member(opfamily, pktype, pktype, eqstrategy); + + if (!OidIsValid(ppeqop)) + elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", + eqstrategy, pktype, pktype, opfamily); + + /* + * Are there equality operators that take exactly the FK type? + * Assume we should look through any domain here. */ - Operator o = oper(NULL, list_make1(makeString("=")), - pktypoid[i], fktypoid[i], - true, -1); + fktype = getBaseType(fktypoid[i]); + + pfeqop = get_opfamily_member(opfamily, pktype, fktype, eqstrategy); + ffeqop = get_opfamily_member(opfamily, fktype, fktype, eqstrategy); - if (o == NULL) + if (!(OidIsValid(pfeqop) && OidIsValid(ffeqop))) + { + /* + * Otherwise, look for an implicit cast from the FK type to + * the PK type, and if found, use the PK type's equality operator. + */ + if (can_coerce_type(1, &fktype, &pktype, COERCION_IMPLICIT)) + pfeqop = ffeqop = ppeqop; + } + + if (!(OidIsValid(pfeqop) && OidIsValid(ffeqop))) ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_FUNCTION), + (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("foreign key constraint \"%s\" " "cannot be implemented", fkconstraint->constr_name), @@ -4202,41 +4031,9 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, format_type_be(fktypoid[i]), format_type_be(pktypoid[i])))); - /* - * Check that the found operator is compatible with the PK index, and - * generate a warning if not, since otherwise costly seqscans will be - * incurred to check FK validity. - */ - if (!op_in_opfamily(oprid(o), get_opclass_family(opclasses[i]))) - ereport(WARNING, - (errmsg("foreign key constraint \"%s\" " - "will require costly sequential scans", - fkconstraint->constr_name), - errdetail("Key columns \"%s\" and \"%s\" " - "are of different types: %s and %s.", - strVal(list_nth(fkconstraint->fk_attrs, i)), - strVal(list_nth(fkconstraint->pk_attrs, i)), - format_type_be(fktypoid[i]), - format_type_be(pktypoid[i])))); - - ReleaseSysCache(o); - } - - /* - * Tell Phase 3 to check that the constraint is satisfied by existing rows - * (we can skip this during table creation). - */ - if (!fkconstraint->skip_validation) - { - NewConstraint *newcon; - - newcon = (NewConstraint *) palloc0(sizeof(NewConstraint)); - newcon->name = fkconstraint->constr_name; - newcon->contype = CONSTR_FOREIGN; - newcon->refrelid = RelationGetRelid(pkrel); - newcon->qual = (Node *) fkconstraint; - - tab->constraints = lappend(tab->constraints, newcon); + pfeqoperators[i] = pfeqop; + ppeqoperators[i] = ppeqop; + ffeqoperators[i] = ffeqop; } /* @@ -4254,6 +4051,9 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, * constraint */ RelationGetRelid(pkrel), pkattnum, + pfeqoperators, + ppeqoperators, + ffeqoperators, numpks, fkconstraint->fk_upd_action, fkconstraint->fk_del_action, @@ -4269,6 +4069,24 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, createForeignKeyTriggers(rel, fkconstraint, constrOid); /* + * Tell Phase 3 to check that the constraint is satisfied by existing rows + * (we can skip this during table creation). + */ + if (!fkconstraint->skip_validation) + { + NewConstraint *newcon; + + newcon = (NewConstraint *) palloc0(sizeof(NewConstraint)); + newcon->name = fkconstraint->constr_name; + newcon->contype = CONSTR_FOREIGN; + newcon->refrelid = RelationGetRelid(pkrel); + newcon->conid = constrOid; + newcon->qual = (Node *) fkconstraint; + + tab->constraints = lappend(tab->constraints, newcon); + } + + /* * Close pk table, but keep lock until we've committed. */ heap_close(pkrel, NoLock); @@ -4526,25 +4344,15 @@ transformFkeyCheckAttrs(Relation pkrel, static void validateForeignKeyConstraint(FkConstraint *fkconstraint, Relation rel, - Relation pkrel) + Relation pkrel, + Oid constraintOid) { HeapScanDesc scan; HeapTuple tuple; Trigger trig; - ListCell *list; - int count; /* - * See if we can do it with a single LEFT JOIN query. A FALSE result - * indicates we must proceed with the fire-the-trigger method. - */ - if (RI_Initial_Check(fkconstraint, rel, pkrel)) - return; - - /* - * Scan through each tuple, calling RI_FKey_check_ins (insert trigger) as - * if that tuple had just been inserted. If any of those fail, it should - * ereport(ERROR) and that's that. + * Build a trigger call structure; we'll need it either way. */ MemSet(&trig, 0, sizeof(trig)); trig.tgoid = InvalidOid; @@ -4552,35 +4360,23 @@ validateForeignKeyConstraint(FkConstraint *fkconstraint, trig.tgenabled = TRUE; trig.tgisconstraint = TRUE; trig.tgconstrrelid = RelationGetRelid(pkrel); + trig.tgconstraint = constraintOid; trig.tgdeferrable = FALSE; trig.tginitdeferred = FALSE; + /* we needn't fill in tgargs */ - trig.tgargs = (char **) palloc(sizeof(char *) * - (4 + list_length(fkconstraint->fk_attrs) - + list_length(fkconstraint->pk_attrs))); - - trig.tgargs[0] = trig.tgname; - trig.tgargs[1] = RelationGetRelationName(rel); - trig.tgargs[2] = RelationGetRelationName(pkrel); - trig.tgargs[3] = fkMatchTypeToString(fkconstraint->fk_matchtype); - count = 4; - foreach(list, fkconstraint->fk_attrs) - { - char *fk_at = strVal(lfirst(list)); - - trig.tgargs[count] = fk_at; - count += 2; - } - count = 5; - foreach(list, fkconstraint->pk_attrs) - { - char *pk_at = strVal(lfirst(list)); - - trig.tgargs[count] = pk_at; - count += 2; - } - trig.tgnargs = count - 1; + /* + * See if we can do it with a single LEFT JOIN query. A FALSE result + * indicates we must proceed with the fire-the-trigger method. + */ + if (RI_Initial_Check(&trig, rel, pkrel)) + return; + /* + * Scan through each tuple, calling RI_FKey_check_ins (insert trigger) as + * if that tuple had just been inserted. If any of those fail, it should + * ereport(ERROR) and that's that. + */ scan = heap_beginscan(rel, SnapshotNow, 0, NULL); while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) @@ -4613,18 +4409,13 @@ validateForeignKeyConstraint(FkConstraint *fkconstraint, } heap_endscan(scan); - - pfree(trig.tgargs); } static void CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint, - ObjectAddress *constrobj, ObjectAddress *trigobj, - bool on_insert) + Oid constraintOid, bool on_insert) { CreateTrigStmt *fk_trigger; - ListCell *fk_attr; - ListCell *pk_attr; fk_trigger = makeNode(CreateTrigStmt); fk_trigger->trigname = fkconstraint->constr_name; @@ -4649,32 +4440,9 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint, fk_trigger->deferrable = fkconstraint->deferrable; fk_trigger->initdeferred = fkconstraint->initdeferred; fk_trigger->constrrel = fkconstraint->pktable; - fk_trigger->args = NIL; - fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->constr_name)); - fk_trigger->args = lappend(fk_trigger->args, - makeString(myRel->relname)); - fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable->relname)); - fk_trigger->args = lappend(fk_trigger->args, - makeString(fkMatchTypeToString(fkconstraint->fk_matchtype))); - if (list_length(fkconstraint->fk_attrs) != list_length(fkconstraint->pk_attrs)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FOREIGN_KEY), - errmsg("number of referencing and referenced columns for foreign key disagree"))); - - forboth(fk_attr, fkconstraint->fk_attrs, - pk_attr, fkconstraint->pk_attrs) - { - fk_trigger->args = lappend(fk_trigger->args, lfirst(fk_attr)); - fk_trigger->args = lappend(fk_trigger->args, lfirst(pk_attr)); - } - trigobj->objectId = CreateTrigger(fk_trigger, true); - - /* Register dependency from trigger to constraint */ - recordDependencyOn(trigobj, constrobj, DEPENDENCY_INTERNAL); + (void) CreateTrigger(fk_trigger, constraintOid); /* Make changes-so-far visible */ CommandCounterIncrement(); @@ -4685,14 +4453,10 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint, */ static void createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint, - Oid constrOid) + Oid constraintOid) { RangeVar *myRel; CreateTrigStmt *fk_trigger; - ListCell *fk_attr; - ListCell *pk_attr; - ObjectAddress trigobj, - constrobj; /* * Reconstruct a RangeVar for my relation (not passed in, unfortunately). @@ -4700,15 +4464,6 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint, myRel = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)), pstrdup(RelationGetRelationName(rel))); - /* - * Preset objectAddress fields - */ - constrobj.classId = ConstraintRelationId; - constrobj.objectId = constrOid; - constrobj.objectSubId = 0; - trigobj.classId = TriggerRelationId; - trigobj.objectSubId = 0; - /* Make changes-so-far visible */ CommandCounterIncrement(); @@ -4716,8 +4471,8 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint, * Build and execute a CREATE CONSTRAINT TRIGGER statement for the CHECK * action for both INSERTs and UPDATEs on the referencing table. */ - CreateFKCheckTrigger(myRel, fkconstraint, &constrobj, &trigobj, true); - CreateFKCheckTrigger(myRel, fkconstraint, &constrobj, &trigobj, false); + CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, true); + CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, false); /* * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON @@ -4765,27 +4520,9 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint, (int) fkconstraint->fk_del_action); break; } - fk_trigger->args = NIL; - fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->constr_name)); - fk_trigger->args = lappend(fk_trigger->args, - makeString(myRel->relname)); - fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable->relname)); - fk_trigger->args = lappend(fk_trigger->args, - makeString(fkMatchTypeToString(fkconstraint->fk_matchtype))); - forboth(fk_attr, fkconstraint->fk_attrs, - pk_attr, fkconstraint->pk_attrs) - { - fk_trigger->args = lappend(fk_trigger->args, lfirst(fk_attr)); - fk_trigger->args = lappend(fk_trigger->args, lfirst(pk_attr)); - } - - trigobj.objectId = CreateTrigger(fk_trigger, true); - /* Register dependency from trigger to constraint */ - recordDependencyOn(&trigobj, &constrobj, DEPENDENCY_INTERNAL); + (void) CreateTrigger(fk_trigger, constraintOid); /* Make changes-so-far visible */ CommandCounterIncrement(); @@ -4835,49 +4572,9 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint, (int) fkconstraint->fk_upd_action); break; } - fk_trigger->args = NIL; - fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->constr_name)); - fk_trigger->args = lappend(fk_trigger->args, - makeString(myRel->relname)); - fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable->relname)); - fk_trigger->args = lappend(fk_trigger->args, - makeString(fkMatchTypeToString(fkconstraint->fk_matchtype))); - forboth(fk_attr, fkconstraint->fk_attrs, - pk_attr, fkconstraint->pk_attrs) - { - fk_trigger->args = lappend(fk_trigger->args, lfirst(fk_attr)); - fk_trigger->args = lappend(fk_trigger->args, lfirst(pk_attr)); - } - - trigobj.objectId = CreateTrigger(fk_trigger, true); - /* Register dependency from trigger to constraint */ - recordDependencyOn(&trigobj, &constrobj, DEPENDENCY_INTERNAL); -} - -/* - * fkMatchTypeToString - - * convert FKCONSTR_MATCH_xxx code to string to use in trigger args - */ -static char * -fkMatchTypeToString(char match_type) -{ - switch (match_type) - { - case FKCONSTR_MATCH_FULL: - return pstrdup("FULL"); - case FKCONSTR_MATCH_PARTIAL: - return pstrdup("PARTIAL"); - case FKCONSTR_MATCH_UNSPECIFIED: - return pstrdup("UNSPECIFIED"); - default: - elog(ERROR, "unrecognized match type: %d", - (int) match_type); - } - return NULL; /* can't get here */ + (void) CreateTrigger(fk_trigger, constraintOid); } /* |