Skip to content

Commit

Permalink
Merge pull request #16146 from eileenmcnaughton/index_api2
Browse files Browse the repository at this point in the history
Update function to repair indexes to take table as a parameter
  • Loading branch information
mattwire authored Jan 3, 2020
2 parents e80b17e + 8e9480b commit 79c9b44
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 21 deletions.
9 changes: 7 additions & 2 deletions CRM/Core/BAO/SchemaHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ public static function alterFieldLength($customFieldID, $tableName, $columnName,
* Check if the table has an index matching the name.
*
* @param string $tableName
* @param array $indexName
* @param string $indexName
*
* @return bool
*/
Expand Down Expand Up @@ -654,15 +654,20 @@ public static function addIndexSignature($table, &$indices) {
* @param bool $dropFalseIndices
* If set - this function deletes false indices present in the DB which mismatches the expected
* values of xml file so that civi re-creates them with correct values using createMissingIndices() function.
* @param array|FALSE $tables
* An optional array of tables - if provided the results will be restricted to these tables.
*
* @return array
* index specifications
*/
public static function getMissingIndices($dropFalseIndices = FALSE) {
public static function getMissingIndices($dropFalseIndices = FALSE, $tables = FALSE) {
$requiredSigs = $existingSigs = [];
// Get the indices defined (originally) in the xml files
$requiredIndices = CRM_Core_DAO_AllCoreTables::indices();
$reqSigs = [];
if ($tables !== FALSE) {
$requiredIndices = array_intersect_key($requiredIndices, array_fill_keys($tables, TRUE));
}
foreach ($requiredIndices as $table => $indices) {
$reqSigs[] = CRM_Utils_Array::collect('sig', $indices);
}
Expand Down
42 changes: 38 additions & 4 deletions api/v3/System.php
Original file line number Diff line number Diff line change
Expand Up @@ -411,22 +411,56 @@ function _civicrm_api3_system_updatelogtables_spec(&$params) {
* Update indexes.
*
* This adds any indexes that exist in the schema but not the database.
*
* @param array $params
*
* @return array
*/
function civicrm_api3_system_updateindexes() {
CRM_Core_BAO_SchemaHandler::createMissingIndices(CRM_Core_BAO_SchemaHandler::getMissingIndices(TRUE));
function civicrm_api3_system_updateindexes(array $params):array {
$tables = empty($params['tables']) ? FALSE : (array) $params['tables'];
CRM_Core_BAO_SchemaHandler::createMissingIndices(CRM_Core_BAO_SchemaHandler::getMissingIndices(TRUE, $tables));
return civicrm_api3_create_success(1);
}

/**
* Declare metadata for api System.getmissingindices
*
* @param array $params
*/
function _civicrm_api3_system_updateindexes_spec(array &$params) {
$params['tables'] = [
'type' => CRM_Utils_Type::T_STRING,
'api.default' => FALSE,
'title' => ts('Optional tables filter'),
];
}

/**
* Get an array of indices that should be defined but are not.
*
* @param array $params
*
* @return array
*/
function civicrm_api3_system_getmissingindices() {
$indices = CRM_Core_BAO_SchemaHandler::getMissingIndices(FALSE);
function civicrm_api3_system_getmissingindices($params) {
$tables = empty($params['tables']) ? FALSE : (array) $params['tables'];
$indices = CRM_Core_BAO_SchemaHandler::getMissingIndices(FALSE, $tables);
return civicrm_api3_create_success($indices);
}

/**
* Declare metadata for api System.getmissingindices
*
* @param array $params
*/
function _civicrm_api3_system_getmissingindices_spec(&$params) {
$params['tables'] = [
'type' => CRM_Utils_Type::T_STRING,
'api.default' => FALSE,
'title' => ts('Optional tables filter'),
];
}

/**
* Creates missing log tables.
*
Expand Down
77 changes: 62 additions & 15 deletions tests/phpunit/CRM/Core/BAO/SchemaHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,21 @@
*
* These tests create and drop indexes on the civicrm_uf_join table. The indexes
* being added and dropped we assume will never exist.
*
* @group headless
*/
class CRM_Core_BAO_SchemaHandlerTest extends CiviUnitTestCase {

/**
* Ensure any removed indices are put back.
*
* @throws \CRM_Core_Exception
*/
public function tearDown() {
parent::tearDown();
$this->callAPISuccess('System', 'updateindexes', []);
}

/**
* Test creating an index.
*
Expand All @@ -28,13 +39,13 @@ public function testCreateIndex() {
$tables = ['civicrm_uf_join' => ['weight']];
CRM_Core_BAO_SchemaHandler::createIndexes($tables);
CRM_Core_BAO_SchemaHandler::createIndexes($tables);
$dao = CRM_Core_DAO::executeQuery("SHOW INDEX FROM civicrm_uf_join");
$dao = CRM_Core_DAO::executeQuery('SHOW INDEX FROM civicrm_uf_join');
$count = 0;

while ($dao->fetch()) {
if ($dao->Column_name == 'weight') {
if ($dao->Column_name === 'weight') {
$count++;
CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_uf_join DROP INDEX " . $dao->Key_name);
CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_uf_join DROP INDEX ' . $dao->Key_name);
}
}
$this->assertEquals(1, $count);
Expand All @@ -60,24 +71,22 @@ public function testCombinedIndex() {

$tables = ['civicrm_uf_join' => [['weight', 'module']]];
CRM_Core_BAO_SchemaHandler::createIndexes($tables);
$dao = CRM_Core_DAO::executeQuery("SHOW INDEX FROM civicrm_uf_join");
$dao = CRM_Core_DAO::executeQuery('SHOW INDEX FROM civicrm_uf_join');
$weightCount = 0;
$combinedCount = 0;
$indexes = [];

while ($dao->fetch()) {
if ($dao->Column_name == 'weight') {
if ($dao->Column_name === 'weight') {
$weightCount++;
$indexes[$dao->Key_name] = $dao->Key_name;
}
if ($dao->Column_name == 'module') {
$combinedCount++;
if ($dao->Column_name === 'module') {
$this->assertArrayHasKey($dao->Key_name, $indexes);
}

}
foreach (array_keys($indexes) as $index) {
CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_uf_join DROP INDEX " . $index);
CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_uf_join DROP INDEX ' . $index);
}
$this->assertEquals(2, $weightCount);
}
Expand Down Expand Up @@ -132,7 +141,7 @@ public function columnTests() {
* @dataProvider columnTests
*/
public function testCheckIfColumnExists($tableName, $columnName) {
if ($columnName == 'xxxx') {
if ($columnName === 'xxxx') {
$this->assertFalse(CRM_Core_BAO_SchemaHandler::checkIfFieldExists($tableName, $columnName));
}
else {
Expand All @@ -154,9 +163,12 @@ public function foreignKeyTests() {
* Test to see if we can drop foreign key
*
* @dataProvider foreignKeyTests
*
* @param string $tableName
* @param string $key
*/
public function testSafeDropForeignKey($tableName, $key) {
if ($key == 'FK_civicrm_mailing_recipients_id') {
if ($key === 'FK_civicrm_mailing_recipients_id') {
$this->assertFalse(CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_recipients', $key));
}
else {
Expand Down Expand Up @@ -235,6 +247,41 @@ public function testReconcileMissingIndices() {
$this->assertEmpty($missingIndices);
}

/**
* Check there are no missing indices
*
* @throws \CRM_Core_Exception
*/
public function testGetMissingIndicesWithTableFilter() {
CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_contact DROP INDEX index_sort_name');
CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_contribution DROP INDEX index_total_amount_receive_date');
$missingIndices = $this->callAPISuccess('System', 'getmissingindices', [])['values'];
$expected = [
'civicrm_contact' => [
[
'name' => 'index_sort_name',
'field' => ['sort_name'],
'localizable' => FALSE,
'sig' => 'civicrm_contact::0::sort_name',
],
],
'civicrm_contribution' => [
[
'name' => 'index_total_amount_receive_date',
'field' => ['total_amount', 'receive_date'],
'localizable' => FALSE,
'sig' => 'civicrm_contribution::0::total_amount::receive_date',
],
],
];
$this->assertEquals($expected, $missingIndices);
$missingIndices = $this->callAPISuccess('System', 'getmissingindices', ['tables' => ['civicrm_contact']])['values'];
$this->assertEquals(['civicrm_contact' => $expected['civicrm_contact']], $missingIndices);
$this->callAPISuccess('System', 'updateindexes', ['tables' => 'civicrm_contribution']);
$missingIndices = $this->callAPISuccess('System', 'getmissingindices', [])['values'];
$this->assertEquals(['civicrm_contact' => $expected['civicrm_contact']], $missingIndices);
}

/**
* Check for partial indices
*/
Expand Down Expand Up @@ -309,7 +356,7 @@ public function testDropColumn() {
// drop col1
CRM_Core_DAO::executeQuery(CRM_Core_BAO_SchemaHandler::buildFieldChangeSql($alterParams, FALSE));

$create_table = CRM_Core_DAO::executeQuery("SHOW CREATE TABLE civicrm_test_drop_column");
$create_table = CRM_Core_DAO::executeQuery('SHOW CREATE TABLE civicrm_test_drop_column');
while ($create_table->fetch()) {
$this->assertNotContains('col1', $create_table->Create_Table);
$this->assertContains('col2', $create_table->Create_Table);
Expand All @@ -319,7 +366,7 @@ public function testDropColumn() {
$alterParams['name'] = 'col2';
CRM_Core_DAO::executeQuery(CRM_Core_BAO_SchemaHandler::buildFieldChangeSql($alterParams, FALSE));

$create_table = CRM_Core_DAO::executeQuery("SHOW CREATE TABLE civicrm_test_drop_column");
$create_table = CRM_Core_DAO::executeQuery('SHOW CREATE TABLE civicrm_test_drop_column');
while ($create_table->fetch()) {
$this->assertNotContains('col2', $create_table->Create_Table);
}
Expand All @@ -336,8 +383,8 @@ public function testBuildFieldChangeSql() {
'type' => 'text',
];
$sql = CRM_Core_BAO_SchemaHandler::buildFieldChangeSql($params, FALSE);
$this->assertEquals("ALTER TABLE big_table
ADD COLUMN `big_bob` text", trim($sql));
$this->assertEquals('ALTER TABLE big_table
ADD COLUMN `big_bob` text', trim($sql));

$params['operation'] = 'modify';
$params['comment'] = 'super big';
Expand Down

0 comments on commit 79c9b44

Please sign in to comment.