]> granicus.if.org Git - postgresql/commitdiff
Minor improvements to code for converting legacy CREATE CONSTRAINT TRIGGER
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 4 Nov 2007 21:25:55 +0000 (21:25 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 4 Nov 2007 21:25:55 +0000 (21:25 +0000)
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.

src/backend/commands/trigger.c

index 98fbe4595eed6499c4c782a40c6f1ae2a73d9cb5..8798992ecf944069448a9321c0b7a3c2216a61f9 100644 (file)
@@ -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);