1919#include "catalog/pg_trigger.h"
2020#include "access/genam.h"
2121#include "access/heapam.h"
22+ #include "access/valid.h"
2223#include "access/xact.h"
2324#include "storage/lmgr.h"
2425#include "storage/bufmgr.h"
@@ -37,13 +38,16 @@ TriggerData *CurrentTriggerData = NULL;
3738void RelationBuildTriggers (Relation relation );
3839void FreeTriggerDesc (Relation relation );
3940
40- static void DescribeTrigger (TriggerDesc * trigdesc ,Trigger * trigger );
41+ static void DescribeTrigger (TriggerDesc * trigdesc ,Trigger * trigger );
42+ static HeapTuple
43+ GetTupleForTrigger (Relation relation ,ItemPointer tid ,
44+ bool before );
4145
42- extern void fmgr_info (Oid procedureId ,func_ptr * function ,int * nargs );
46+ extern void fmgr_info (Oid procedureId ,func_ptr * function ,int * nargs );
4347extern GlobalMemory CacheCxt ;
4448
4549void
46- CreateTrigger (CreateTrigStmt * stmt )
50+ CreateTrigger (CreateTrigStmt * stmt )
4751{
4852int16 tgtype ;
4953int16 tgattr [8 ]= {0 };
@@ -211,7 +215,7 @@ CreateTrigger(CreateTrigStmt *stmt)
211215}
212216
213217void
214- DropTrigger (DropTrigStmt * stmt )
218+ DropTrigger (DropTrigStmt * stmt )
215219{
216220Relation rel ;
217221Relation tgrel ;
@@ -481,7 +485,7 @@ FreeTriggerDesc(Relation relation)
481485}
482486
483487static void
484- DescribeTrigger (TriggerDesc * trigdesc ,Trigger * trigger )
488+ DescribeTrigger (TriggerDesc * trigdesc ,Trigger * trigger )
485489{
486490uint16 * n ;
487491Trigger * * * t ,
@@ -555,64 +559,249 @@ DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger)
555559}
556560
557561HeapTuple
558- ExecBRInsertTriggers (Relation rel ,HeapTuple tuple )
562+ ExecBRInsertTriggers (Relation rel ,HeapTuple trigtuple )
559563{
564+ TriggerData * SaveTriggerData ;
560565int ntrigs = rel -> trigdesc -> n_before_row [TRIGGER_EVENT_INSERT ];
561566Trigger * * trigger = rel -> trigdesc -> tg_before_row [TRIGGER_EVENT_INSERT ];
562- HeapTuple newtuple = tuple ;
567+ HeapTuple newtuple = trigtuple ;
568+ HeapTuple oldtuple ;
563569int nargs ;
564570int i ;
565571
566- CurrentTriggerData = (TriggerData * )palloc (sizeof (TriggerData ));
567- CurrentTriggerData -> tg_event = TRIGGER_EVENT_INSERT |TRIGGER_EVENT_ROW ;
568- CurrentTriggerData -> tg_relation = rel ;
569- CurrentTriggerData -> tg_newtuple = NULL ;
572+ SaveTriggerData = (TriggerData * )palloc (sizeof (TriggerData ));
573+ SaveTriggerData -> tg_event =
574+ TRIGGER_EVENT_INSERT |TRIGGER_EVENT_ROW |TRIGGER_EVENT_BEFORE ;
575+ SaveTriggerData -> tg_relation = rel ;
576+ SaveTriggerData -> tg_newtuple = NULL ;
570577for (i = 0 ;i < ntrigs ;i ++ )
571578{
572- CurrentTriggerData -> tg_trigtuple = newtuple ;
579+ CurrentTriggerData = SaveTriggerData ;
580+ CurrentTriggerData -> tg_trigtuple = oldtuple = newtuple ;
573581CurrentTriggerData -> tg_trigger = trigger [i ];
574582if (trigger [i ]-> tgfunc == NULL )
575583fmgr_info (trigger [i ]-> tgfoid ,& (trigger [i ]-> tgfunc ),& nargs );
576584newtuple = (HeapTuple ) ((* (trigger [i ]-> tgfunc )) ());
577585if (newtuple == NULL )
578586break ;
587+ else if (oldtuple != newtuple && oldtuple != trigtuple )
588+ pfree (oldtuple );
579589}
580- pfree (CurrentTriggerData );
581590CurrentTriggerData = NULL ;
591+ pfree (SaveTriggerData );
582592return (newtuple );
583593}
584594
585595void
586- ExecARInsertTriggers (Relation rel ,HeapTuple tuple )
596+ ExecARInsertTriggers (Relation rel ,HeapTuple trigtuple )
587597{
598+ TriggerData * SaveTriggerData ;
599+ int ntrigs = rel -> trigdesc -> n_after_row [TRIGGER_EVENT_INSERT ];
600+ Trigger * * trigger = rel -> trigdesc -> tg_after_row [TRIGGER_EVENT_INSERT ];
601+ int nargs ;
602+ int i ;
588603
604+ SaveTriggerData = (TriggerData * )palloc (sizeof (TriggerData ));
605+ SaveTriggerData -> tg_event = TRIGGER_EVENT_INSERT |TRIGGER_EVENT_ROW ;
606+ SaveTriggerData -> tg_relation = rel ;
607+ SaveTriggerData -> tg_newtuple = NULL ;
608+ for (i = 0 ;i < ntrigs ;i ++ )
609+ {
610+ CurrentTriggerData = SaveTriggerData ;
611+ CurrentTriggerData -> tg_trigtuple = trigtuple ;
612+ CurrentTriggerData -> tg_trigger = trigger [i ];
613+ if (trigger [i ]-> tgfunc == NULL )
614+ fmgr_info (trigger [i ]-> tgfoid ,& (trigger [i ]-> tgfunc ),& nargs );
615+ (void ) ((* (trigger [i ]-> tgfunc )) ());
616+ }
617+ CurrentTriggerData = NULL ;
618+ pfree (SaveTriggerData );
589619return ;
590620}
591621
592622bool
593623ExecBRDeleteTriggers (Relation rel ,ItemPointer tupleid )
594624{
625+ TriggerData * SaveTriggerData ;
626+ int ntrigs = rel -> trigdesc -> n_before_row [TRIGGER_EVENT_DELETE ];
627+ Trigger * * trigger = rel -> trigdesc -> tg_before_row [TRIGGER_EVENT_DELETE ];
628+ HeapTuple trigtuple ;
629+ HeapTuple newtuple = NULL ;
630+ int nargs ;
631+ int i ;
632+
633+ trigtuple = GetTupleForTrigger (rel ,tupleid , true);
634+ if (trigtuple == NULL )
635+ return (false);
595636
596- return (true);
637+ SaveTriggerData = (TriggerData * )palloc (sizeof (TriggerData ));
638+ SaveTriggerData -> tg_event =
639+ TRIGGER_EVENT_DELETE |TRIGGER_EVENT_ROW |TRIGGER_EVENT_BEFORE ;
640+ SaveTriggerData -> tg_relation = rel ;
641+ SaveTriggerData -> tg_newtuple = NULL ;
642+ for (i = 0 ;i < ntrigs ;i ++ )
643+ {
644+ CurrentTriggerData = SaveTriggerData ;
645+ CurrentTriggerData -> tg_trigtuple = trigtuple ;
646+ CurrentTriggerData -> tg_trigger = trigger [i ];
647+ if (trigger [i ]-> tgfunc == NULL )
648+ fmgr_info (trigger [i ]-> tgfoid ,& (trigger [i ]-> tgfunc ),& nargs );
649+ newtuple = (HeapTuple ) ((* (trigger [i ]-> tgfunc )) ());
650+ if (newtuple == NULL )
651+ break ;
652+ }
653+ CurrentTriggerData = NULL ;
654+ pfree (SaveTriggerData );
655+ pfree (trigtuple );
656+
657+ return ((newtuple == NULL ) ? false : true);
597658}
598659
599660void
600661ExecARDeleteTriggers (Relation rel ,ItemPointer tupleid )
601662{
663+ TriggerData * SaveTriggerData ;
664+ int ntrigs = rel -> trigdesc -> n_after_row [TRIGGER_EVENT_DELETE ];
665+ Trigger * * trigger = rel -> trigdesc -> tg_after_row [TRIGGER_EVENT_DELETE ];
666+ HeapTuple trigtuple ;
667+ int nargs ;
668+ int i ;
602669
670+ trigtuple = GetTupleForTrigger (rel ,tupleid , false);
671+ Assert (trigtuple != NULL );
672+
673+ SaveTriggerData = (TriggerData * )palloc (sizeof (TriggerData ));
674+ SaveTriggerData -> tg_event =
675+ TRIGGER_EVENT_DELETE |TRIGGER_EVENT_ROW ;
676+ SaveTriggerData -> tg_relation = rel ;
677+ SaveTriggerData -> tg_newtuple = NULL ;
678+ for (i = 0 ;i < ntrigs ;i ++ )
679+ {
680+ CurrentTriggerData = SaveTriggerData ;
681+ CurrentTriggerData -> tg_trigtuple = trigtuple ;
682+ CurrentTriggerData -> tg_trigger = trigger [i ];
683+ if (trigger [i ]-> tgfunc == NULL )
684+ fmgr_info (trigger [i ]-> tgfoid ,& (trigger [i ]-> tgfunc ),& nargs );
685+ (void ) ((* (trigger [i ]-> tgfunc )) ());
686+ }
687+ CurrentTriggerData = NULL ;
688+ pfree (SaveTriggerData );
689+ pfree (trigtuple );
603690return ;
604691}
605692
606693HeapTuple
607- ExecBRUpdateTriggers (Relation rel ,ItemPointer tupleid ,HeapTuple tuple )
694+ ExecBRUpdateTriggers (Relation rel ,ItemPointer tupleid ,HeapTuple newtuple )
608695{
696+ TriggerData * SaveTriggerData ;
697+ int ntrigs = rel -> trigdesc -> n_before_row [TRIGGER_EVENT_UPDATE ];
698+ Trigger * * trigger = rel -> trigdesc -> tg_before_row [TRIGGER_EVENT_UPDATE ];
699+ HeapTuple trigtuple ;
700+ HeapTuple oldtuple ;
701+ HeapTuple intuple = newtuple ;
702+ int nargs ;
703+ int i ;
609704
610- return (tuple );
705+ trigtuple = GetTupleForTrigger (rel ,tupleid , true);
706+ if (trigtuple == NULL )
707+ return (NULL );
708+
709+ SaveTriggerData = (TriggerData * )palloc (sizeof (TriggerData ));
710+ SaveTriggerData -> tg_event =
711+ TRIGGER_EVENT_UPDATE |TRIGGER_EVENT_ROW |TRIGGER_EVENT_BEFORE ;
712+ SaveTriggerData -> tg_relation = rel ;
713+ for (i = 0 ;i < ntrigs ;i ++ )
714+ {
715+ CurrentTriggerData = SaveTriggerData ;
716+ CurrentTriggerData -> tg_trigtuple = trigtuple ;
717+ CurrentTriggerData -> tg_newtuple = oldtuple = newtuple ;
718+ CurrentTriggerData -> tg_trigger = trigger [i ];
719+ if (trigger [i ]-> tgfunc == NULL )
720+ fmgr_info (trigger [i ]-> tgfoid ,& (trigger [i ]-> tgfunc ),& nargs );
721+ newtuple = (HeapTuple ) ((* (trigger [i ]-> tgfunc )) ());
722+ if (newtuple == NULL )
723+ break ;
724+ else if (oldtuple != newtuple && oldtuple != intuple )
725+ pfree (oldtuple );
726+ }
727+ CurrentTriggerData = NULL ;
728+ pfree (SaveTriggerData );
729+ pfree (trigtuple );
730+ return (newtuple );
611731}
612732
613733void
614- ExecARUpdateTriggers (Relation rel ,ItemPointer tupleid ,HeapTuple tuple )
734+ ExecARUpdateTriggers (Relation rel ,ItemPointer tupleid ,HeapTuple newtuple )
615735{
736+ TriggerData * SaveTriggerData ;
737+ int ntrigs = rel -> trigdesc -> n_after_row [TRIGGER_EVENT_UPDATE ];
738+ Trigger * * trigger = rel -> trigdesc -> tg_after_row [TRIGGER_EVENT_UPDATE ];
739+ HeapTuple trigtuple ;
740+ int nargs ;
741+ int i ;
742+
743+ trigtuple = GetTupleForTrigger (rel ,tupleid , false);
744+ Assert (trigtuple != NULL );
616745
746+ SaveTriggerData = (TriggerData * )palloc (sizeof (TriggerData ));
747+ SaveTriggerData -> tg_event =
748+ TRIGGER_EVENT_UPDATE |TRIGGER_EVENT_ROW ;
749+ SaveTriggerData -> tg_relation = rel ;
750+ for (i = 0 ;i < ntrigs ;i ++ )
751+ {
752+ CurrentTriggerData = SaveTriggerData ;
753+ CurrentTriggerData -> tg_trigtuple = trigtuple ;
754+ CurrentTriggerData -> tg_newtuple = newtuple ;
755+ CurrentTriggerData -> tg_trigger = trigger [i ];
756+ if (trigger [i ]-> tgfunc == NULL )
757+ fmgr_info (trigger [i ]-> tgfoid ,& (trigger [i ]-> tgfunc ),& nargs );
758+ (void ) ((* (trigger [i ]-> tgfunc )) ());
759+ }
760+ CurrentTriggerData = NULL ;
761+ pfree (SaveTriggerData );
762+ pfree (trigtuple );
617763return ;
618764}
765+
766+ static HeapTuple
767+ GetTupleForTrigger (Relation relation ,ItemPointer tid ,bool before )
768+ {
769+ ItemId lp ;
770+ HeapTuple tuple ;
771+ PageHeader dp ;
772+ Buffer b ;
773+
774+ b = ReadBuffer (relation ,ItemPointerGetBlockNumber (tid ));
775+
776+ if (!BufferIsValid (b ))
777+ elog (WARN ,"GetTupleForTrigger: failed ReadBuffer" );
778+
779+ dp = (PageHeader )BufferGetPage (b );
780+ lp = PageGetItemId (dp ,ItemPointerGetOffsetNumber (tid ));
781+
782+ Assert (ItemIdIsUsed (lp ));
783+
784+ tuple = (HeapTuple )PageGetItem ((Page )dp ,lp );
785+
786+ if (before )
787+ {
788+ if (TupleUpdatedByCurXactAndCmd (tuple ))
789+ {
790+ elog (NOTICE ,"GetTupleForTrigger: Non-functional delete/update" );
791+ ReleaseBuffer (b );
792+ return (NULL );
793+ }
794+
795+ if (!(tuple = heap_tuple_satisfies (lp ,relation ,b ,dp ,
796+ NowTimeQual ,0 , (ScanKey )NULL )))
797+ {
798+ ReleaseBuffer (b );
799+ elog (WARN ,"GetTupleForTrigger: (am)invalid tid" );
800+ }
801+ }
802+
803+ tuple = heap_copytuple (tuple );
804+ ReleaseBuffer (b );
805+
806+ return (tuple );
807+ }