diff options
author | Tom Lane | 2007-11-04 21:25:55 +0000 |
---|---|---|
committer | Tom Lane | 2007-11-04 21:25:55 +0000 |
commit | 5e0377ae7e8e1882ddfdc1a1a66984bab9889f54 (patch) | |
tree | 435933a131119aeb3858298f2b529b76b6222ff5 /src/backend/commands/trigger.c | |
parent | 729d2b08c018d02d61046211defb2c2f02d12b79 (diff) |
Minor improvements to code for converting legacy CREATE CONSTRAINT TRIGGER
commands into proper foreign-key constraints. Believe the constraint name
given in the trigger arguments in preference to the trigger name --- to judge
from Olivier Prenant's example, pg_dump must at some time have used the
autogenerated trigger name there, though AFAICT no current release branch tip
does. Improve the emitted NOTICEs to provide more detail (PK table's name and
column names). Handle the case where pg_dump forgot to provide the FROM table
(a bug that never did get fixed in 7.0.x apparently). This commit doesn't
do anything about the question of what to do with incomplete trigger groups.
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r-- | src/backend/commands/trigger.c | 117 |
1 files changed, 82 insertions, 35 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 98fbe4595ee..8798992ecf9 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 - * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.220 2007/11/04 01:16:19 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.221 2007/11/04 21:25:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -218,7 +218,6 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid) * constraint. Ugly, but necessary for loading old dump files. */ if (stmt->isconstraint && !OidIsValid(constraintOid) && - stmt->constrrel != NULL && list_length(stmt->args) >= 6 && (list_length(stmt->args) % 2) == 0 && RI_FKey_trigger_type(funcoid) != RI_TRIGGER_NONE) @@ -482,9 +481,69 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) { static List *info_list = NIL; + char *constr_name; + char *fk_table_name; + char *pk_table_name; + char fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED; + List *fk_attrs = NIL; + List *pk_attrs = NIL; + StringInfoData buf; bool isupd; OldTriggerInfo *info = NULL; ListCell *l; + int i; + + /* Parse out the trigger arguments */ + constr_name = strVal(linitial(stmt->args)); + fk_table_name = strVal(lsecond(stmt->args)); + pk_table_name = strVal(lthird(stmt->args)); + i = 0; + foreach(l, stmt->args) + { + Value *arg = (Value *) lfirst(l); + + i++; + if (i < 4) /* skip constraint and table names */ + continue; + if (i == 4) /* handle match type */ + { + if (strcmp(strVal(arg), "FULL") == 0) + fk_matchtype = FKCONSTR_MATCH_FULL; + else + fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED; + continue; + } + if (i % 2) + fk_attrs = lappend(fk_attrs, arg); + else + pk_attrs = lappend(pk_attrs, arg); + } + + /* Prepare description of constraint for use in messages */ + initStringInfo(&buf); + appendStringInfo(&buf, "FOREIGN KEY %s(", + quote_identifier(fk_table_name)); + i = 0; + foreach(l, fk_attrs) + { + Value *arg = (Value *) lfirst(l); + + if (i++ > 0) + appendStringInfoChar(&buf, ','); + appendStringInfoString(&buf, quote_identifier(strVal(arg))); + } + appendStringInfo(&buf, ") REFERENCES %s(", + quote_identifier(pk_table_name)); + i = 0; + foreach(l, pk_attrs) + { + Value *arg = (Value *) lfirst(l); + + if (i++ > 0) + appendStringInfoChar(&buf, ','); + appendStringInfoString(&buf, quote_identifier(strVal(arg))); + } + appendStringInfoChar(&buf, ')'); /* Identify class of trigger --- update, delete, or referencing-table */ switch (funcoid) @@ -508,8 +567,8 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) default: /* Ignore triggers on referencing table */ ereport(NOTICE, - (errmsg("ignoring incomplete foreign-key trigger group for constraint \"%s\" on table \"%s\"", - stmt->trigname, stmt->relation->relname))); + (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s", + constr_name, buf.data))); return; } @@ -527,8 +586,8 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) MemoryContext oldContext; ereport(NOTICE, - (errmsg("ignoring incomplete foreign-key trigger group for constraint \"%s\" on table \"%s\"", - stmt->trigname, stmt->constrrel->relname))); + (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s", + constr_name, buf.data))); oldContext = MemoryContextSwitchTo(TopMemoryContext); info = (OldTriggerInfo *) palloc(sizeof(OldTriggerInfo)); info->args = copyObject(stmt->args); @@ -539,49 +598,36 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) } else { - /* OK, we have a pair, so make the FK constraint */ + /* OK, we have a pair, so make the FK constraint ALTER TABLE cmd */ AlterTableStmt *atstmt = makeNode(AlterTableStmt); AlterTableCmd *atcmd = makeNode(AlterTableCmd); FkConstraint *fkcon = makeNode(FkConstraint); - int i; Oid updfunc, delfunc; ereport(NOTICE, - (errmsg("converting foreign-key trigger group into constraint \"%s\" on table \"%s\"", - stmt->trigname, stmt->constrrel->relname))); - atstmt->relation = stmt->constrrel; + (errmsg("converting trigger group into constraint \"%s\" %s", + constr_name, buf.data))); + + if (stmt->constrrel) + atstmt->relation = stmt->constrrel; + else + { + /* Work around ancient pg_dump bug that omitted constrrel */ + atstmt->relation = makeRangeVar(NULL, fk_table_name); + } atstmt->cmds = list_make1(atcmd); atstmt->relkind = OBJECT_TABLE; atcmd->subtype = AT_AddConstraint; atcmd->def = (Node *) fkcon; - if (strcmp(stmt->trigname, "<unnamed>") == 0) + if (strcmp(constr_name, "<unnamed>") == 0) fkcon->constr_name = NULL; else - fkcon->constr_name = stmt->trigname; + fkcon->constr_name = constr_name; fkcon->pktable = stmt->relation; - - i = 0; - foreach(l, stmt->args) - { - Value *arg = (Value *) lfirst(l); - - i++; - if (i < 4) /* ignore constraint and table names */ - continue; - if (i == 4) /* handle match type */ - { - if (strcmp(strVal(arg), "FULL") == 0) - fkcon->fk_matchtype = FKCONSTR_MATCH_FULL; - else - fkcon->fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED; - continue; - } - if (i % 2) - fkcon->fk_attrs = lappend(fkcon->fk_attrs, arg); - else - fkcon->pk_attrs = lappend(fkcon->pk_attrs, arg); - } + fkcon->fk_attrs = fk_attrs; + fkcon->pk_attrs = pk_attrs; + fkcon->fk_matchtype = fk_matchtype; if (isupd) { @@ -638,6 +684,7 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) fkcon->deferrable = stmt->deferrable; fkcon->initdeferred = stmt->initdeferred; + /* ... and execute it */ ProcessUtility((Node *) atstmt, NULL, NULL, false, None_Receiver, NULL); |