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. */