diff --git a/CRM/Core/BAO/SchemaHandler.php b/CRM/Core/BAO/SchemaHandler.php
index 1f4a93c17183..c4f8c221ef86 100644
--- a/CRM/Core/BAO/SchemaHandler.php
+++ b/CRM/Core/BAO/SchemaHandler.php
@@ -723,6 +723,23 @@ public static function getMissingIndices() {
// Compare
$missingSigs = array_diff($requiredSigs, $existingSigs);
+
+ //CRM-20774 - Get index key which exist in db but the value varies.
+ $existingKeyIndices = array();
+ $existingKeySigs = array_intersect_key($missingSigs, $existingSigs);
+ if (!empty($existingKeySigs)) {
+ $missingSigs = array_diff_key($missingSigs, $existingKeySigs);
+ foreach ($existingKeySigs as $sig) {
+ $sigParts = explode('::', $sig);
+ foreach ($requiredIndices[$sigParts[0]] as $index) {
+ if ($index['sig'] == $sig) {
+ $existingKeyIndices[$sigParts[0]][] = $index;
+ continue;
+ }
+ }
+ }
+ }
+
// Get missing indices
$missingIndices = array();
foreach ($missingSigs as $sig) {
@@ -734,7 +751,7 @@ public static function getMissingIndices() {
}
}
}
- return $missingIndices;
+ return array($missingIndices, $existingKeyIndices);
}
/**
diff --git a/CRM/Utils/Check/Component/Schema.php b/CRM/Utils/Check/Component/Schema.php
index 6c8f7608e76f..d281c26a405c 100644
--- a/CRM/Utils/Check/Component/Schema.php
+++ b/CRM/Utils/Check/Component/Schema.php
@@ -37,11 +37,29 @@ class CRM_Utils_Check_Component_Schema extends CRM_Utils_Check_Component {
*/
public function checkIndices() {
$messages = array();
- $missingIndices = CRM_Core_BAO_SchemaHandler::getMissingIndices();
- if ($missingIndices) {
+ list($missingIndices, $existingKeyIndices) = CRM_Core_BAO_SchemaHandler::getMissingIndices();
+ if ($existingKeyIndices) {
+ $html = '';
+ foreach ($existingKeyIndices as $tableName => $indices) {
+ foreach ($indices as $index) {
+ $fields = implode(', ', $index['field']);
+ $html .= "
{$tableName} | {$index['name']} | $fields | ";
+ }
+ }
+ $keyMessage = "The following tables have an index key with a mismatch in value. Please delete the key indices listed from the below table and then click on 'Update Indices' button.
+
Table Name | Key Name | Fields |
+
+ $html
+
";
+ }
+ if ($missingIndices || $existingKeyIndices) {
+ $message = "You have missing indices on some tables. This may cause poor performance.";
+ if (!empty($keyMessage)) {
+ $message = $keyMessage;
+ }
$msg = new CRM_Utils_Check_Message(
__FUNCTION__,
- ts('You have missing indices on some tables. This may cause poor performance.'),
+ ts($message),
ts('Performance warning: Missing indices'),
\Psr\Log\LogLevel::WARNING,
'fa-server'
diff --git a/api/v3/System.php b/api/v3/System.php
index b71103297259..b4b4974bf0d7 100644
--- a/api/v3/System.php
+++ b/api/v3/System.php
@@ -408,6 +408,7 @@ function civicrm_api3_system_updatelogtables() {
* This adds any indexes that exist in the schema but not the database.
*/
function civicrm_api3_system_updateindexes() {
- CRM_Core_BAO_SchemaHandler::createMissingIndices(CRM_Core_BAO_SchemaHandler::getMissingIndices());
+ list($missingIndices) = CRM_Core_BAO_SchemaHandler::getMissingIndices();
+ CRM_Core_BAO_SchemaHandler::createMissingIndices($missingIndices);
return civicrm_api3_create_success(1);
}
diff --git a/tests/phpunit/CRM/Core/BAO/SchemaHandlerTest.php b/tests/phpunit/CRM/Core/BAO/SchemaHandlerTest.php
index e2bcba688233..6227a957d212 100644
--- a/tests/phpunit/CRM/Core/BAO/SchemaHandlerTest.php
+++ b/tests/phpunit/CRM/Core/BAO/SchemaHandlerTest.php
@@ -184,7 +184,7 @@ public function testSafeDropForeignKey($tableName, $key) {
* Check there are no missing indices
*/
public function testGetMissingIndices() {
- $missingIndices = CRM_Core_BAO_SchemaHandler::getMissingIndices();
+ list($missingIndices) = CRM_Core_BAO_SchemaHandler::getMissingIndices();
$this->assertTrue(empty($missingIndices));
}
@@ -230,7 +230,7 @@ public function testCreateMissingIndices() {
*/
public function testReconcileMissingIndices() {
CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_contact DROP INDEX index_sort_name');
- $missingIndices = CRM_Core_BAO_SchemaHandler::getMissingIndices();
+ list($missingIndices) = CRM_Core_BAO_SchemaHandler::getMissingIndices();
$this->assertEquals(array(
'civicrm_contact' => array(
array(
@@ -242,10 +242,39 @@ public function testReconcileMissingIndices() {
),
), $missingIndices);
$this->callAPISuccess('System', 'updateindexes', array());
- $missingIndices = CRM_Core_BAO_SchemaHandler::getMissingIndices();
+ list($missingIndices) = CRM_Core_BAO_SchemaHandler::getMissingIndices();
$this->assertTrue(empty($missingIndices));
}
+ /**
+ * Check for partial indices
+ */
+ public function testPartialIndices() {
+ CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_prevnext_cache DROP INDEX index_all');
+ //Missing Column `is_selected`.
+ CRM_Core_DAO::executeQuery('CREATE INDEX index_all ON civicrm_prevnext_cache (cacheKey, entity_id1, entity_id2, entity_table)');
+ list($missingIndices, $existingKeyIndices) = CRM_Core_BAO_SchemaHandler::getMissingIndices();
+ $this->assertNotEmpty($existingKeyIndices);
+
+ CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_entity_tag DROP INDEX UI_entity_id_entity_table_tag_id');
+ //Test incorrect Ordering(correct order defined is entity_id and then entity_table, tag_id).
+ CRM_Core_DAO::executeQuery('CREATE INDEX UI_entity_id_entity_table_tag_id ON civicrm_entity_tag (entity_table, entity_id, tag_id)');
+ list($missingIndices, $existingKeyIndices) = CRM_Core_BAO_SchemaHandler::getMissingIndices();
+ $this->assertNotEmpty($existingKeyIndices);
+ $this->assertEquals(array('civicrm_prevnext_cache', 'civicrm_entity_tag'), array_keys($existingKeyIndices));
+
+ //Drop false index and create again.
+ CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_prevnext_cache DROP INDEX index_all');
+ CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_entity_tag DROP INDEX UI_entity_id_entity_table_tag_id');
+ list($missingIndices, $existingKeyIndices) = CRM_Core_BAO_SchemaHandler::getMissingIndices();
+ $this->assertEmpty($existingKeyIndices);
+ CRM_Core_BAO_SchemaHandler::createMissingIndices($missingIndices);
+ //Both vars should be empty now.
+ list($missingIndices, $existingKeyIndices) = CRM_Core_BAO_SchemaHandler::getMissingIndices();
+ $this->assertEmpty($missingIndices);
+ $this->assertEmpty($existingKeyIndices);
+ }
+
/**
* Test index signatures are added correctly
*/