From b45d17ca3051da8da47b0fdbd66ae07fab488a14 Mon Sep 17 00:00:00 2001 From: Paul Holden Date: Mon, 1 Jul 2024 10:28:11 +0100 Subject: [PATCH] MDL-80173 reportbuilder: remove various Oracle support/workarounds. "True happiness is to rejoice in the ." Reference: ba1f9cb2, 892b68d5, c63af985, 208adcf3, 9a244403, 3894fa94, 62d22c66, 628541b5, 429508a7. --- .upgradenotes/MDL-80173-2025011618240202.yml | 7 ++ .upgradenotes/MDL-83172-2024112009513041.yml | 2 +- .../reportbuilder/local/entities/task_log.php | 4 +- .../reportbuilder/local/entities/role.php | 18 +-- .../local/entities/admin_preset.php | 9 +- .../reportbuilder/local/entities/badge.php | 14 +-- .../reportbuilder/local/entities/blog.php | 13 +- .../reportbuilder/local/entities/cohort.php | 14 +-- .../reportbuilder/local/entities/comment.php | 16 +-- .../local/entities/competency.php | 10 +- .../local/entities/framework.php | 10 +- .../local/entities/course_category.php | 10 +- .../reportbuilder/local/entities/group.php | 11 +- .../reportbuilder/local/entities/grouping.php | 10 +- .../reportbuilder/local/entities/note.php | 14 +-- .../classes/local/aggregation/base.php | 4 +- .../classes/local/aggregation/count.php | 6 - .../local/aggregation/countdistinct.php | 6 - .../local/aggregation/groupconcatdistinct.php | 3 +- .../classes/local/entities/course.php | 35 +----- reportbuilder/classes/local/entities/user.php | 40 +----- reportbuilder/classes/local/filters/text.php | 11 +- .../classes/local/helpers/custom_fields.php | 27 +--- .../local/helpers/user_profile_fields.php | 23 +--- .../tests/local/filters/text_test.php | 117 ++++++------------ .../local/helpers/custom_fields_test.php | 2 +- .../helpers/user_profile_fields_test.php | 2 +- .../reportbuilder/local/entities/tag.php | 10 +- 28 files changed, 110 insertions(+), 338 deletions(-) create mode 100644 .upgradenotes/MDL-80173-2025011618240202.yml diff --git a/.upgradenotes/MDL-80173-2025011618240202.yml b/.upgradenotes/MDL-80173-2025011618240202.yml new file mode 100644 index 00000000000..d4f9b1b42f0 --- /dev/null +++ b/.upgradenotes/MDL-80173-2025011618240202.yml @@ -0,0 +1,7 @@ +issueNumber: MDL-80173 +notes: + core_reportbuilder: + - message: >- + Various Oracle-specific support/workarounds in APIs and component report + entities have been removed + type: removed diff --git a/.upgradenotes/MDL-83172-2024112009513041.yml b/.upgradenotes/MDL-83172-2024112009513041.yml index 724e86490d1..8e23b33f9d7 100644 --- a/.upgradenotes/MDL-83172-2024112009513041.yml +++ b/.upgradenotes/MDL-83172-2024112009513041.yml @@ -1,5 +1,5 @@ issueNumber: MDL-83172 notes: core: - - message: Oracle support has been removed in LMS, with the exception of report builder which will be handled in a separate issue (MDL-80173). + - message: Oracle support has been removed in LMS type: removed diff --git a/admin/classes/reportbuilder/local/entities/task_log.php b/admin/classes/reportbuilder/local/entities/task_log.php index 79b012e3399..9adb3ee9b53 100644 --- a/admin/classes/reportbuilder/local/entities/task_log.php +++ b/admin/classes/reportbuilder/local/entities/task_log.php @@ -271,8 +271,6 @@ class task_log extends base { * @return filter[] */ protected function get_all_filters(): array { - global $DB; - $tablealias = $this->get_table_alias('task_log'); // Name filter (Filter by classname). @@ -330,7 +328,7 @@ class task_log extends base { 'output', new lang_string('task_logoutput', 'admin'), $this->get_entity_name(), - $DB->sql_cast_to_char("{$tablealias}.output") + "{$tablealias}.output" )) ->add_joins($this->get_joins()); diff --git a/admin/roles/classes/reportbuilder/local/entities/role.php b/admin/roles/classes/reportbuilder/local/entities/role.php index 1b758ac8bdc..b22cc57b604 100644 --- a/admin/roles/classes/reportbuilder/local/entities/role.php +++ b/admin/roles/classes/reportbuilder/local/entities/role.php @@ -83,8 +83,6 @@ class role extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $contextalias = $this->get_table_alias('context'); $rolealias = $this->get_table_alias('role'); @@ -97,9 +95,9 @@ class role extends base { ->add_joins($this->get_joins()) ->add_fields("{$rolealias}.name, {$rolealias}.shortname, {$rolealias}.id, {$contextalias}.id AS contextid") ->add_fields(context_helper::get_preload_record_columns_sql($contextalias)) - // The sorting is on name, unless empty (determined by single space - thanks Oracle) then we use shortname. + // The sorting is on name, unless empty then we use shortname. ->set_is_sortable(true, [ - "CASE WHEN " . $DB->sql_concat("{$rolealias}.name", "' '") . " = ' ' + "CASE WHEN COALESCE({$rolealias}.name, '') = '' THEN {$rolealias}.shortname ELSE {$rolealias}.name END", @@ -123,9 +121,9 @@ class role extends base { )) ->add_joins($this->get_joins()) ->add_fields("{$rolealias}.name, {$rolealias}.shortname") - // The sorting is on name, unless empty (determined by single space - thanks Oracle) then we use shortname. + // The sorting is on name, unless empty then we use shortname. ->set_is_sortable(true, [ - "CASE WHEN " . $DB->sql_concat("{$rolealias}.name", "' '") . " = ' ' + "CASE WHEN COALESCE({$rolealias}.name, '') = '' THEN {$rolealias}.shortname ELSE {$rolealias}.name END", @@ -161,10 +159,6 @@ class role extends base { ->set_is_sortable(true); // Description column. - $descriptionfieldsql = "{$rolealias}.description"; - if ($DB->get_dbfamily() === 'oracle') { - $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024); - } $columns[] = (new column( 'description', new lang_string('description'), @@ -172,8 +166,8 @@ class role extends base { )) ->add_joins($this->get_joins()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($descriptionfieldsql, 'description') - ->add_field("{$rolealias}.shortname") + ->add_fields("{$rolealias}.description, {$rolealias}.shortname") + ->set_is_sortable(true) ->add_callback(fn(?string $description, stdClass $role) => match ($description) { null => '', default => role_get_description($role), diff --git a/admin/tool/admin_presets/classes/reportbuilder/local/entities/admin_preset.php b/admin/tool/admin_presets/classes/reportbuilder/local/entities/admin_preset.php index 321572a7a3b..74203b20877 100644 --- a/admin/tool/admin_presets/classes/reportbuilder/local/entities/admin_preset.php +++ b/admin/tool/admin_presets/classes/reportbuilder/local/entities/admin_preset.php @@ -81,7 +81,6 @@ class admin_preset extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; $apalias = $this->get_table_alias('adminpresets'); // Name. @@ -106,10 +105,6 @@ class admin_preset extends base { }); // Description. - $descriptionfieldsql = "{$apalias}.comments"; - if ($DB->get_dbfamily() === 'oracle') { - $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024); - } $columns[] = (new column( 'description', new lang_string('description'), @@ -117,9 +112,9 @@ class admin_preset extends base { )) ->add_joins($this->get_joins()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($descriptionfieldsql, 'description') + ->add_field("{$apalias}.comments") ->set_is_sortable(true) - ->set_callback(static function(?string $description, \stdClass $row): string { + ->set_callback(static function(?string $description): string { return format_text($description, FORMAT_HTML, ['context' => \context_system::instance()]); }); diff --git a/badges/classes/reportbuilder/local/entities/badge.php b/badges/classes/reportbuilder/local/entities/badge.php index 16b337d9e33..e01831490d3 100644 --- a/badges/classes/reportbuilder/local/entities/badge.php +++ b/badges/classes/reportbuilder/local/entities/badge.php @@ -95,8 +95,6 @@ class badge extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $badgealias = $this->get_table_alias('badge'); $contextalias = $this->get_table_alias('context'); @@ -131,10 +129,6 @@ class badge extends base { }); // Description (note, this column contains plaintext so requires no post-processing). - $descriptionfieldsql = "{$badgealias}.description"; - if ($DB->get_dbfamily() === 'oracle') { - $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024); - } $columns[] = (new column( 'description', new lang_string('description', 'core_badges'), @@ -142,7 +136,8 @@ class badge extends base { )) ->add_joins($this->get_joins()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($descriptionfieldsql, 'description'); + ->add_field("{$badgealias}.description") + ->set_is_sortable(true); // Criteria. $columns[] = (new column( @@ -177,8 +172,7 @@ class badge extends base { ->add_join("LEFT JOIN {context} {$contextalias} ON {$contextalias}.contextlevel = " . CONTEXT_COURSE . " AND {$contextalias}.instanceid = {$badgealias}.courseid") - ->add_fields("{$badgealias}.id, {$badgealias}.type, {$badgealias}.courseid") - ->add_field($DB->sql_cast_to_char("{$badgealias}.imagecaption"), 'imagecaption') + ->add_fields("{$badgealias}.id, {$badgealias}.type, {$badgealias}.courseid, {$badgealias}.imagecaption") ->add_fields(context_helper::get_preload_record_columns_sql($contextalias)) ->add_callback(static function($value, stdClass $badge): string { if ($badge->id === null) { @@ -271,8 +265,6 @@ class badge extends base { * @return filter[] */ protected function get_all_filters(): array { - global $DB; - $badgealias = $this->get_table_alias('badge'); // Name. diff --git a/blog/classes/reportbuilder/local/entities/blog.php b/blog/classes/reportbuilder/local/entities/blog.php index f9d634f60d6..bdcd2889d67 100644 --- a/blog/classes/reportbuilder/local/entities/blog.php +++ b/blog/classes/reportbuilder/local/entities/blog.php @@ -89,8 +89,6 @@ class blog extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $postalias = $this->get_table_alias('post'); // Title. @@ -122,11 +120,6 @@ class blog extends base { }); // Body. - $summaryfieldsql = "{$postalias}.summary"; - if ($DB->get_dbfamily() === 'oracle') { - $summaryfieldsql = $DB->sql_order_by_text($summaryfieldsql, 1024); - } - $columns[] = (new column( 'body', new lang_string('entrybody', 'core_blog'), @@ -134,8 +127,8 @@ class blog extends base { )) ->add_joins($this->get_joins()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($summaryfieldsql, 'summary') - ->add_fields("{$postalias}.summaryformat, {$postalias}.id") + ->add_fields("{$postalias}.summary, {$postalias}.summaryformat, {$postalias}.id") + ->set_is_sortable(true) ->add_callback(static function(?string $summary, stdClass $post): string { global $CFG; require_once("{$CFG->libdir}/filelib.php"); @@ -259,7 +252,7 @@ class blog extends base { 'body', new lang_string('entrybody', 'core_blog'), $this->get_entity_name(), - $DB->sql_cast_to_char("{$postalias}.summary") + "{$postalias}.summary" )) ->add_joins($this->get_joins()); diff --git a/cohort/classes/reportbuilder/local/entities/cohort.php b/cohort/classes/reportbuilder/local/entities/cohort.php index 0cc77fdb7b4..4fca506d7ad 100644 --- a/cohort/classes/reportbuilder/local/entities/cohort.php +++ b/cohort/classes/reportbuilder/local/entities/cohort.php @@ -102,8 +102,6 @@ class cohort extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $tablealias = $this->get_table_alias('cohort'); $contextalias = $this->get_table_alias('context'); @@ -150,10 +148,6 @@ class cohort extends base { ->set_is_sortable(true); // Description column. - $descriptionfieldsql = "{$tablealias}.description"; - if ($DB->get_dbfamily() === 'oracle') { - $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024); - } $columns[] = (new column( 'description', new lang_string('description'), @@ -162,9 +156,9 @@ class cohort extends base { ->add_joins($this->get_joins()) ->add_join($this->get_context_join()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($descriptionfieldsql, 'description') - ->add_fields("{$tablealias}.descriptionformat, {$tablealias}.id, {$tablealias}.contextid") + ->add_fields("{$tablealias}.description, {$tablealias}.descriptionformat, {$tablealias}.id, {$tablealias}.contextid") ->add_fields(context_helper::get_preload_record_columns_sql($contextalias)) + ->set_is_sortable(true) ->add_callback(static function(?string $description, stdClass $cohort): string { global $CFG; require_once("{$CFG->libdir}/filelib.php"); @@ -265,8 +259,6 @@ class cohort extends base { * @return filter[] */ protected function get_all_filters(): array { - global $DB; - $tablealias = $this->get_table_alias('cohort'); // Cohort select filter. @@ -343,7 +335,7 @@ class cohort extends base { 'description', new lang_string('description'), $this->get_entity_name(), - $DB->sql_cast_to_char("{$tablealias}.description") + "{$tablealias}.description" )) ->add_joins($this->get_joins()); diff --git a/comment/classes/reportbuilder/local/entities/comment.php b/comment/classes/reportbuilder/local/entities/comment.php index 4ddced0d408..a890e4bdf40 100644 --- a/comment/classes/reportbuilder/local/entities/comment.php +++ b/comment/classes/reportbuilder/local/entities/comment.php @@ -85,16 +85,10 @@ class comment extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $commentalias = $this->get_table_alias('comments'); $contextalias = $this->get_table_alias('context'); // Content. - $contentfieldsql = "{$commentalias}.content"; - if ($DB->get_dbfamily() === 'oracle') { - $contentfieldsql = $DB->sql_order_by_text($contentfieldsql, 1024); - } $columns[] = (new column( 'content', new lang_string('content'), @@ -103,9 +97,9 @@ class comment extends base { ->add_joins($this->get_joins()) ->set_type(column::TYPE_LONGTEXT) ->add_join($this->get_context_join()) - ->add_field($contentfieldsql, 'content') - ->add_fields("{$commentalias}.format, {$commentalias}.contextid, " . - context_helper::get_preload_record_columns_sql($contextalias)) + ->add_fields("{$commentalias}.content, {$commentalias}.format, {$commentalias}.contextid") + ->add_fields(context_helper::get_preload_record_columns_sql($contextalias)) + ->set_is_sortable(true) ->add_callback(static function($content, stdClass $comment): string { if ($content === null) { return ''; @@ -170,8 +164,6 @@ class comment extends base { * @return filter[] */ protected function get_all_filters(): array { - global $DB; - $commentalias = $this->get_table_alias('comments'); // Content. @@ -180,7 +172,7 @@ class comment extends base { 'content', new lang_string('content'), $this->get_entity_name(), - $DB->sql_cast_to_char("{$commentalias}.content") + "{$commentalias}.content" )) ->add_joins($this->get_joins()); diff --git a/competency/classes/reportbuilder/local/entities/competency.php b/competency/classes/reportbuilder/local/entities/competency.php index 25e2106091c..3b70ce414ee 100644 --- a/competency/classes/reportbuilder/local/entities/competency.php +++ b/competency/classes/reportbuilder/local/entities/competency.php @@ -84,8 +84,6 @@ class competency extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $contextalias = $this->get_table_alias('context'); $competencyalias = $this->get_table_alias('competency'); @@ -100,10 +98,6 @@ class competency extends base { ->set_is_sortable(true); // Description. - $descriptionfieldsql = "{$competencyalias}.description"; - if ($DB->get_dbfamily() === 'oracle') { - $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024); - } $columns[] = (new column( 'description', new lang_string('description'), @@ -112,9 +106,9 @@ class competency extends base { ->add_joins($this->get_joins()) ->add_joins($this->get_context_joins()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($descriptionfieldsql, 'description') - ->add_field("{$competencyalias}.descriptionformat") + ->add_fields("{$competencyalias}.description, {$competencyalias}.descriptionformat") ->add_fields(context_helper::get_preload_record_columns_sql($contextalias)) + ->set_is_sortable(true) ->add_callback(static function(?string $description, stdClass $competency): string { if ($description === null) { return ''; diff --git a/competency/classes/reportbuilder/local/entities/framework.php b/competency/classes/reportbuilder/local/entities/framework.php index fbdebb11416..322616f4140 100644 --- a/competency/classes/reportbuilder/local/entities/framework.php +++ b/competency/classes/reportbuilder/local/entities/framework.php @@ -84,8 +84,6 @@ class framework extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $frameworkalias = $this->get_table_alias('competency_framework'); $contextalias = $this->get_table_alias('context'); @@ -100,10 +98,6 @@ class framework extends base { ->set_is_sortable(true); // Description. - $descriptionfieldsql = "{$frameworkalias}.description"; - if ($DB->get_dbfamily() === 'oracle') { - $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024); - } $columns[] = (new column( 'description', new lang_string('description'), @@ -112,9 +106,9 @@ class framework extends base { ->add_joins($this->get_joins()) ->add_join($this->get_context_join()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($descriptionfieldsql, 'description') - ->add_field("{$frameworkalias}.descriptionformat") + ->add_fields("{$frameworkalias}.description, {$frameworkalias}.descriptionformat") ->add_fields(context_helper::get_preload_record_columns_sql($contextalias)) + ->set_is_sortable(true) ->add_callback(static function(?string $description, stdClass $framework): string { if ($description === null) { return ''; diff --git a/course/classes/reportbuilder/local/entities/course_category.php b/course/classes/reportbuilder/local/entities/course_category.php index 31f9586ad32..a55d878e3b6 100644 --- a/course/classes/reportbuilder/local/entities/course_category.php +++ b/course/classes/reportbuilder/local/entities/course_category.php @@ -89,8 +89,6 @@ class course_category extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $tablealias = $this->get_table_alias('course_categories'); $tablealiascontext = $this->get_table_alias('context'); @@ -168,10 +166,6 @@ class course_category extends base { ->set_is_sortable(true); // Description column (note we need to join/select from the context table in order to format the column). - $descriptionfieldsql = "{$tablealias}.description"; - if ($DB->get_dbfamily() === 'oracle') { - $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024); - } $columns[] = (new column( 'description', new lang_string('description'), @@ -180,9 +174,9 @@ class course_category extends base { ->add_joins($this->get_joins()) ->add_join($this->get_context_join()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($descriptionfieldsql, 'description') - ->add_fields("{$tablealias}.descriptionformat, {$tablealias}.id") + ->add_fields("{$tablealias}.description, {$tablealias}.descriptionformat, {$tablealias}.id") ->add_fields(context_helper::get_preload_record_columns_sql($tablealiascontext)) + ->set_is_sortable(true) ->add_callback(static function(?string $description, stdClass $category): string { global $CFG; require_once("{$CFG->libdir}/filelib.php"); diff --git a/group/classes/reportbuilder/local/entities/group.php b/group/classes/reportbuilder/local/entities/group.php index 5348f4e672b..8eaf901e9ee 100644 --- a/group/classes/reportbuilder/local/entities/group.php +++ b/group/classes/reportbuilder/local/entities/group.php @@ -102,8 +102,6 @@ class group extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $contextalias = $this->get_table_alias('context'); $groupsalias = $this->get_table_alias('groups'); @@ -141,10 +139,6 @@ class group extends base { ->set_is_sortable(true); // Description column. - $descriptionfieldsql = "{$groupsalias}.description"; - if ($DB->get_dbfamily() === 'oracle') { - $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024); - } $columns[] = (new column( 'description', new lang_string('description'), @@ -152,10 +146,9 @@ class group extends base { )) ->add_joins($this->get_joins()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($descriptionfieldsql, 'description') - ->add_fields("{$groupsalias}.descriptionformat, {$groupsalias}.id, {$groupsalias}.courseid") + ->add_fields("{$groupsalias}.description, {$groupsalias}.descriptionformat, {$groupsalias}.id, {$groupsalias}.courseid") ->add_fields(context_helper::get_preload_record_columns_sql($contextalias)) - ->set_is_sortable(false) + ->set_is_sortable(true) ->set_callback(static function(?string $description, stdClass $group): string { global $CFG; diff --git a/group/classes/reportbuilder/local/entities/grouping.php b/group/classes/reportbuilder/local/entities/grouping.php index 39570820bc0..edee4cd4cb4 100644 --- a/group/classes/reportbuilder/local/entities/grouping.php +++ b/group/classes/reportbuilder/local/entities/grouping.php @@ -95,8 +95,6 @@ class grouping extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $contextalias = $this->get_table_alias('context'); $groupingsalias = $this->get_table_alias('groupings'); @@ -134,10 +132,6 @@ class grouping extends base { ->set_is_sortable(true); // Description column. - $descriptionfieldsql = "{$groupingsalias}.description"; - if ($DB->get_dbfamily() === 'oracle') { - $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024); - } $columns[] = (new column( 'description', new lang_string('description'), @@ -145,10 +139,10 @@ class grouping extends base { )) ->add_joins($this->get_joins()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($descriptionfieldsql, 'description') + ->add_field("{$groupingsalias}.description") ->add_fields("{$groupingsalias}.descriptionformat, {$groupingsalias}.id, {$groupingsalias}.courseid") ->add_fields(context_helper::get_preload_record_columns_sql($contextalias)) - ->set_is_sortable(false) + ->set_is_sortable(true) ->set_callback(static function(?string $description, stdClass $grouping): string { global $CFG; diff --git a/notes/classes/reportbuilder/local/entities/note.php b/notes/classes/reportbuilder/local/entities/note.php index 0bc05b30fb1..830ea1e73c1 100644 --- a/notes/classes/reportbuilder/local/entities/note.php +++ b/notes/classes/reportbuilder/local/entities/note.php @@ -87,15 +87,9 @@ class note extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $postalias = $this->get_table_alias('post'); // Content. - $contentfieldsql = "{$postalias}.content"; - if ($DB->get_dbfamily() === 'oracle') { - $contentfieldsql = $DB->sql_order_by_text($contentfieldsql, 1024); - } $columns[] = (new column( 'content', new lang_string('content', 'core_notes'), @@ -103,8 +97,8 @@ class note extends base { )) ->add_joins($this->get_joins()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($contentfieldsql, 'content') - ->add_field("{$postalias}.format") + ->add_fields("{$postalias}.content, {$postalias}.format") + ->set_is_sortable(true) ->add_callback(static function(?string $content, stdClass $note): string { if ($content === null) { return ''; @@ -165,8 +159,6 @@ class note extends base { * @return filter[] */ protected function get_all_filters(): array { - global $DB; - $postalias = $this->get_table_alias('post'); // Content. @@ -175,7 +167,7 @@ class note extends base { 'content', new lang_string('content', 'core_notes'), $this->get_entity_name(), - $DB->sql_cast_to_char("{$postalias}.content") + "{$postalias}.content" )) ->add_joins($this->get_joins()); diff --git a/reportbuilder/classes/local/aggregation/base.php b/reportbuilder/classes/local/aggregation/base.php index 33a1001fdf5..79c3b4ce024 100644 --- a/reportbuilder/classes/local/aggregation/base.php +++ b/reportbuilder/classes/local/aggregation/base.php @@ -91,8 +91,8 @@ abstract class base { ): string { global $DB; - // We need to ensure all values are char. - $sqlfieldrequirescast = in_array($DB->get_dbfamily(), ['mssql', 'oracle', 'postgres']); + // We need to ensure all values are char in supported DBs. + $sqlfieldrequirescast = in_array($DB->get_dbfamily(), ['mssql', 'postgres']); $concatfields = []; foreach ($sqlfields as $sqlfield) { diff --git a/reportbuilder/classes/local/aggregation/count.php b/reportbuilder/classes/local/aggregation/count.php index 681283c4b68..f2d4ab5e606 100644 --- a/reportbuilder/classes/local/aggregation/count.php +++ b/reportbuilder/classes/local/aggregation/count.php @@ -57,12 +57,6 @@ class count extends base { * @return string */ public static function get_field_sql(string $field, int $columntype): string { - global $DB; - - if ($columntype === column::TYPE_LONGTEXT && $DB->get_dbfamily() === 'oracle') { - $field = $DB->sql_compare_text($field, 255); - } - return "COUNT({$field})"; } diff --git a/reportbuilder/classes/local/aggregation/countdistinct.php b/reportbuilder/classes/local/aggregation/countdistinct.php index cb190869c77..0b4a834ef88 100644 --- a/reportbuilder/classes/local/aggregation/countdistinct.php +++ b/reportbuilder/classes/local/aggregation/countdistinct.php @@ -71,12 +71,6 @@ class countdistinct extends base { * @return string */ public static function get_field_sql(string $field, int $columntype): string { - global $DB; - - if ($columntype === column::TYPE_LONGTEXT && $DB->get_dbfamily() === 'oracle') { - $field = $DB->sql_compare_text($field, 255); - } - return "COUNT(DISTINCT {$field})"; } diff --git a/reportbuilder/classes/local/aggregation/groupconcatdistinct.php b/reportbuilder/classes/local/aggregation/groupconcatdistinct.php index 9751ebea9fc..f1a8961e168 100644 --- a/reportbuilder/classes/local/aggregation/groupconcatdistinct.php +++ b/reportbuilder/classes/local/aggregation/groupconcatdistinct.php @@ -40,7 +40,7 @@ class groupconcatdistinct extends groupconcat { } /** - * This aggregation can be performed on all non-timestamp columns in MySQL, Postgres and Oracle only + * This aggregation can be performed on all non-timestamp columns in supported DBs * * @param int $columntype * @return bool @@ -51,7 +51,6 @@ class groupconcatdistinct extends groupconcat { $dbsupportedtype = in_array($DB->get_dbfamily(), [ 'mysql', 'postgres', - 'oracle', ]); return $dbsupportedtype && parent::compatible($columntype); diff --git a/reportbuilder/classes/local/entities/course.php b/reportbuilder/classes/local/entities/course.php index a21ea0a51f4..eb6ee11d58d 100644 --- a/reportbuilder/classes/local/entities/course.php +++ b/reportbuilder/classes/local/entities/course.php @@ -146,21 +146,6 @@ class course extends base { ]; } - /** - * Check if this field is sortable - * - * @param string $fieldname - * @return bool - */ - protected function is_sortable(string $fieldname): bool { - // Some columns can't be sorted, like longtext or images. - $nonsortable = [ - 'summary', - ]; - - return !in_array($fieldname, $nonsortable); - } - /** * Return appropriate column type for given user field * @@ -219,8 +204,6 @@ class course extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $coursefields = $this->get_course_fields(); $tablealias = $this->get_table_alias('course'); $contexttablealias = $this->get_table_alias('context'); @@ -264,11 +247,6 @@ class course extends base { foreach ($coursefields as $coursefield => $coursefieldlang) { $columntype = $this->get_course_field_type($coursefield); - $columnfieldsql = "{$tablealias}.{$coursefield}"; - if ($columntype === column::TYPE_LONGTEXT && $DB->get_dbfamily() === 'oracle') { - $columnfieldsql = $DB->sql_order_by_text($columnfieldsql, 1024); - } - $column = (new column( $coursefield, $coursefieldlang, @@ -276,9 +254,9 @@ class course extends base { )) ->add_joins($this->get_joins()) ->set_type($columntype) - ->add_field($columnfieldsql, $coursefield) + ->add_field("{$tablealias}.{$coursefield}") ->add_callback([$this, 'format'], $coursefield) - ->set_is_sortable($this->is_sortable($coursefield)); + ->set_is_sortable(true); // Join on the context table so that we can use it for formatting these columns later. if ($coursefield === 'summary' || $coursefield === 'shortname' || $coursefield === 'fullname') { @@ -299,18 +277,11 @@ class course extends base { * @return array */ protected function get_all_filters(): array { - global $DB; - $filters = []; $tablealias = $this->get_table_alias('course'); $fields = $this->get_course_fields(); foreach ($fields as $field => $name) { - $filterfieldsql = "{$tablealias}.{$field}"; - if ($this->get_course_field_type($field) === column::TYPE_LONGTEXT) { - $filterfieldsql = $DB->sql_cast_to_char($filterfieldsql); - } - $optionscallback = [static::class, 'get_options_for_' . $field]; if (is_callable($optionscallback)) { $filterclass = select::class; @@ -327,7 +298,7 @@ class course extends base { $field, $name, $this->get_entity_name(), - $filterfieldsql + "{$tablealias}.{$field}" )) ->add_joins($this->get_joins()); diff --git a/reportbuilder/classes/local/entities/user.php b/reportbuilder/classes/local/entities/user.php index 7e35f4ea5a0..c9c0481bd7b 100644 --- a/reportbuilder/classes/local/entities/user.php +++ b/reportbuilder/classes/local/entities/user.php @@ -203,7 +203,7 @@ class user extends base { )) ->add_joins($this->get_joins()) ->add_fields($fullnameselect) - ->set_is_sortable($this->is_sortable('fullname'), $fullnamesort) + ->set_is_sortable(true, $fullnamesort) ->add_callback(static function($value, stdClass $row) use ($viewfullnames): string { // Ensure we have at least one field present. @@ -235,7 +235,7 @@ class user extends base { ->add_joins($this->get_joins()) ->add_fields($fullnameselect) ->add_field("{$usertablealias}.id") - ->set_is_sortable($this->is_sortable($fullnamefield), $fullnamesort) + ->set_is_sortable(true, $fullnamesort) ->add_callback(static function($value, stdClass $row) use ($fullnamefield, $viewfullnames): string { global $OUTPUT; @@ -283,7 +283,6 @@ class user extends base { )) ->add_joins($this->get_joins()) ->add_fields($userpictureselect) - ->set_is_sortable($this->is_sortable('picture')) ->add_callback(static function($value, stdClass $row): string { global $OUTPUT; @@ -295,11 +294,6 @@ class user extends base { foreach ($userfields as $userfield => $userfieldlang) { $columntype = $this->get_user_field_type($userfield); - $columnfieldsql = "{$usertablealias}.{$userfield}"; - if ($columntype === column::TYPE_LONGTEXT && $DB->get_dbfamily() === 'oracle') { - $columnfieldsql = $DB->sql_order_by_text($columnfieldsql, 1024); - } - $column = (new column( $userfield, $userfieldlang, @@ -307,8 +301,8 @@ class user extends base { )) ->add_joins($this->get_joins()) ->set_type($columntype) - ->add_field($columnfieldsql, $userfield) - ->set_is_sortable($this->is_sortable($userfield)) + ->add_field("{$usertablealias}.{$userfield}") + ->set_is_sortable(true) ->add_callback([$this, 'format'], $userfield); // Join on the context table so that we can use it for formatting these columns later. @@ -327,22 +321,6 @@ class user extends base { return $columns; } - /** - * Check if this field is sortable - * - * @param string $fieldname - * @return bool - */ - protected function is_sortable(string $fieldname): bool { - // Some columns can't be sorted, like longtext or images. - $nonsortable = [ - 'description', - 'picture', - ]; - - return !in_array($fieldname, $nonsortable); - } - /** * Formats the user field for display. * @@ -488,9 +466,6 @@ class user extends base { * @return filter[] */ protected function get_all_filters(): array { - global $DB; - - $filters = []; $tablealias = $this->get_table_alias('user'); // Fullname filter. @@ -519,11 +494,6 @@ class user extends base { // User fields filters. $fields = $this->get_user_fields(); foreach ($fields as $field => $name) { - $filterfieldsql = "{$tablealias}.{$field}"; - if ($this->get_user_field_type($field) === column::TYPE_LONGTEXT) { - $filterfieldsql = $DB->sql_cast_to_char($filterfieldsql); - } - $optionscallback = [static::class, 'get_options_for_' . $field]; if (is_callable($optionscallback)) { $classname = select::class; @@ -540,7 +510,7 @@ class user extends base { $field, $name, $this->get_entity_name(), - $filterfieldsql + "{$tablealias}.{$field}" )) ->add_joins($this->get_joins()); diff --git a/reportbuilder/classes/local/filters/text.php b/reportbuilder/classes/local/filters/text.php index f543272a9e0..ce268e95660 100644 --- a/reportbuilder/classes/local/filters/text.php +++ b/reportbuilder/classes/local/filters/text.php @@ -109,7 +109,6 @@ class text extends base { */ public function get_sql_filter(array $values): array { global $DB; - $name = database::generate_param_name(); $operator = (int) ($values["{$this->name}_operator"] ?? self::ANY_VALUE); $value = trim($values["{$this->name}_value"] ?? ''); @@ -123,6 +122,8 @@ class text extends base { return ['', []]; } + $name = database::generate_param_name(); + switch($operator) { case self::CONTAINS: $res = $DB->sql_like($fieldsql, ":$name", false, false); @@ -153,14 +154,10 @@ class text extends base { $params[$name] = "%$value"; break; case self::IS_EMPTY: - $paramempty = database::generate_param_name(); - $res = "COALESCE({$fieldsql}, :{$paramempty}) = :{$name}"; - $params[$paramempty] = $params[$name] = ''; + $res = "COALESCE({$fieldsql}, '') = ''"; break; case self::IS_NOT_EMPTY: - $paramempty = database::generate_param_name(); - $res = "COALESCE({$fieldsql}, :{$paramempty}) != :{$name}"; - $params[$paramempty] = $params[$name] = ''; + $res = "COALESCE({$fieldsql}, '') != ''"; break; default: // Filter configuration is invalid. Ignore the filter. diff --git a/reportbuilder/classes/local/helpers/custom_fields.php b/reportbuilder/classes/local/helpers/custom_fields.php index da0e67b5ebc..7895088aaca 100644 --- a/reportbuilder/classes/local/helpers/custom_fields.php +++ b/reportbuilder/classes/local/helpers/custom_fields.php @@ -103,8 +103,6 @@ class custom_fields { * @return column[] */ public function get_columns(): array { - global $DB; - $columns = []; $categorieswithfields = $this->handler->get_categories_with_fields(); @@ -117,18 +115,16 @@ class custom_fields { $customdatatablealias = $this->get_table_alias($field); $customdatasql = "{$customdatatablealias}.{$datafield}"; - // Numeric column (non-text) should coalesce with default, as should text fields for Oracle, for aggregation. + // Numeric column (non-text) should coalesce with default, for aggregation. $columntype = $this->get_column_type($field, $datafield); if (!in_array($columntype, [column::TYPE_TEXT, column::TYPE_LONGTEXT])) { - // See MDL-78783 regarding no bound parameters, and Oracle limitations of GROUP BY. + // See MDL-78783 regarding no bound parameters, and SQL Server limitations of GROUP BY. $customdatasql = " CASE WHEN {$this->tablefieldalias} IS NOT NULL THEN COALESCE({$customdatasql}, " . (float) $datacontroller->get_default_value() . ") ELSE NULL END"; - } else if ($columntype === column::TYPE_LONGTEXT && $DB->get_dbfamily() === 'oracle') { - $customdatasql = $DB->sql_order_by_text($customdatasql, 1024); } // Select enough fields to re-create and format each custom field instance value. @@ -145,11 +141,11 @@ class custom_fields { )) ->add_joins($this->get_joins()) ->add_join($this->get_table_join($field)) + ->set_type($columntype) ->add_field($customdatasql, $datafield) ->add_fields($customdatasqlextra) ->add_field($this->tablefieldalias, 'tablefieldalias') - ->set_type($columntype) - ->set_is_sortable($columntype !== column::TYPE_LONGTEXT) + ->set_is_sortable(true) ->add_callback(static function($value, stdClass $row, field_controller $field, ?string $aggregation): string { if ($row->tablefieldalias === null && $value === null) { return ''; @@ -211,8 +207,6 @@ class custom_fields { * @return filter[] */ public function get_filters(): array { - global $DB; - $filters = []; $categorieswithfields = $this->handler->get_categories_with_fields(); @@ -226,23 +220,12 @@ class custom_fields { $customdatasql = "{$customdatatablealias}.{$datafield}"; $customdataparams = []; - if ($datafield === 'value') { - $customdatasql = $DB->sql_cast_to_char($customdatasql); - } - // Account for field default value, when joined to the instance table related to the custom fields. if (($fielddefault = $datacontroller->get_default_value()) !== null) { $paramdefault = database::generate_param_name(); - - // Oracle be crazy. - $paramdefaultsql = ":{$paramdefault}"; - if ($DB->get_dbfamily() === 'oracle' && in_array($datafield, ['intvalue', 'decvalue'])) { - $paramdefaultsql = $DB->sql_cast_char2int($paramdefaultsql); - } - $customdatasql = " CASE WHEN {$this->tablefieldalias} IS NOT NULL - THEN COALESCE({$customdatasql}, {$paramdefaultsql}) + THEN COALESCE({$customdatasql}, :{$paramdefault}) ELSE NULL END"; $customdataparams[$paramdefault] = $fielddefault; diff --git a/reportbuilder/classes/local/helpers/user_profile_fields.php b/reportbuilder/classes/local/helpers/user_profile_fields.php index 06f88192c11..6e3c92c4718 100644 --- a/reportbuilder/classes/local/helpers/user_profile_fields.php +++ b/reportbuilder/classes/local/helpers/user_profile_fields.php @@ -107,15 +107,11 @@ class user_profile_fields { $userinfotablealias = $this->get_table_alias($profilefield); $userinfosql = "{$userinfotablealias}.data"; - if ($DB->get_dbfamily() === 'oracle') { - $userinfosql = $DB->sql_order_by_text($userinfosql, 1024); - } - - // Numeric column (non-text) should cast/coalesce with default, as should all fields for Oracle, for aggregation. + // Numeric column (non-text) should coalesce with default, for aggregation. $columntype = $this->get_user_field_type($profilefield->field->datatype); if (!in_array($columntype, [column::TYPE_TEXT, column::TYPE_LONGTEXT])) { - // See MDL-78783 regarding no bound parameters, and Oracle limitations of GROUP BY. + // See MDL-78783 regarding no bound parameters, and SQL Server limitations of GROUP BY. $userinfosql = " CASE WHEN {$this->usertablefieldalias} IS NOT NULL THEN " . @@ -133,11 +129,11 @@ class user_profile_fields { )) ->add_joins($this->get_joins()) ->add_join($this->get_table_join($profilefield)) + ->set_type($columntype) ->add_field($userinfosql, 'data') ->add_field("{$userinfotablealias}.dataformat") ->add_field($this->usertablefieldalias, 'userid') - ->set_type($columntype) - ->set_is_sortable($columntype !== column::TYPE_LONGTEXT) + ->set_is_sortable(true) ->add_callback(static function($value, stdClass $row, profile_field_base $field): string { if ($row->userid === null && $value === null) { return ''; @@ -183,29 +179,20 @@ class user_profile_fields { break; case 'menu': $classname = select::class; - $userinfosql = $DB->sql_cast_to_char($userinfosql); break; case 'text': case 'textarea': default: $classname = text::class; - $userinfosql = $DB->sql_cast_to_char($userinfosql); break; } // Account for field default value, when joined to the user table. if (($fielddefault = $profilefield->field->defaultdata) !== null) { $paramdefault = database::generate_param_name(); - - // Oracle be crazy. - $paramdefaultsql = ":{$paramdefault}"; - if ($DB->get_dbfamily() === 'oracle' && in_array($profilefield->field->datatype, ['checkbox', 'datetime'])) { - $paramdefaultsql = $DB->sql_cast_char2int($paramdefaultsql); - } - $userinfosql = " CASE WHEN {$this->usertablefieldalias} IS NOT NULL - THEN COALESCE({$userinfosql}, {$paramdefaultsql}) + THEN COALESCE({$userinfosql}, :{$paramdefault}) ELSE NULL END"; $userinfoparams[$paramdefault] = $fielddefault; diff --git a/reportbuilder/tests/local/filters/text_test.php b/reportbuilder/tests/local/filters/text_test.php index 06eb79e2ace..518a8270bbe 100644 --- a/reportbuilder/tests/local/filters/text_test.php +++ b/reportbuilder/tests/local/filters/text_test.php @@ -19,7 +19,7 @@ declare(strict_types=1); namespace core_reportbuilder\local\filters; use advanced_testcase; -use lang_string; +use core\lang_string; use core_reportbuilder\local\report\filter; /** @@ -40,25 +40,33 @@ final class text_test extends advanced_testcase { */ public static function get_sql_filter_simple_provider(): array { return [ - [text::ANY_VALUE, null, true], - [text::CONTAINS, 'looking', true], - [text::CONTAINS, 'sky', false], - [text::DOES_NOT_CONTAIN, 'sky', true], - [text::DOES_NOT_CONTAIN, 'looking', false], - [text::IS_EQUAL_TO, "Hello, is it me you're looking for?", true], - [text::IS_EQUAL_TO, 'I can see it in your eyes', false], - [text::IS_NOT_EQUAL_TO, "Hello, is it me you're looking for?", false], - [text::IS_NOT_EQUAL_TO, 'I can see it in your eyes', true], - [text::STARTS_WITH, 'Hello', true], - [text::STARTS_WITH, 'sunlight', false], - [text::ENDS_WITH, 'looking for?', true], - [text::ENDS_WITH, 'your heart', false], + [text::ANY_VALUE, 'Looking for', null, true], + [text::CONTAINS, 'Looking for', 'king', true], + [text::CONTAINS, 'Looking for', 'sky', false], + [text::DOES_NOT_CONTAIN, 'Looking for', 'sky', true], + [text::DOES_NOT_CONTAIN, 'Looking for', 'king', false], + [text::IS_EQUAL_TO, 'Looking for', 'Looking for', true], + [text::IS_EQUAL_TO, 'Looking for', 'Your eyes', false], + [text::IS_NOT_EQUAL_TO, 'Looking for', 'Looking for', false], + [text::IS_NOT_EQUAL_TO, 'Looking for', 'Your eyes', true], + [text::STARTS_WITH, 'Looking for', 'Looking', true], + [text::STARTS_WITH, 'Looking for', 'Your', false], + [text::ENDS_WITH, 'Looking for', 'for', true], + [text::ENDS_WITH, 'Looking for', 'eyes', false], + + // Empty content. + [text::IS_EMPTY, null, null, true], + [text::IS_EMPTY, '', null, true], + [text::IS_EMPTY, 'Looking for', null, false], + [text::IS_NOT_EMPTY, null, null, false], + [text::IS_NOT_EMPTY, '', null, false], + [text::IS_NOT_EMPTY, 'Looking for', null, true], // Ensure whitespace is trimmed. - [text::CONTAINS, ' looking for ', true], - [text::IS_EQUAL_TO, ' Hello, is it me you\'re looking for? ', true], - [text::STARTS_WITH, ' Hello, is it me ', true], - [text::ENDS_WITH, ' you\'re looking for? ', true], + [text::CONTAINS, 'Looking for', ' Looking for ', true], + [text::IS_EQUAL_TO, 'Looking for', ' Looking for ', true], + [text::STARTS_WITH, 'Looking for', ' Looking ', true], + [text::ENDS_WITH, 'Looking for', ' for ', true], ]; } @@ -66,18 +74,25 @@ final class text_test extends advanced_testcase { * Test getting filter SQL * * @param int $operator - * @param string|null $value + * @param string|null $fieldvalue + * @param string|null $filtervalue * @param bool $expectmatch * * @dataProvider get_sql_filter_simple_provider */ - public function test_get_sql_filter_simple(int $operator, ?string $value, bool $expectmatch): void { + public function test_get_sql_filter_simple( + int $operator, + ?string $fieldvalue, + ?string $filtervalue, + bool $expectmatch, + ): void { global $DB; $this->resetAfterTest(); + // We are using the pdfexportfont field because it is nullable. $course = $this->getDataGenerator()->create_course([ - 'fullname' => "Hello, is it me you're looking for?", + 'pdfexportfont' => $fieldvalue, ]); $filter = new filter( @@ -85,13 +100,13 @@ final class text_test extends advanced_testcase { 'test', new lang_string('course'), 'testentity', - 'fullname' + 'pdfexportfont', ); // Create instance of our filter, passing given operator. [$select, $params] = text::create($filter)->get_sql_filter([ $filter->get_unique_identifier() . '_operator' => $operator, - $filter->get_unique_identifier() . '_value' => $value, + $filter->get_unique_identifier() . '_value' => $filtervalue, ]); $fullnames = $DB->get_fieldset_select('course', 'fullname', $select, $params); @@ -101,60 +116,4 @@ final class text_test extends advanced_testcase { $this->assertNotContains($course->fullname, $fullnames); } } - - /** - * Data provider for {@see test_get_sql_filter_empty} - * - * @return array - */ - public static function get_sql_filter_empty_provider(): array { - return [ - [text::IS_EMPTY, null, true], - [text::IS_EMPTY, '', true], - [text::IS_EMPTY, 'hola', false], - [text::IS_NOT_EMPTY, null, false], - [text::IS_NOT_EMPTY, '', false], - [text::IS_NOT_EMPTY, 'hola', true], - ]; - } - - /** - * Test getting filter SQL using the {@see text::IS_EMPTY} and {@see text::IS_NOT_EMPTY} operators - * - * @param int $operator - * @param string|null $profilefieldvalue - * @param bool $expectmatch - * - * @dataProvider get_sql_filter_empty_provider - */ - public function test_get_sql_filter_empty(int $operator, ?string $profilefieldvalue, bool $expectmatch): void { - global $DB; - - $this->resetAfterTest(); - - // We are using the user.moodlenetprofile field because it is nullable. - $user = $this->getDataGenerator()->create_user([ - 'moodlenetprofile' => $profilefieldvalue, - ]); - - $filter = new filter( - text::class, - 'test', - new lang_string('user'), - 'testentity', - 'moodlenetprofile' - ); - - // Create instance of our filter, passing given operator. - [$select, $params] = text::create($filter)->get_sql_filter([ - $filter->get_unique_identifier() . '_operator' => $operator, - ]); - - $usernames = $DB->get_fieldset_select('user', 'username', $select, $params); - if ($expectmatch) { - $this->assertContains($user->username, $usernames); - } else { - $this->assertNotContains($user->username, $usernames); - } - } } diff --git a/reportbuilder/tests/local/helpers/custom_fields_test.php b/reportbuilder/tests/local/helpers/custom_fields_test.php index 1be2aee68ec..bf40563e20a 100644 --- a/reportbuilder/tests/local/helpers/custom_fields_test.php +++ b/reportbuilder/tests/local/helpers/custom_fields_test.php @@ -125,7 +125,7 @@ final class custom_fields_test extends core_reportbuilder_testcase { // Column sortable. $this->assertEquals([ true, - false, + true, true, true, true, diff --git a/reportbuilder/tests/local/helpers/user_profile_fields_test.php b/reportbuilder/tests/local/helpers/user_profile_fields_test.php index 2060320e2e5..0b9b357a052 100644 --- a/reportbuilder/tests/local/helpers/user_profile_fields_test.php +++ b/reportbuilder/tests/local/helpers/user_profile_fields_test.php @@ -130,7 +130,7 @@ final class user_profile_fields_test extends core_reportbuilder_testcase { true, true, true, - false, + true, ], array_map( fn(column $column): bool => $column->get_is_sortable(), $columns, diff --git a/tag/classes/reportbuilder/local/entities/tag.php b/tag/classes/reportbuilder/local/entities/tag.php index 4212c79b23a..75b57d6aa31 100644 --- a/tag/classes/reportbuilder/local/entities/tag.php +++ b/tag/classes/reportbuilder/local/entities/tag.php @@ -86,8 +86,6 @@ class tag extends base { * @return column[] */ protected function get_all_columns(): array { - global $DB; - $tagalias = $this->get_table_alias('tag'); // Name. @@ -126,10 +124,6 @@ class tag extends base { }); // Description. - $descriptionfieldsql = "{$tagalias}.description"; - if ($DB->get_dbfamily() === 'oracle') { - $descriptionfieldsql = $DB->sql_order_by_text($descriptionfieldsql, 1024); - } $columns[] = (new column( 'description', new lang_string('tagdescription', 'core_tag'), @@ -137,8 +131,8 @@ class tag extends base { )) ->add_joins($this->get_joins()) ->set_type(column::TYPE_LONGTEXT) - ->add_field($descriptionfieldsql, 'description') - ->add_fields("{$tagalias}.descriptionformat, {$tagalias}.id") + ->add_fields("{$tagalias}.description, {$tagalias}.descriptionformat, {$tagalias}.id") + ->set_is_sortable(true) ->add_callback(static function(?string $description, stdClass $tag): string { global $CFG; require_once("{$CFG->libdir}/filelib.php");