]> granicus.if.org Git - postgresql/commitdiff
Apply RI trigger skipping tests also for DELETE
authorPeter Eisentraut <peter_e@gmx.net>
Thu, 19 Jul 2018 06:37:32 +0000 (08:37 +0200)
committerPeter Eisentraut <peter_e@gmx.net>
Sat, 10 Nov 2018 15:14:51 +0000 (16:14 +0100)
The tests added in cfa0f4255bb0f5550d37a01c4d8fe2966d20040c to skip
firing an RI trigger if any old key value is NULL can also be applied
for DELETE.  This should give a performance gain in those cases, and it
also saves a lot of duplicate code in the actual RI triggers.  (That
code was already dead code for the UPDATE cases.)

Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
src/backend/commands/trigger.c
src/backend/utils/adt/ri_triggers.c

index 0bd847cd195f578a58beca1bed0a89675f4c04db..ccb5706c1628d6de1dd7b54b3531699d06d3d424 100644 (file)
@@ -5950,12 +5950,12 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
                 * certain cases where we can skip queueing the event because we can
                 * tell by inspection that the FK constraint will still pass.
                 */
-               if (TRIGGER_FIRED_BY_UPDATE(event))
+               if (TRIGGER_FIRED_BY_UPDATE(event) || TRIGGER_FIRED_BY_DELETE(event))
                {
                        switch (RI_FKey_trigger_type(trigger->tgfoid))
                        {
                                case RI_TRIGGER_PK:
-                                       /* Update on trigger's PK table */
+                                       /* Update or delete on trigger's PK table */
                                        if (!RI_FKey_pk_upd_check_required(trigger, rel,
                                                                                                           oldtup, newtup))
                                        {
index dfa9ab98c31423e8fb701fd5bdbf16a9ddf31273..cdda860e73a379d7563c8bb6d24cb2e3a95820a1 100644 (file)
@@ -724,25 +724,6 @@ ri_restrict(TriggerData *trigdata, bool is_no_action)
                         */
                case FKCONSTR_MATCH_SIMPLE:
                case FKCONSTR_MATCH_FULL:
-                       switch (ri_NullCheck(RelationGetDescr(pk_rel), old_row, riinfo, true))
-                       {
-                               case RI_KEYS_ALL_NULL:
-                               case RI_KEYS_SOME_NULL:
-
-                                       /*
-                                        * No check needed - there cannot be any reference to old
-                                        * key if it contains a NULL
-                                        */
-                                       heap_close(fk_rel, RowShareLock);
-                                       return PointerGetDatum(NULL);
-
-                               case RI_KEYS_NONE_NULL:
-
-                                       /*
-                                        * Have a full qualified key - continue below
-                                        */
-                                       break;
-                       }
 
                        /*
                         * If another PK row now exists providing the old key values, we
@@ -900,26 +881,6 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
                         */
                case FKCONSTR_MATCH_SIMPLE:
                case FKCONSTR_MATCH_FULL:
-                       switch (ri_NullCheck(RelationGetDescr(pk_rel), old_row, riinfo, true))
-                       {
-                               case RI_KEYS_ALL_NULL:
-                               case RI_KEYS_SOME_NULL:
-
-                                       /*
-                                        * No check needed - there cannot be any reference to old
-                                        * key if it contains a NULL
-                                        */
-                                       heap_close(fk_rel, RowExclusiveLock);
-                                       return PointerGetDatum(NULL);
-
-                               case RI_KEYS_NONE_NULL:
-
-                                       /*
-                                        * Have a full qualified key - continue below
-                                        */
-                                       break;
-                       }
-
                        if (SPI_connect() != SPI_OK_CONNECT)
                                elog(ERROR, "SPI_connect failed");
 
@@ -1064,26 +1025,6 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
                         */
                case FKCONSTR_MATCH_SIMPLE:
                case FKCONSTR_MATCH_FULL:
-                       switch (ri_NullCheck(RelationGetDescr(pk_rel), old_row, riinfo, true))
-                       {
-                               case RI_KEYS_ALL_NULL:
-                               case RI_KEYS_SOME_NULL:
-
-                                       /*
-                                        * No check needed - there cannot be any reference to old
-                                        * key if it contains a NULL
-                                        */
-                                       heap_close(fk_rel, RowExclusiveLock);
-                                       return PointerGetDatum(NULL);
-
-                               case RI_KEYS_NONE_NULL:
-
-                                       /*
-                                        * Have a full qualified key - continue below
-                                        */
-                                       break;
-                       }
-
                        if (SPI_connect() != SPI_OK_CONNECT)
                                elog(ERROR, "SPI_connect failed");
 
@@ -1273,26 +1214,6 @@ ri_setnull(TriggerData *trigdata)
                         */
                case FKCONSTR_MATCH_SIMPLE:
                case FKCONSTR_MATCH_FULL:
-                       switch (ri_NullCheck(RelationGetDescr(pk_rel), old_row, riinfo, true))
-                       {
-                               case RI_KEYS_ALL_NULL:
-                               case RI_KEYS_SOME_NULL:
-
-                                       /*
-                                        * No check needed - there cannot be any reference to old
-                                        * key if it contains a NULL
-                                        */
-                                       heap_close(fk_rel, RowExclusiveLock);
-                                       return PointerGetDatum(NULL);
-
-                               case RI_KEYS_NONE_NULL:
-
-                                       /*
-                                        * Have a full qualified key - continue below
-                                        */
-                                       break;
-                       }
-
                        if (SPI_connect() != SPI_OK_CONNECT)
                                elog(ERROR, "SPI_connect failed");
 
@@ -1479,26 +1400,6 @@ ri_setdefault(TriggerData *trigdata)
                         */
                case FKCONSTR_MATCH_SIMPLE:
                case FKCONSTR_MATCH_FULL:
-                       switch (ri_NullCheck(RelationGetDescr(pk_rel), old_row, riinfo, true))
-                       {
-                               case RI_KEYS_ALL_NULL:
-                               case RI_KEYS_SOME_NULL:
-
-                                       /*
-                                        * No check needed - there cannot be any reference to old
-                                        * key if it contains a NULL
-                                        */
-                                       heap_close(fk_rel, RowExclusiveLock);
-                                       return PointerGetDatum(NULL);
-
-                               case RI_KEYS_NONE_NULL:
-
-                                       /*
-                                        * Have a full qualified key - continue below
-                                        */
-                                       break;
-                       }
-
                        if (SPI_connect() != SPI_OK_CONNECT)
                                elog(ERROR, "SPI_connect failed");
 
@@ -1617,11 +1518,13 @@ ri_setdefault(TriggerData *trigdata)
 /* ----------
  * RI_FKey_pk_upd_check_required -
  *
- *     Check if we really need to fire the RI trigger for an update to a PK
+ *     Check if we really need to fire the RI trigger for an update or delete to a PK
  *     relation.  This is called by the AFTER trigger queue manager to see if
  *     it can skip queuing an instance of an RI trigger.  Returns true if the
  *     trigger must be fired, false if we can prove the constraint will still
  *     be satisfied.
+ *
+ *     new_row will be NULL if this is called for a delete.
  * ----------
  */
 bool
@@ -1648,7 +1551,7 @@ RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel,
                                return false;
 
                        /* If all old and new key values are equal, no check is needed */
-                       if (ri_KeysEqual(pk_rel, old_row, new_row, riinfo, true))
+                       if (new_row && ri_KeysEqual(pk_rel, old_row, new_row, riinfo, true))
                                return false;
 
                        /* Else we need to fire the trigger. */