Skip to content

Commit

Permalink
Merge pull request #10019 from eileenmcnaughton/cacheid
Browse files Browse the repository at this point in the history
CRM-19385 - remove dependence on ids in cache tables.
  • Loading branch information
eileenmcnaughton authored Mar 20, 2017
2 parents fdbbaee + 21ca2cb commit e410674
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 22 deletions.
2 changes: 1 addition & 1 deletion CRM/Contact/BAO/Contact/Permission.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ public static function cache($userID, $type = CRM_Core_Permission::VIEW, $force

// run a query to see if the cache is filled
$sql = "
SELECT count(id)
SELECT count(*)
FROM civicrm_acl_contact_cache
WHERE user_id = %1
AND $operationClause
Expand Down
2 changes: 1 addition & 1 deletion CRM/Contact/BAO/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,7 @@ public static function getGroupList(&$params) {
}
// Exclude deleted contacts
$where .= " and c.id = g.contact_id AND c.is_deleted = 0";
$dao = CRM_Core_DAO::executeQuery("SELECT g.group_id, COUNT(g.id) as `count` FROM $table g, civicrm_contact c WHERE $where GROUP BY g.group_id");
$dao = CRM_Core_DAO::executeQuery("SELECT g.group_id, COUNT(*) as `count` FROM $table g, civicrm_contact c WHERE $where GROUP BY g.group_id");
while ($dao->fetch()) {
$values[$dao->group_id]['count'] = $dao->count;
}
Expand Down
6 changes: 2 additions & 4 deletions CRM/Contact/BAO/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -4788,11 +4788,9 @@ public function getCachedContacts($cacheKey, $offset, $rowCount, $includeContact
$onlyDeleted = in_array(array('deleted_contacts', '=', '1', '0', '0'), $this->_params);
list($select, $from, $where) = $this->query(FALSE, FALSE, FALSE, $onlyDeleted);
$from = " FROM civicrm_prevnext_cache pnc INNER JOIN civicrm_contact contact_a ON contact_a.id = pnc.entity_id1 AND pnc.cacheKey = '$cacheKey' " . substr($from, 31);
$order = " ORDER BY pnc.id";
$groupByCol = array('contact_a.id', 'pnc.id');
$groupBy = self::getGroupByFromSelectColumns($this->_select, $groupByCol);
$groupBy = self::getGroupByFromSelectColumns($this->_select, array('contact_a.id'));
$limit = " LIMIT $offset, $rowCount";
$query = "$select $from $where $groupBy $order $limit";
$query = "$select $from $where $groupBy $limit";

return CRM_Core_DAO::executeQuery($query);
}
Expand Down
10 changes: 7 additions & 3 deletions CRM/Contact/Form/Search/Custom/FullText.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ public function buildTempTable() {
) ENGINE=HEAP DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci
";
CRM_Core_DAO::executeQuery($sql);

if (!empty($this->_formValues['is_unit_test'])) {
$this->_tableNameForTest = $this->_tableName;
}
}

public function fillTable() {
Expand Down Expand Up @@ -259,7 +263,7 @@ public function filterACLContacts() {
$sql = "
DELETE t.*
FROM {$this->_tableName} t
WHERE NOT EXISTS ( SELECT c.id
WHERE NOT EXISTS ( SELECT c.contact_id
FROM civicrm_acl_contact_cache c
WHERE c.user_id = %1 AND t.contact_id = c.contact_id )
";
Expand All @@ -269,7 +273,7 @@ public function filterACLContacts() {
DELETE t.*
FROM {$this->_tableName} t
WHERE t.table_name = 'Activity' AND
NOT EXISTS ( SELECT c.id
NOT EXISTS ( SELECT c.contact_id
FROM civicrm_acl_contact_cache c
WHERE c.user_id = %1 AND ( t.target_contact_id = c.contact_id OR t.target_contact_id IS NULL ) )
";
Expand All @@ -279,7 +283,7 @@ public function filterACLContacts() {
DELETE t.*
FROM {$this->_tableName} t
WHERE t.table_name = 'Activity' AND
NOT EXISTS ( SELECT c.id
NOT EXISTS ( SELECT c.contact_id
FROM civicrm_acl_contact_cache c
WHERE c.user_id = %1 AND ( t.assignee_contact_id = c.contact_id OR t.assignee_contact_id IS NULL ) )
";
Expand Down
7 changes: 3 additions & 4 deletions CRM/Core/BAO/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,17 @@ public static function setItem(&$data, $group, $path, $componentID = NULL) {

$table = self::getTableName();
$where = self::whereCache($group, $path, $componentID);
$id = CRM_Core_DAO::singleValueQuery("SELECT id FROM $table WHERE $where");
$dataExists = CRM_Core_DAO::singleValueQuery("SELECT COUNT(*) FROM $table WHERE {$where}");
$now = date('Y-m-d H:i:s'); // FIXME - Use SQL NOW() or CRM_Utils_Time?
$dataSerialized = serialize($data);

// This table has a wonky index, so we cannot use REPLACE or
// "INSERT ... ON DUPE". Instead, use SELECT+(INSERT|UPDATE).
if ($id) {
$sql = "UPDATE $table SET data = %1, created_date = %2 WHERE id = %3";
if ($dataExists) {
$sql = "UPDATE $table SET data = %1, created_date = %2 WHERE {$where}";
$args = array(
1 => array($dataSerialized, 'String'),
2 => array($now, 'String'),
3 => array($id, 'Int'),
);
$dao = CRM_Core_DAO::executeQuery($sql, $args, TRUE, NULL, FALSE, FALSE);
}
Expand Down
3 changes: 1 addition & 2 deletions CRM/Core/BAO/PrevNextCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,6 @@ public static function getSelection($cacheKey, $action = 'get', $entity_table =
WHERE cacheKey LIKE %1
$actionGet
$entity_whereClause
ORDER BY id
";
$params[1] = array("{$cacheKey}%", 'String');

Expand Down Expand Up @@ -566,7 +565,7 @@ public static function buildSelectedContactPager(&$form, &$params) {
$cacheKey = "civicrm search {$qfKey}";

$query = "
SELECT count(id)
SELECT count(*)
FROM civicrm_prevnext_cache
WHERE cacheKey LIKE %1
AND is_selected = 1
Expand Down
8 changes: 4 additions & 4 deletions CRM/Core/CodeGen/Specification.php
Original file line number Diff line number Diff line change
Expand Up @@ -463,16 +463,16 @@ public function composeTitle($name) {
}

/**
* @param $primaryXML
* @param $fields
* @param $table
* @param object $primaryXML
* @param array $fields
* @param array $table
*/
public function getPrimaryKey(&$primaryXML, &$fields, &$table) {
$name = trim((string ) $primaryXML->name);

/** need to make sure there is a field of type name */
if (!array_key_exists($name, $fields)) {
echo "primary key $name in $table->name does not have a field definition, ignoring\n";
echo "primary key $name in {$table['name']} does not have a field definition, ignoring\n";
return;
}

Expand Down
9 changes: 7 additions & 2 deletions CRM/Core/Reference/Basic.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,16 @@ public function matchesTargetTable($tableName) {
*/
public function findReferences($targetDao) {
$targetColumn = $this->getTargetKey();
$select = 'id';
// CRM-19385: Since id is removed, return all rows for cache tables.
if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists($this->getReferenceTable(), 'id')) {
$select = '*';
}
$params = array(
1 => array($targetDao->$targetColumn, 'String'),
);
$sql = <<<EOS
SELECT id
SELECT {$select}
FROM {$this->getReferenceTable()}
WHERE {$this->getReferenceKey()} = %1
EOS;
Expand All @@ -103,7 +108,7 @@ public function getReferenceCount($targetDao) {
1 => array($targetDao->$targetColumn, 'String'),
);
$sql = <<<EOS
SELECT count(id)
SELECT count(*)
FROM {$this->getReferenceTable()}
WHERE {$this->getReferenceKey()} = %1
EOS;
Expand Down
2 changes: 1 addition & 1 deletion CRM/Group/Page/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public function browse($action = NULL) {
if (!empty($_GET['update_smart_groups'])) {
CRM_Contact_BAO_GroupContactCache::loadAll();
}
elseif (!CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_group_contact_cache LIMIT 1")) {
elseif (!CRM_Core_DAO::singleValueQuery("SELECT contact_id FROM civicrm_group_contact_cache LIMIT 1")) {
CRM_Core_Session::setStatus(ts('Count data for smart groups is not currently calculated. You may click Update Smart Groups to generate it. Be aware this can cause significant server load'));
}

Expand Down
16 changes: 16 additions & 0 deletions CRM/Upgrade/Incremental/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,20 @@ public static function addColumn($ctx, $table, $column, $properties) {
return TRUE;
}

/**
* Drop a column from a table if it exist.
*
* @param CRM_Queue_TaskContext $ctx
* @param string $table
* @param string $column
* @return bool
*/
public static function dropColumn($ctx, $table, $column) {
if (CRM_Core_BAO_SchemaHandler::checkIfFieldExists($table, $column)) {
CRM_Core_DAO::executeQuery("ALTER TABLE `$table` DROP COLUMN `$column`",
array(), TRUE, NULL, FALSE, FALSE);
}
return TRUE;
}

}
74 changes: 74 additions & 0 deletions tests/phpunit/CRM/Contact/Form/Search/Custom/FullTextTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

class CRM_Contact_Form_Search_Custom_FullTextTest extends CiviUnitTestCase {

/**
* @var array
*/
protected $_tablesToTruncate = array(
'civicrm_acl_contact_cache',
);

/**
* Test ACL contacts are filtered properly.
*/
public function testfilterACLContacts() {
$this->quickCleanup($this->_tablesToTruncate);

$userId = $this->createLoggedInUser();
// remove all permissions
$config = CRM_Core_Config::singleton();
$config->userPermissionClass->permissions = array();

for ($i = 1; $i <= 10; $i++) {
$contactId = $this->individualCreate(array(), $i);
if ($i <= 5) {
$queryParams = array(
1 => array($userId, 'Integer'),
2 => array($contactId, 'Integer'),
);
CRM_Core_DAO::executeQuery("INSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation ) VALUES(%1, %2, 'View')", $queryParams);
}
$contactIDs[$i] = $contactId;
}

$formValues = array('component_mode' => 1, 'operator' => 1, 'is_unit_test' => 1);
$fullText = new CRM_Contact_Form_Search_Custom_FullText($formValues);
$fullText->initialize();

//Assert that ACL contacts are filtered.
$queryParams = array(1 => array($userId, 'Integer'));
$whereClause = "WHERE NOT EXISTS (SELECT c.contact_id
FROM civicrm_acl_contact_cache c
WHERE c.user_id = %1 AND t.contact_id = c.contact_id )";

$count = CRM_Core_DAO::singleValueQuery("SELECT COUNT(*) FROM {$fullText->_tableNameForTest} t {$whereClause}", $queryParams);
$this->assertEmpty($count, 'ACL contacts are not removed.');
}

}

0 comments on commit e410674

Please sign in to comment.