CRM-18104 Hook for hook for defining log tables.
authoreileenmcnaugton <eileen@fuzion.co.nz>
Wed, 24 Feb 2016 23:34:15 +0000 (12:34 +1300)
committereileenmcnaugton <eileen@fuzion.co.nz>
Thu, 21 Apr 2016 22:22:42 +0000 (10:22 +1200)
Allows defining ENGINE and any indexes

CRM/Logging/Schema.php
CRM/Utils/Hook.php

index 6d0248470fcb7789ce32f7987aeefe3c5c48a0b6..810f047f6d6c774fb8c4086d0fc189a0716b3537 100644 (file)
@@ -56,6 +56,18 @@ class CRM_Logging_Schema {
     'civicrm_group' => array('cache_date', 'refresh_date'),
   );
 
+  /**
+   * Specifications of all log table including
+   *  - engine (default is archive, if not set.)
+   *  - indexes (default is none and they cannot be added unless engine is innodb. If they are added and
+   *    engine is not set to innodb an exception will be thrown since quiet acquiescence is easier to miss).
+   *  - exceptions (by default those stored in $this->exceptions are included). These are
+   *    excluded from the triggers.
+   *
+   * @var array
+   */
+  private $logTableSpec = array();
+
   /**
    * Setting Callback - Validate.
    *
@@ -136,6 +148,12 @@ AND    TABLE_NAME LIKE 'civicrm_%'
 
     // do not log civicrm_mailing_recipients table, CRM-16193
     $this->tables = array_diff($this->tables, array('civicrm_mailing_recipients'));
+    $this->logTableSpec = array_fill_keys($this->tables, array());
+    foreach ($this->exceptions as $tableName => $fields) {
+      $this->logTableSpec[$tableName]['exceptions'] = $fields;
+    }
+    CRM_Utils_Hook::alterLogTables($this->logTableSpec);
+    $this->tables = array_keys($this->logTableSpec);
 
     if (defined('CIVICRM_LOGGING_DSN')) {
       $dsn = DB::parseDSN(CIVICRM_LOGGING_DSN);
@@ -583,6 +601,15 @@ WHERE  table_schema IN ('{$this->db}', '{$civiDB}')";
             log_action  ENUM('Initialization', 'Insert', 'Update', 'Delete')
 COLS;
 
+    if (!empty($this->logTableSpec[$table]['indexes'])) {
+      foreach ($this->logTableSpec[$table]['indexes'] as $indexName => $indexSpec) {
+        if (is_array($indexSpec)) {
+          $indexSpec = implode(" , ", $indexSpec);
+        }
+        $cols .= ", INDEX {$indexName}($indexSpec)";
+      }
+    }
+
     // - prepend the name with log_
     // - drop AUTO_INCREMENT columns
     // - drop non-column rows of the query (keys, constraints, etc.)
@@ -591,7 +618,8 @@ COLS;
     $query = preg_replace("/^CREATE TABLE `$table`/i", "CREATE TABLE `{$this->db}`.log_$table", $query);
     $query = preg_replace("/ AUTO_INCREMENT/i", '', $query);
     $query = preg_replace("/^  [^`].*$/m", '', $query);
-    $query = preg_replace("/^\) ENGINE=[^ ]+ /im", ') ENGINE=ARCHIVE ', $query);
+    $engine = strtoupper(CRM_Utils_Array::value('engine', $this->logTableSpec[$table], 'ARCHIVE'));
+    $query = preg_replace("/^\) ENGINE=[^ ]+ /im", ') ENGINE=' . $engine . ' ', $query);
 
     // log_civicrm_contact.modified_date for example would always be copied from civicrm_contact.modified_date,
     // so there's no need for a default timestamp and therefore we remove such default timestamps
@@ -687,8 +715,9 @@ COLS;
       // only do the change if any data has changed
       $cond = array();
       foreach ($columns as $column) {
+        $tableExceptions = array_key_exists('exceptions', $this->logTableSpec[$table]) ? $this->logTableSpec[$table]['exceptions'] : array();
         // ignore modified_date changes
-        if ($column != 'modified_date' && !in_array($column, CRM_Utils_Array::value($table, $this->exceptions, array()))) {
+        if ($column != 'modified_date' && !in_array($column, $tableExceptions)) {
           $cond[] = "IFNULL(OLD.$column,'') <> IFNULL(NEW.$column,'')";
         }
       }
index 7ac73c056fcbe88e49bfb7d5fd6ae15e5fe6a9fc..ddee93bfde6461e6ac43bc5db15766c8d9fc740c 100644 (file)
@@ -1474,6 +1474,20 @@ abstract class CRM_Utils_Hook {
       'civicrm_triggerInfo'
     );
   }
+  /**
+   * This hook allows changes to the spec of which tables to log.
+   *
+   * @param array $logTableSpec
+   *
+   * @return mixed
+   */
+  public static function alterLogTables(&$logTableSpec) {
+    return self::singleton()->invoke(1, $logTableSpec, $_nullObject,
+      self::$_nullObject, self::$_nullObject, self::$_nullObject,
+      self::$_nullObject,
+      'civicrm_alterLogTables'
+    );
+  }
 
   /**
    * This hook is called when a module-extension is installed.