Skip to content

Commit

Permalink
Improve output triggers when logged to file
Browse files Browse the repository at this point in the history
Hmm write on rebuild AND reap on destruct
  • Loading branch information
eileenmcnaughton committed Jun 8, 2021
1 parent a6f6f86 commit f443cc6
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 8 deletions.
2 changes: 1 addition & 1 deletion CRM/Logging/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ public function disableLogging() {
*
* @param string $tableName
*/
public function dropTriggers($tableName = NULL) {
public function dropTriggers($tableName = NULL): void {
/** @var \Civi\Core\SqlTriggers $sqlTriggers */
$sqlTriggers = Civi::service('sql_triggers');
$dao = new CRM_Core_DAO();
Expand Down
49 changes: 42 additions & 7 deletions Civi/Core/SqlTriggers.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ class SqlTriggers {
*
* @var string|null
*/
private $file = NULL;
private $file;

/**
* Queries written to file when the class is destructed.
*
* @var array
*/
private $enqueuedQueries = [];

/**
* Build a list of triggers via hook and add them to (err, reconcile them
Expand Down Expand Up @@ -52,6 +59,7 @@ public function rebuild($tableName = NULL, $force = FALSE) {

// now create the set of new triggers
$this->createTriggers($info, $tableName);
$this->writeEnqueuedQueriesToFile();
}

/**
Expand Down Expand Up @@ -202,12 +210,8 @@ public function enqueueQuery($triggerSQL, $params = []) {
['expires' => 0]
);
}

$buf = "\n";
$buf .= "DELIMITER //\n";
$buf .= \CRM_Core_DAO::composeQuery($triggerSQL, $params) . " //\n";
$buf .= "DELIMITER ;\n";
file_put_contents($this->getFile(), $buf, FILE_APPEND);
$query = \CRM_Core_DAO::composeQuery($triggerSQL, $params);
$this->enqueuedQueries[$query] = $query;
}
else {
\CRM_Core_DAO::executeQuery($triggerSQL, $params, TRUE, NULL, FALSE, FALSE);
Expand All @@ -226,4 +230,35 @@ public function getFile() {
return $this->file;
}

/**
* Write queries to file when the class is destructed.
*
* Note this is already written out for a full rebuild but it is
* possible (at least in terms of what is public) to call drop & create
* separately so this ensures they are output.
*/
public function __destruct() {
$this->writeEnqueuedQueriesToFile();
}

/**
* Write queries queued for write-to-file.
*/
protected function writeEnqueuedQueriesToFile(): void {
if (!empty($this->enqueuedQueries) && $this->getFile()) {
$buf = "DELIMITER //\n";
foreach ($this->enqueuedQueries as $query) {
if (strpos($query, 'CREATE TRIGGER') === 0) {
// The create triggers are long so put spaces between them. For the drops
// condensed is more readable.
$buf .= "\n";
}
$buf .= $query . " //\n";
}
$buf .= "DELIMITER ;\n";
file_put_contents($this->getFile(), $buf, FILE_APPEND);
$this->enqueuedQueries = [];
}
}

}
38 changes: 38 additions & 0 deletions tests/phpunit/api/v3/LoggingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ protected function setUp(): void {
protected function tearDown(): void {
$this->quickCleanup(['civicrm_email', 'civicrm_address']);
parent::tearDown();
Civi::settings()->set('logging_no_trigger_permission', FALSE);
$this->callAPISuccess('Setting', 'create', ['logging' => FALSE]);
$schema = new CRM_Logging_Schema();
$schema->dropAllLogTables();
Expand Down Expand Up @@ -492,4 +493,41 @@ protected function ensureTempColIsCleanedUp() {
}
}

/**
* Test the output under logging_no_trigger_permission.
*
* The logging_no_trigger_permission setting causes the trigger sql
* to be output to a file rather than run. It is for situations
* where the db user does not have adequate permissions (Super permission
* is required when replication is enabled.
*
* This tests the output of that file.
*/
public function testTriggerOutput(): void {
Civi::settings()->set('logging_no_trigger_permission', TRUE);
Civi::settings()->set('logging', TRUE);
/* @var \Civi\Core\SqlTriggers $sqlTriggers */
$sqlTriggers = Civi::service('sql_triggers');
$fileName = $sqlTriggers->getFile();
$triggerOutPut = file_get_contents($fileName);
$this->assertStringStartsWith('DELIMITER //
DROP FUNCTION', $triggerOutPut);
$this->assertStringContainsString('DROP TRIGGER IF EXISTS civicrm_activity_before_insert //
DROP TRIGGER IF EXISTS civicrm_activity_before_update //
DROP TRIGGER IF EXISTS civicrm_activity_before_delete //
DROP TRIGGER IF EXISTS civicrm_activity_after_insert //
DROP TRIGGER IF EXISTS civicrm_activity_after_update //
DROP TRIGGER IF EXISTS civicrm_activity_after_delete //
DROP TRIGGER IF EXISTS civicrm_activity_contact_before_insert //
DROP TRIGGER IF EXISTS civicrm_activity_contact_before_update //
DROP TRIGGER IF EXISTS civicrm_activity_contact_before_delete //
DROP TRIGGER IF EXISTS civicrm_activity_contact_after_insert //
DROP TRIGGER IF EXISTS civicrm_activity_contact_after_update //
DROP TRIGGER IF EXISTS civicrm_activity_contact_after_delete //', $triggerOutPut);

$this->assertStringEndsWith('END //
DELIMITER ;
', $triggerOutPut);
}

}

0 comments on commit f443cc6

Please sign in to comment.