mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-11-27 07:21:09 +08:00
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.
This commit is contained in:
parent
729d2b08c0
commit
5e0377ae7e
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user