77 * Portions Copyright (c) 1994, Regents of the University of California
88 *
99 * IDENTIFICATION
10- * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.220 2007/11/0401:16:19 tgl Exp $
10+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.221 2007/11/0421:25:55 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -218,7 +218,6 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
218218 * constraint. Ugly, but necessary for loading old dump files.
219219 */
220220if (stmt -> isconstraint && !OidIsValid (constraintOid )&&
221- stmt -> constrrel != NULL &&
222221list_length (stmt -> args ) >=6 &&
223222(list_length (stmt -> args ) %2 )== 0 &&
224223RI_FKey_trigger_type (funcoid )!= RI_TRIGGER_NONE )
@@ -482,9 +481,69 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
482481{
483482static List * info_list = NIL ;
484483
484+ char * constr_name ;
485+ char * fk_table_name ;
486+ char * pk_table_name ;
487+ char fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED ;
488+ List * fk_attrs = NIL ;
489+ List * pk_attrs = NIL ;
490+ StringInfoData buf ;
485491bool isupd ;
486492OldTriggerInfo * info = NULL ;
487493ListCell * l ;
494+ int i ;
495+
496+ /* Parse out the trigger arguments */
497+ constr_name = strVal (linitial (stmt -> args ));
498+ fk_table_name = strVal (lsecond (stmt -> args ));
499+ pk_table_name = strVal (lthird (stmt -> args ));
500+ i = 0 ;
501+ foreach (l ,stmt -> args )
502+ {
503+ Value * arg = (Value * )lfirst (l );
504+
505+ i ++ ;
506+ if (i < 4 )/* skip constraint and table names */
507+ continue ;
508+ if (i == 4 )/* handle match type */
509+ {
510+ if (strcmp (strVal (arg ),"FULL" )== 0 )
511+ fk_matchtype = FKCONSTR_MATCH_FULL ;
512+ else
513+ fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED ;
514+ continue ;
515+ }
516+ if (i %2 )
517+ fk_attrs = lappend (fk_attrs ,arg );
518+ else
519+ pk_attrs = lappend (pk_attrs ,arg );
520+ }
521+
522+ /* Prepare description of constraint for use in messages */
523+ initStringInfo (& buf );
524+ appendStringInfo (& buf ,"FOREIGN KEY %s(" ,
525+ quote_identifier (fk_table_name ));
526+ i = 0 ;
527+ foreach (l ,fk_attrs )
528+ {
529+ Value * arg = (Value * )lfirst (l );
530+
531+ if (i ++ > 0 )
532+ appendStringInfoChar (& buf ,',' );
533+ appendStringInfoString (& buf ,quote_identifier (strVal (arg )));
534+ }
535+ appendStringInfo (& buf ,") REFERENCES %s(" ,
536+ quote_identifier (pk_table_name ));
537+ i = 0 ;
538+ foreach (l ,pk_attrs )
539+ {
540+ Value * arg = (Value * )lfirst (l );
541+
542+ if (i ++ > 0 )
543+ appendStringInfoChar (& buf ,',' );
544+ appendStringInfoString (& buf ,quote_identifier (strVal (arg )));
545+ }
546+ appendStringInfoChar (& buf ,')' );
488547
489548/* Identify class of trigger --- update, delete, or referencing-table */
490549switch (funcoid )
@@ -508,8 +567,8 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
508567default :
509568/* Ignore triggers on referencing table */
510569ereport (NOTICE ,
511- (errmsg ("ignoring incompleteforeign-key trigger group for constraint \"%s\"on table \"%s\" " ,
512- stmt -> trigname , stmt -> relation -> relname )));
570+ (errmsg ("ignoring incomplete trigger group for constraint \"%s\"%s " ,
571+ constr_name , buf . data )));
513572return ;
514573}
515574
@@ -527,8 +586,8 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
527586MemoryContext oldContext ;
528587
529588ereport (NOTICE ,
530- (errmsg ("ignoring incompleteforeign-key trigger group for constraint \"%s\"on table \"%s\" " ,
531- stmt -> trigname , stmt -> constrrel -> relname )));
589+ (errmsg ("ignoring incomplete trigger group for constraint \"%s\"%s " ,
590+ constr_name , buf . data )));
532591oldContext = MemoryContextSwitchTo (TopMemoryContext );
533592info = (OldTriggerInfo * )palloc (sizeof (OldTriggerInfo ));
534593info -> args = copyObject (stmt -> args );
@@ -539,49 +598,36 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
539598}
540599else
541600{
542- /* OK, we have a pair, so make the FK constraint */
601+ /* OK, we have a pair, so make the FK constraintALTER TABLE cmd */
543602AlterTableStmt * atstmt = makeNode (AlterTableStmt );
544603AlterTableCmd * atcmd = makeNode (AlterTableCmd );
545604FkConstraint * fkcon = makeNode (FkConstraint );
546- int i ;
547605Oid updfunc ,
548606delfunc ;
549607
550608ereport (NOTICE ,
551- (errmsg ("converting foreign-key trigger group into constraint \"%s\" on table \"%s\"" ,
552- stmt -> trigname ,stmt -> constrrel -> relname )));
553- atstmt -> relation = stmt -> constrrel ;
609+ (errmsg ("converting trigger group into constraint \"%s\" %s" ,
610+ constr_name ,buf .data )));
611+
612+ if (stmt -> constrrel )
613+ atstmt -> relation = stmt -> constrrel ;
614+ else
615+ {
616+ /* Work around ancient pg_dump bug that omitted constrrel */
617+ atstmt -> relation = makeRangeVar (NULL ,fk_table_name );
618+ }
554619atstmt -> cmds = list_make1 (atcmd );
555620atstmt -> relkind = OBJECT_TABLE ;
556621atcmd -> subtype = AT_AddConstraint ;
557622atcmd -> def = (Node * )fkcon ;
558- if (strcmp (stmt -> trigname ,"<unnamed>" )== 0 )
623+ if (strcmp (constr_name ,"<unnamed>" )== 0 )
559624fkcon -> constr_name = NULL ;
560625else
561- fkcon -> constr_name = stmt -> trigname ;
626+ fkcon -> constr_name = constr_name ;
562627fkcon -> pktable = stmt -> relation ;
563-
564- i = 0 ;
565- foreach (l ,stmt -> args )
566- {
567- Value * arg = (Value * )lfirst (l );
568-
569- i ++ ;
570- if (i < 4 )/* ignore constraint and table names */
571- continue ;
572- if (i == 4 )/* handle match type */
573- {
574- if (strcmp (strVal (arg ),"FULL" )== 0 )
575- fkcon -> fk_matchtype = FKCONSTR_MATCH_FULL ;
576- else
577- fkcon -> fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED ;
578- continue ;
579- }
580- if (i %2 )
581- fkcon -> fk_attrs = lappend (fkcon -> fk_attrs ,arg );
582- else
583- fkcon -> pk_attrs = lappend (fkcon -> pk_attrs ,arg );
584- }
628+ fkcon -> fk_attrs = fk_attrs ;
629+ fkcon -> pk_attrs = pk_attrs ;
630+ fkcon -> fk_matchtype = fk_matchtype ;
585631
586632if (isupd )
587633{
@@ -638,6 +684,7 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
638684fkcon -> deferrable = stmt -> deferrable ;
639685fkcon -> initdeferred = stmt -> initdeferred ;
640686
687+ /* ... and execute it */
641688ProcessUtility ((Node * )atstmt ,
642689NULL ,NULL , false,None_Receiver ,NULL );
643690