Skip to content

Commit

Permalink
Fixed issue #17409: Exporting responses with big data sets and activa…
Browse files Browse the repository at this point in the history
…ted encryption will timeout php memory limit, even with high settings (512M)
  • Loading branch information
ptelu committed Aug 13, 2021
1 parent bf72986 commit b72beac
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 13 deletions.
21 changes: 11 additions & 10 deletions application/helpers/admin/export/SurveyDao.php
Expand Up @@ -81,9 +81,9 @@ public function loadSurveyById($id, $lang = null, FormattingOptions $oOptions =
* @param string $completionState all, complete or incomplete
* @param array $aFields If empty all, otherwise only select the selected fields from the survey response table
* @param string $sResponsesId
* @throws CException
* @return CDbCommand
*/
public function loadSurveyResults(SurveyObj $survey, $iMinimum, $iMaximum, $sFilter = '', $completionState = 'all', $aFields = array(), $sResponsesId = null)
public function loadSurveyResults(SurveyObj $survey, $iMinimum, $iMaximum, $sFilter = '', $completionState = 'all', $aFields = array(), $sResponsesId = null): CDbCommand
{
$oSurvey = Survey::model()->findByPk($survey->id);

Expand All @@ -107,7 +107,7 @@ public function loadSurveyResults(SurveyObj $survey, $iMinimum, $iMaximum, $sFil
foreach ($aTokenFields as &$sField) {
$sField = "tokentable." . $sField;
}
$aSelectFields = array_merge($aSelectFields, array_diff($aTokenFields, array('tokentable.token')));
$aSelectFields = array_merge($aSelectFields, array_diff($aTokenFields, ['tokentable.token']));
//$aSelectFields=array_diff($aSelectFields, array('{{survey_{$survey->id}}}.token'));
//$aSelectFields[]='{{survey_' . $survey->id . '}}.token';
}
Expand All @@ -117,29 +117,29 @@ public function loadSurveyResults(SurveyObj $survey, $iMinimum, $iMaximum, $sFil
foreach ($aTimingFields as &$sField) {
$sField = "survey_timings." . $sField;
}
$aSelectFields = array_merge($aSelectFields, array_diff($aTimingFields, array('survey_timings.id')));
$aSelectFields = array_merge($aSelectFields, array_diff($aTimingFields, ['survey_timings.id']));
//$aSelectFields=array_diff($aSelectFields, array('{{survey_{$survey->id}}}.id'));
//$aSelectFields[]='{{survey_' . $survey->id . '}}.id';
}
if (empty($sResponsesId)) {
$aParams = array(
$aParams = [
'min' => $iMinimum,
'max' => $iMaximum
);
];
$selection = $oSurvey->responsesTableName . '.id >= :min AND ' . $oSurvey->responsesTableName . '.id <= :max';
$oRecordSet->where($selection, $aParams);
} else {
$aResponsesId = explode(',', $sResponsesId);

foreach ($aResponsesId as $i => $iResponseId) {
$iResponseId = (int) $iResponseId;
$iResponseId = (int)$iResponseId;
$selection = $oSurvey->responsesTableName . '.id = :id' . $i;


if ($i === 0) {
$oRecordSet->where($selection, array('id' . $i => $iResponseId));
$oRecordSet->where($selection, ['id' . $i => $iResponseId]);
} else {
$oRecordSet->orWhere($selection, array('id' . $i => $iResponseId));
$oRecordSet->orWhere($selection, ['id' . $i => $iResponseId]);
}
}
}
Expand All @@ -165,6 +165,7 @@ public function loadSurveyResults(SurveyObj $survey, $iMinimum, $iMaximum, $sFil
break;
}
$oRecordSet->order = $oSurvey->responsesTableName . '.id ASC';
$survey->responses = $oRecordSet->select($aSelectFields)->query();
$oRecordSet->select($aSelectFields);
return $oRecordSet;
}
}
17 changes: 14 additions & 3 deletions application/helpers/admin/exportresults_helper.php
Expand Up @@ -103,9 +103,20 @@ function exportResponses($iSurveyId, $sLanguageCode, $sExportPlugin, FormattingO
$surveyDao = new SurveyDao();
$survey = $surveyDao->loadSurveyById($iSurveyId, $sLanguageCode, $oOptions);
$writer->init($survey, $sLanguageCode, $oOptions);

$surveyDao->loadSurveyResults($survey, $oOptions->responseMinRecord, $oOptions->responseMaxRecord, $sFilter, $oOptions->responseCompletionState, $oOptions->selectedColumns, $oOptions->aResponses);
$writer->write($survey, $sLanguageCode, $oOptions, true);

$countResponsesCommand = $surveyDao->loadSurveyResults($survey, $oOptions->responseMinRecord, $oOptions->responseMaxRecord, $sFilter, $oOptions->responseCompletionState, $oOptions->selectedColumns, $oOptions->aResponses);
$countResponsesCommand->select('count(*)');
$reponsesCount = $countResponsesCommand->queryScalar();
$maxRows = 100;
$maxPages = ceil($reponsesCount / $maxRows);
for ($i = 0; $i < $maxPages; $i++) {
$offset = $i * $maxRows;
$responsesQuery = $surveyDao->loadSurveyResults($survey, $oOptions->responseMinRecord, $oOptions->responseMaxRecord, $sFilter, $oOptions->responseCompletionState, $oOptions->selectedColumns, $oOptions->aResponses);

This comment has been minimized.

Copy link
@Shnoulle

Shnoulle Oct 13, 2022

Collaborator

My opinion : must use $responseMinRecord and $responseMaxRecord directly here with offset and maxRows

$responsesQuery->offset($offset);
$responsesQuery->limit($maxRows);
$survey->responses = $responsesQuery->query();
$writer->write($survey, $sLanguageCode, $oOptions, true);
}
$result = $writer->close();

// Close resultset if needed
Expand Down

3 comments on commit b72beac

@Shnoulle
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit create a bug in MSSQL
https://bugs.limesurvey.org/view.php?id=18102

@gabrieljenik
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How?

@Shnoulle
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How?

See the mantis issue https://bugs.limesurvey.org/view.php?id=18102#c72247

New SQL fix inside Yii2, i try to fix it in LimeSurey before open a issue in Yii

Please sign in to comment.