Skip to content

Commit

Permalink
Merge pull request #10585 from JMAConsulting/CRM-17748
Browse files Browse the repository at this point in the history
[ready for core team review] CRM-17748: Expose options to CRM_Core_DAO
  • Loading branch information
eileenmcnaughton authored Aug 29, 2017
2 parents a7813bf + 4d1368d commit 33754fd
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 37 deletions.
90 changes: 53 additions & 37 deletions CRM/Core/DAO.php
Original file line number Diff line number Diff line change
Expand Up @@ -1249,43 +1249,17 @@ static public function executeUnbufferedQuery(
$i18nRewrite = TRUE,
$trapException = FALSE
) {
$queryStr = self::composeQuery($query, $params, $abort);
//CRM_Core_Error::debug( 'q', $queryStr );
if (!$daoName) {
$dao = new CRM_Core_DAO();
}
else {
$dao = new $daoName();
}

if ($trapException) {
CRM_Core_Error::ignoreException();
}

// set the DAO object to use an unbuffered query
$dao->setOptions(array('result_buffering' => 0));

$result = $dao->query($queryStr, $i18nRewrite);

if ($trapException) {
CRM_Core_Error::setCallback();
}

if (is_a($result, 'DB_Error')) {
return $result;
}

// since it is unbuffered, ($dao->N==0) is true. This blocks the standard fetch() mechanism.
$dao->N = TRUE;

if ($freeDAO ||
preg_match('/^(insert|update|delete|create|drop|replace)/i', $queryStr)
) {
// we typically do this for insert/update/delete stataments OR if explicitly asked to
// free the dao
$dao->free();
}
return $dao;
return self::executeQuery(
$query,
$params,
$abort,
$daoName,
$freeDAO,
$i18nRewrite,
$trapException,
array('result_buffering' => 0)
);
}

/**
Expand All @@ -1300,6 +1274,7 @@ static public function executeUnbufferedQuery(
* @param bool $freeDAO
* @param bool $i18nRewrite
* @param bool $trapException
* @param array $options
*
* @return CRM_Core_DAO|object
* object that holds the results of the query
Expand All @@ -1313,7 +1288,8 @@ public static function &executeQuery(
$daoName = NULL,
$freeDAO = FALSE,
$i18nRewrite = TRUE,
$trapException = FALSE
$trapException = FALSE,
$options = array()
) {
$queryStr = self::composeQuery($query, $params, $abort);

Expand All @@ -1328,8 +1304,17 @@ public static function &executeQuery(
$errorScope = CRM_Core_TemporaryErrorScope::ignoreException();
}

if ($dao->isValidOption($options)) {
$dao->setOptions($options);
}

$result = $dao->query($queryStr, $i18nRewrite);

// since it is unbuffered, ($dao->N==0) is true. This blocks the standard fetch() mechanism.
if (CRM_Utils_Array::value('result_buffering', $options) === 0) {
$dao->N = TRUE;
}

if (is_a($result, 'DB_Error')) {
return $result;
}
Expand All @@ -1344,6 +1329,37 @@ public static function &executeQuery(
return $dao;
}

/**
* Wrapper to validate internal DAO options before passing to DB_mysql/DB_Common level
*
* @param array $options
*
* @return bool
* Provided options are valid
*/
public function isValidOption($options) {
$isValid = FALSE;
$validOptions = array(
'result_buffering',
'persistent',
'ssl',
'portability',
);

if (empty($options)) {
return $isValid;
}

foreach (array_keys($options) as $option) {
if (!in_array($option, $validOptions)) {
return FALSE;
}
$isValid = TRUE;
}

return $isValid;
}

/**
* Execute a query and get the single result.
*
Expand Down
38 changes: 38 additions & 0 deletions tests/phpunit/CRM/Core/DAOTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,42 @@ public function testDAOtoArray() {
}
}

/**
* CRM-17748: Test internal DAO options
*/
public function testDBOptions() {
$contactIDs = array();
for ($i = 0; $i < 10; $i++) {
$contactIDs[] = $this->individualCreate(array(
'first_name' => 'Alan' . substr(sha1(rand()), 0, 7),
'last_name' => 'Smith' . substr(sha1(rand()), 0, 4),
));
}

// Test option 'result_buffering'
$this->_testMemoryUsageForUnbufferedQuery();

// cleanup
foreach ($contactIDs as $contactID) {
$this->callAPISuccess('Contact', 'delete', array('id' => $contactID));
}
}

/**
* Helper function to test result of buffered and unbuffered query
*/
public function _testMemoryUsageForUnbufferedQuery() {
$sql = "SELECT * FROM civicrm_contact WHERE first_name LIKE 'Alan%' AND last_name LIKE 'Smith%' ";

$dao = CRM_Core_DAO::executeQuery($sql);
$contactsFetchedFromBufferedQuery = $dao->fetchAll();
$dao->free();

$dao = CRM_Core_DAO::executeUnbufferedQuery($sql);
$contactsFetchedFromUnbufferedQuery = $dao->fetchAll();
$dao->free();

$this->checkArrayEquals($contactsFetchedFromBufferedQuery, $contactsFetchedFromUnbufferedQuery);
}

}

0 comments on commit 33754fd

Please sign in to comment.