mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 13:38:32 +01:00
MDL-60174 core_dml: fix miscellaneous incorrect recordset usage
The new recordset support for Postgres requires transactions and will cause errors if recordsets are not closed correctly. This commit fixes problems that were identified during unit tests, and via some basic code analysis, across all core code. Most of these are incorrect usage of recordset (forgetting to close them).
This commit is contained in:
parent
ed00d67c99
commit
a938e4096c
@ -73,6 +73,7 @@ foreach ($rs as $user) {
|
||||
echo "Redeleting user $user->id: $user->username ($user->email)\n";
|
||||
delete_user($user);
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
cli_heading('Deleting all leftovers');
|
||||
|
||||
|
@ -40,6 +40,7 @@ if (empty($classname)) {
|
||||
foreach ($records as $record) {
|
||||
$instances[] = \core\message\inbound\manager::get_handler($record->classname);
|
||||
}
|
||||
$records->close();
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $renderer->messageinbound_handlers_table($instances);
|
||||
|
@ -234,15 +234,19 @@ function search_spammers($keywords) {
|
||||
$keywordlist = implode(', ', $keywords);
|
||||
echo $OUTPUT->box(get_string('spamresult', 'tool_spamcleaner').s($keywordlist)).' ...';
|
||||
|
||||
print_user_list(array($spamusers_desc,
|
||||
$spamusers_blog,
|
||||
$spamusers_blogsub,
|
||||
$spamusers_comment,
|
||||
$spamusers_message,
|
||||
$spamusers_forumpost,
|
||||
$spamusers_forumpostsub
|
||||
),
|
||||
$keywords);
|
||||
$recordsets = [
|
||||
$spamusers_desc,
|
||||
$spamusers_blog,
|
||||
$spamusers_blogsub,
|
||||
$spamusers_comment,
|
||||
$spamusers_message,
|
||||
$spamusers_forumpost,
|
||||
$spamusers_forumpostsub
|
||||
];
|
||||
print_user_list($recordsets, $keywords);
|
||||
foreach ($recordsets as $rs) {
|
||||
$rs->close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -360,6 +360,7 @@ class manager {
|
||||
}
|
||||
$existingcalculations[$calculation->indicator][$calculation->sampleid] = $calculation->value;
|
||||
}
|
||||
$calculations->close();
|
||||
return $existingcalculations;
|
||||
}
|
||||
|
||||
|
@ -981,8 +981,8 @@ class restore_process_course_modules_availability extends restore_execution_step
|
||||
$DB->set_field('course_' . $table . 's', 'availability', $newvalue,
|
||||
array('id' => $thingid));
|
||||
}
|
||||
$rs->close();
|
||||
}
|
||||
$rs->close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -504,6 +504,7 @@ function cohort_get_invisible_contexts() {
|
||||
$excludedcontexts[] = $ctx->id;
|
||||
}
|
||||
}
|
||||
$records->close();
|
||||
return $excludedcontexts;
|
||||
}
|
||||
|
||||
|
@ -428,6 +428,7 @@ abstract class gradingform_controller {
|
||||
foreach ($records as $record) {
|
||||
$rv[] = $this->get_instance($record);
|
||||
}
|
||||
$records->close();
|
||||
return $rv;
|
||||
}
|
||||
|
||||
|
@ -419,6 +419,7 @@ abstract class screen {
|
||||
while ($user = $gui->next_user()) {
|
||||
$users[$user->user->id] = $user->user;
|
||||
}
|
||||
$gui->close();
|
||||
return $users;
|
||||
}
|
||||
|
||||
|
@ -618,6 +618,7 @@ function groups_delete_groupings_groups($courseid, $showfeedback=false) {
|
||||
foreach ($results as $result) {
|
||||
groups_unassign_grouping($result->groupingid, $result->groupid, false);
|
||||
}
|
||||
$results->close();
|
||||
|
||||
// Invalidate the grouping cache for the course
|
||||
cache_helper::invalidate_by_definition('core', 'groupdata', array(), array($courseid));
|
||||
@ -646,6 +647,7 @@ function groups_delete_groups($courseid, $showfeedback=false) {
|
||||
foreach ($groups as $group) {
|
||||
groups_delete_group($group);
|
||||
}
|
||||
$groups->close();
|
||||
|
||||
// Invalidate the grouping cache for the course
|
||||
cache_helper::invalidate_by_definition('core', 'groupdata', array(), array($courseid));
|
||||
@ -676,6 +678,7 @@ function groups_delete_groupings($courseid, $showfeedback=false) {
|
||||
foreach ($groupings as $grouping) {
|
||||
groups_delete_grouping($grouping);
|
||||
}
|
||||
$groupings->close();
|
||||
|
||||
// Invalidate the grouping cache for the course.
|
||||
cache_helper::invalidate_by_definition('core', 'groupdata', array(), array($courseid));
|
||||
|
@ -800,6 +800,7 @@ class block_manager {
|
||||
$unknown[] = $bi;
|
||||
}
|
||||
}
|
||||
$blockinstances->close();
|
||||
|
||||
// Pages don't necessarily have a defaultregion. The one time this can
|
||||
// happen is when there are no theme block regions, but the script itself
|
||||
|
@ -74,6 +74,7 @@ class manager {
|
||||
self::remove_messageinbound_handler($handler);
|
||||
}
|
||||
}
|
||||
$existinghandlers->close();
|
||||
|
||||
self::create_missing_messageinbound_handlers_for_component($componentname);
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ class portfolio extends base {
|
||||
foreach ($rs as $repository) {
|
||||
$enabled[$repository->plugin] = $repository->plugin;
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
return $enabled;
|
||||
}
|
||||
@ -91,4 +92,4 @@ class portfolio extends base {
|
||||
|
||||
parent::uninstall_cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1183,6 +1183,7 @@ function xmldb_main_upgrade($oldversion) {
|
||||
$i++;
|
||||
$pbar->update($i, $total, "Updating duplicate question category stamp - $i/$total.");
|
||||
}
|
||||
$rs->close();
|
||||
unset($usedstamps);
|
||||
|
||||
// The uniqueness of each (contextid, stamp) pair is now guaranteed, so add the unique index to stop future duplicates.
|
||||
|
@ -2001,6 +2001,7 @@ class file_storage {
|
||||
foreach ($rs as $filerecord) {
|
||||
$files[$filerecord->pathnamehash] = $this->get_file_instance($filerecord);
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
@ -3258,6 +3258,7 @@ class global_navigation_for_ajax extends global_navigation {
|
||||
foreach ($categories as $category){
|
||||
$coursesubcategories = array_merge($coursesubcategories, explode('/', trim($category->path, "/")));
|
||||
}
|
||||
$categories->close();
|
||||
$coursesubcategories = array_unique($coursesubcategories);
|
||||
|
||||
// Only add a subcategory if it is part of the path to user's course and
|
||||
|
@ -1499,9 +1499,9 @@ class table_sql extends flexible_table {
|
||||
* method or if other_cols returns NULL then put the data straight into the
|
||||
* table.
|
||||
*
|
||||
* @return void
|
||||
* After calling this function, don't forget to call close_recordset.
|
||||
*/
|
||||
function build_table() {
|
||||
public function build_table() {
|
||||
|
||||
if ($this->rawdata instanceof \Traversable && !$this->rawdata->valid()) {
|
||||
return;
|
||||
@ -1515,10 +1515,16 @@ class table_sql extends flexible_table {
|
||||
$this->add_data_keyed($formattedrow,
|
||||
$this->get_row_class($row));
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->rawdata instanceof \core\dml\recordset_walk ||
|
||||
$this->rawdata instanceof moodle_recordset) {
|
||||
/**
|
||||
* Closes recordset (for use after building the table).
|
||||
*/
|
||||
public function close_recordset() {
|
||||
if ($this->rawdata && ($this->rawdata instanceof \core\dml\recordset_walk ||
|
||||
$this->rawdata instanceof moodle_recordset)) {
|
||||
$this->rawdata->close();
|
||||
$this->rawdata = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1629,6 +1635,7 @@ class table_sql extends flexible_table {
|
||||
$this->setup();
|
||||
$this->query_db($pagesize, $useinitialsbar);
|
||||
$this->build_table();
|
||||
$this->close_recordset();
|
||||
$this->finish_output();
|
||||
}
|
||||
}
|
||||
|
@ -676,6 +676,7 @@ abstract class testing_util {
|
||||
$mysqlsequences[$table] = $info->auto_increment;
|
||||
}
|
||||
}
|
||||
$rs->close();
|
||||
}
|
||||
|
||||
foreach ($data as $table => $records) {
|
||||
|
@ -902,15 +902,15 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
$this->send_message($sender3, $recipient, 'Notification', 1);
|
||||
|
||||
core_message_external::mark_all_notifications_as_read($recipient->id, $sender1->id);
|
||||
$readnotifications = $DB->get_recordset('message_read', ['useridto' => $recipient->id]);
|
||||
$unreadnotifications = $DB->get_recordset('message', ['useridto' => $recipient->id]);
|
||||
$readnotifications = $DB->get_records('message_read', ['useridto' => $recipient->id]);
|
||||
$unreadnotifications = $DB->get_records('message', ['useridto' => $recipient->id]);
|
||||
|
||||
$this->assertCount(2, $readnotifications);
|
||||
$this->assertCount(4, $unreadnotifications);
|
||||
|
||||
core_message_external::mark_all_notifications_as_read($recipient->id, 0);
|
||||
$readnotifications = $DB->get_recordset('message_read', ['useridto' => $recipient->id]);
|
||||
$unreadnotifications = $DB->get_recordset('message', ['useridto' => $recipient->id]);
|
||||
$readnotifications = $DB->get_records('message_read', ['useridto' => $recipient->id]);
|
||||
$unreadnotifications = $DB->get_records('message', ['useridto' => $recipient->id]);
|
||||
|
||||
$this->assertCount(6, $readnotifications);
|
||||
$this->assertCount(0, $unreadnotifications);
|
||||
|
@ -504,8 +504,6 @@ class mod_feedback_responses_table extends table_sql {
|
||||
}
|
||||
}
|
||||
$this->build_table_chunk($chunk, $columnsgroups);
|
||||
|
||||
$this->rawdata->close();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -631,6 +629,7 @@ class mod_feedback_responses_table extends table_sql {
|
||||
}
|
||||
$this->query_db($this->pagesize, false);
|
||||
$this->build_table();
|
||||
$this->close_recordset();
|
||||
return $this->dataforexternal;
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +28,12 @@ global $CFG;
|
||||
require_once($CFG->dirroot . '/mod/forum/lib.php');
|
||||
|
||||
class mod_forum_subscriptions_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test setUp.
|
||||
*/
|
||||
public function setUp() {
|
||||
global $DB;
|
||||
|
||||
// We must clear the subscription caches. This has to be done both before each test, and after in case of other
|
||||
// tests using these functions.
|
||||
\mod_forum\subscriptions::reset_forum_cache();
|
||||
@ -973,11 +974,11 @@ class mod_forum_subscriptions_testcase extends advanced_testcase {
|
||||
// Reset the subscription cache.
|
||||
\mod_forum\subscriptions::reset_forum_cache();
|
||||
|
||||
// Filling the subscription cache should only use a single query.
|
||||
// Filling the subscription cache should use a query.
|
||||
$startcount = $DB->perf_get_reads();
|
||||
$this->assertNull(\mod_forum\subscriptions::fill_subscription_cache($forum->id));
|
||||
$postfillcount = $DB->perf_get_reads();
|
||||
$this->assertEquals(1, $postfillcount - $startcount);
|
||||
$this->assertNotEquals($postfillcount, $startcount);
|
||||
|
||||
// Now fetch some subscriptions from that forum - these should use
|
||||
// the cache and not perform additional queries.
|
||||
@ -1049,7 +1050,7 @@ class mod_forum_subscriptions_testcase extends advanced_testcase {
|
||||
$result = \mod_forum\subscriptions::fill_subscription_cache_for_course($course->id, $user->id);
|
||||
$this->assertNull($result);
|
||||
$postfillcount = $DB->perf_get_reads();
|
||||
$this->assertEquals(1, $postfillcount - $startcount);
|
||||
$this->assertNotEquals($postfillcount, $startcount);
|
||||
$this->assertFalse(\mod_forum\subscriptions::fetch_subscription_cache($disallowforum->id, $user->id));
|
||||
$this->assertFalse(\mod_forum\subscriptions::fetch_subscription_cache($chooseforum->id, $user->id));
|
||||
$this->assertTrue(\mod_forum\subscriptions::fetch_subscription_cache($initialforum->id, $user->id));
|
||||
@ -1064,7 +1065,7 @@ class mod_forum_subscriptions_testcase extends advanced_testcase {
|
||||
$this->assertTrue(\mod_forum\subscriptions::fetch_subscription_cache($initialforum->id, $user->id));
|
||||
}
|
||||
$finalcount = $DB->perf_get_reads();
|
||||
$this->assertEquals(count($users), $finalcount - $postfillcount);
|
||||
$this->assertNotEquals($finalcount, $postfillcount);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1117,7 +1118,7 @@ class mod_forum_subscriptions_testcase extends advanced_testcase {
|
||||
$startcount = $DB->perf_get_reads();
|
||||
$this->assertNull(\mod_forum\subscriptions::fill_discussion_subscription_cache($forum->id));
|
||||
$postfillcount = $DB->perf_get_reads();
|
||||
$this->assertEquals(1, $postfillcount - $startcount);
|
||||
$this->assertNotEquals($postfillcount, $startcount);
|
||||
|
||||
// Now fetch some subscriptions from that forum - these should use
|
||||
// the cache and not perform additional queries.
|
||||
@ -1184,7 +1185,7 @@ class mod_forum_subscriptions_testcase extends advanced_testcase {
|
||||
$this->assertInternalType('array', $result);
|
||||
}
|
||||
$finalcount = $DB->perf_get_reads();
|
||||
$this->assertEquals(20, $finalcount - $startcount);
|
||||
$this->assertNotEquals($finalcount, $startcount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3795,7 +3795,7 @@ function glossary_get_search_terms_sql(array $terms, $fullsearch = true, $glossa
|
||||
* @param array $options Accepts:
|
||||
* - (bool) includenotapproved. When false, includes the non-approved entries created by
|
||||
* the current user. When true, also includes the ones that the user has the permission to approve.
|
||||
* @return array The first element being the recordset, the second the number of entries.
|
||||
* @return array The first element being the array of results, the second the number of entries.
|
||||
* @since Moodle 3.1
|
||||
*/
|
||||
function glossary_get_entries_by_search($glossary, $context, $query, $fullsearch, $order, $sort, $from, $limit,
|
||||
|
@ -216,6 +216,10 @@ if ( $allentries ) {
|
||||
|
||||
glossary_print_entry($course, $cm, $glossary, $entry, $mode, $hook, 1, $displayformat, true);
|
||||
}
|
||||
// The all entries value may be a recordset or an array.
|
||||
if ($allentries instanceof moodle_recordset) {
|
||||
$allentries->close();
|
||||
}
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
@ -521,6 +521,10 @@ if ($allentries) {
|
||||
glossary_print_entry($course, $cm, $glossary, $entry, $mode, $hook,1,$displayformat);
|
||||
$entriesshown++;
|
||||
}
|
||||
// The all entries value may be a recordset or an array.
|
||||
if ($allentries instanceof moodle_recordset) {
|
||||
$allentries->close();
|
||||
}
|
||||
}
|
||||
if ( !$entriesshown ) {
|
||||
echo $OUTPUT->box(get_string("noentries","glossary"), "generalbox boxaligncenter boxwidthwide");
|
||||
|
@ -306,6 +306,7 @@ class mod_quiz_attempt_overdue_testcase extends advanced_testcase {
|
||||
$count++;
|
||||
|
||||
}
|
||||
$attempts->close();
|
||||
$this->assertEquals($DB->count_records_select('quiz_attempts', 'timecheckstate IS NOT NULL'), $count);
|
||||
|
||||
$attempts = $overduehander->get_list_of_overdue_attempts(0); // before all attempts
|
||||
@ -313,6 +314,7 @@ class mod_quiz_attempt_overdue_testcase extends advanced_testcase {
|
||||
foreach ($attempts as $attempt) {
|
||||
$count++;
|
||||
}
|
||||
$attempts->close();
|
||||
$this->assertEquals(0, $count);
|
||||
|
||||
}
|
||||
|
@ -1240,7 +1240,7 @@ function wiki_delete_page_versions($deleteversions, $context = null) {
|
||||
list($insql, $param) = $DB->get_in_or_equal($versions);
|
||||
$insql .= ' AND pageid = ?';
|
||||
array_push($param, $params['pageid']);
|
||||
$oldversions = $DB->get_recordset_select('wiki_versions', 'version ' . $insql, $param);
|
||||
$oldversions = $DB->get_records_select('wiki_versions', 'version ' . $insql, $param);
|
||||
$DB->delete_records_select('wiki_versions', 'version ' . $insql, $param);
|
||||
}
|
||||
foreach ($oldversions as $version) {
|
||||
|
@ -408,6 +408,7 @@ class view {
|
||||
$questions = $DB->get_recordset_sql($this->loadsql, $this->sqlparams, $page * $perpage, $perpage);
|
||||
if (!$questions->valid()) {
|
||||
// No questions on this page. Reset to page 0.
|
||||
$questions->close();
|
||||
$questions = $DB->get_recordset_sql($this->loadsql, $this->sqlparams, 0, $perpage);
|
||||
}
|
||||
return $questions;
|
||||
@ -708,6 +709,7 @@ class view {
|
||||
$this->print_table_row($question, $rowcount);
|
||||
$rowcount += 1;
|
||||
}
|
||||
$questions->close();
|
||||
$this->end_table();
|
||||
echo "</div>\n";
|
||||
|
||||
|
@ -828,6 +828,7 @@ function report_security_check_riskbackup($detailed=false) {
|
||||
'contextname'=>$context->get_context_name());
|
||||
$users[] = '<li>'.get_string('check_riskbackup_unassign', 'report_security', $a).'</li>';
|
||||
}
|
||||
$rs->close();
|
||||
if (!empty($users)) {
|
||||
$users = '<ul>'.implode('', $users).'</ul>';
|
||||
$result->details .= get_string('check_riskbackup_details_users', 'report_security', $users);
|
||||
|
Loading…
x
Reference in New Issue
Block a user