MDL-79270 reportbuilder: remove duplicate columns from order clause.

This works around a problem in SQL Server, which caused it to throw a
DML exception if the same column is duplicated in `ORDER BY` clause.
This commit is contained in:
Paul Holden 2023-12-13 17:10:46 +00:00
parent 95cd15ea12
commit 8f32e623bb
No known key found for this signature in database
GPG Key ID: A81A96D6045F6164

View File

@ -186,14 +186,24 @@ abstract class base_report_table extends table_sql implements dynamic, renderabl
/** /**
* Override parent method of the same, to ensure that any columns with custom sort fields are accounted for * Override parent method of the same, to ensure that any columns with custom sort fields are accounted for
* *
* Because the base table_sql has "special" handling of fullname columns {@see table_sql::contains_fullname_columns}, we need
* to handle that here to ensure that any that are being sorted take priority over reportbuilders own aliases of the same
* columns. This prevents them appearing multiple times in a query, which SQL Server really doesn't like
*
* @return string * @return string
*/ */
public function get_sql_sort() { public function get_sql_sort() {
$columnsbyalias = $this->report->get_active_columns_by_alias(); $columnsbyalias = $this->report->get_active_columns_by_alias();
$columnsortby = []; $columnsortby = [];
// First pass over sorted columns, to extract all the fullname fields from table_sql.
$sortedcolumns = $this->get_sort_columns();
$sortedcolumnsfullname = array_filter($sortedcolumns, static function(string $alias): bool {
return !preg_match('/^c[\d]+_/', $alias);
}, ARRAY_FILTER_USE_KEY);
// Iterate over all sorted report columns, replace with columns own fields if applicable. // Iterate over all sorted report columns, replace with columns own fields if applicable.
foreach ($this->get_sort_columns() as $alias => $order) { foreach ($sortedcolumns as $alias => $order) {
$column = $columnsbyalias[$alias] ?? null; $column = $columnsbyalias[$alias] ?? null;
// If the column is not being aggregated and defines custom sort fields, then use them. // If the column is not being aggregated and defines custom sort fields, then use them.
@ -208,6 +218,14 @@ abstract class base_report_table extends table_sql implements dynamic, renderabl
} }
} }
// Now ensure that any fullname sorted columns have duplicated aliases removed.
$columnsortby = array_filter($columnsortby, static function(string $alias) use ($sortedcolumnsfullname): bool {
if (preg_match('/^c[\d]+_(?<column>.*)$/', $alias, $matches)) {
return !array_key_exists($matches['column'], $sortedcolumnsfullname);
}
return true;
}, ARRAY_FILTER_USE_KEY);
return static::construct_order_by($columnsortby); return static::construct_order_by($columnsortby);
} }