Commit a938e409 authored by sam marshall's avatar sam marshall
Browse files

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).
parent ed00d67c
......@@ -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();
}
}
\ No newline at end of file
}
......@@ -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);
}
/**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment