MDL-81434 reportbuilder: ensure filter/condition parameter uniqueness.

This change fixes an edge case that could be triggered by creating a
custom report that contained a filter instance that was active as both
a filter and condition, where the filter instance provides parameters
to it's SQL fragment.

There is only one such filter present currently with which we can test
this, see 2f9001cbe9.
This commit is contained in:
Paul Holden 2024-04-04 12:26:18 +01:00
parent 462d5f04a8
commit 9b827c09ce
No known key found for this signature in database
GPG key ID: A81A96D6045F6164
5 changed files with 116 additions and 11 deletions

View file

@ -30,7 +30,7 @@ use core_user;
* @copyright 2020 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class database_test extends advanced_testcase {
final class database_test extends advanced_testcase {
/**
* Test generating alias
@ -176,9 +176,11 @@ class database_test extends advanced_testcase {
[$param0, $param1, $param10] = ['rbparam0', 'rbparam1', 'rbparam10'];
$sql = "SELECT :{$param0} AS field0, :{$param1} AS field1, :{$param10} AS field10" . $DB->sql_null_from_clause();
$sql = database::sql_replace_parameter_names($sql, [$param0, $param1, $param10], static function(string $param): string {
return "prefix_{$param}";
});
$sql = database::sql_replace_parameter_names(
$sql,
[$param0, $param1, $param10],
fn(string $param) => "prefix_{$param}",
);
$record = $DB->get_record_sql($sql, [
"prefix_{$param0}" => 'Zero',
@ -192,4 +194,29 @@ class database_test extends advanced_testcase {
'field10' => 'Ten',
], $record);
}
/**
* Test replacement of parameter names within query, returning both modified query and parameters
*/
public function test_sql_replace_parameters(): void {
global $DB;
// Predefine parameter names, to ensure they don't overwrite each other.
[$param0, $param1, $param10] = ['rbparam0', 'rbparam1', 'rbparam10'];
$sql = "SELECT :{$param0} AS field0, :{$param1} AS field1, :{$param10} AS field10" . $DB->sql_null_from_clause();
[$sql, $params] = database::sql_replace_parameters(
$sql,
[$param0 => 'Zero', $param1 => 'One', $param10 => 'Ten'],
fn(string $param) => "prefix_{$param}",
);
$record = $DB->get_record_sql($sql, $params);
$this->assertEquals((object) [
'field0' => 'Zero',
'field1' => 'One',
'field10' => 'Ten',
], $record);
}
}