From 6ef22d16dc449453930fb8216dfc6841a7f6ff12 Mon Sep 17 00:00:00 2001
From: eileenmcnaugton <eileen@fuzion.co.nz>
Date: Thu, 29 Oct 2015 21:26:04 +1300
Subject: [PATCH] CRM-17464 remove deadlock inducing query

Signed-off-by: JKingsnorth <john@johnkingsnorth.co.uk>
---
 CRM/Contact/BAO/Contact.php            | 35 ++++++++++++++++++++------
 CRM/Contact/BAO/Contact/Permission.php |  1 -
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/CRM/Contact/BAO/Contact.php b/CRM/Contact/BAO/Contact.php
index 51430c9bee..0f8ba6291b 100644
--- a/CRM/Contact/BAO/Contact.php
+++ b/CRM/Contact/BAO/Contact.php
@@ -879,14 +879,7 @@ WHERE     civicrm_contact.id = " . CRM_Utils_Type::escape($id, 'Integer');
 
     //delete the contact id from recently view
     CRM_Utils_Recent::delContact($id);
-
-    // Update the group contact cache
-    if ($restore) {
-      CRM_Contact_BAO_GroupContactCache::remove();
-    }
-    else {
-      CRM_Contact_BAO_GroupContactCache::removeContact($id);
-    }
+    self::updateContactCache($id, empty($restore));
 
     // delete any dupe cache entry
     CRM_Core_BAO_PrevNextCache::deleteItem($id);
@@ -904,6 +897,32 @@ WHERE     civicrm_contact.id = " . CRM_Utils_Type::escape($id, 'Integer');
     return TRUE;
   }
 
+  /**
+   * Action to update any caches relating to a recently update contact.
+   *
+   * I was going to call this from delete as well as from create to ensure the delete is being
+   * done whenever a contact is set to is_deleted=1 BUT I found create is already over-aggressive in
+   * that regard so adding it to delete seems to be enough to remove it from CRM_Contact_BAO_Contact_Permission
+   * where the call involved a subquery that was locking the table.
+   *
+   * @param int $contactID
+   * @param bool $isTrashed
+   */
+  public static function updateContactCache($contactID, $isTrashed = FALSE) {
+
+    if ($isTrashed) {
+      CRM_Contact_BAO_GroupContactCache::removeContact($contactID);
+      // This has been moved to here from CRM_Contact_BAO_Contact_Permission as that was causing
+      // a table-locking query. It still seems a bit inadequate as it assumes the acl users can't see deleted
+      // but this should not cause any change as long as contacts are not being trashed outside the
+      // main functions for that.
+      CRM_Core_DAO::executeQuery('DELETE FROM civicrm_acl_contact_cache WHERE contact_id = %1', array(1 => array($contactID, 'Integer')));
+    }
+    else {
+      CRM_Contact_BAO_GroupContactCache::remove();
+    }
+  }
+
   /**
    * Delete the image of a contact.
    *
diff --git a/CRM/Contact/BAO/Contact/Permission.php b/CRM/Contact/BAO/Contact/Permission.php
index 2d42840291..3a326ca6e3 100644
--- a/CRM/Contact/BAO/Contact/Permission.php
+++ b/CRM/Contact/BAO/Contact/Permission.php
@@ -141,7 +141,6 @@ ON DUPLICATE KEY UPDATE
          operation=VALUES(operation)"
     );
 
-    CRM_Core_DAO::executeQuery('DELETE FROM civicrm_acl_contact_cache WHERE contact_id IN (SELECT id FROM civicrm_contact WHERE is_deleted = 1)');
     $_processed[$userID] = 1;
   }
 
-- 
2.25.1