MDL-72184 dml: implement driver methods for casting to char.

This commit is contained in:
Paul Holden 2021-11-05 17:27:24 +00:00
parent ca583bddaf
commit 27f9929b52
5 changed files with 73 additions and 2 deletions

View File

@ -2162,6 +2162,17 @@ abstract class moodle_database {
return ' CEIL(' . $fieldname . ')';
}
/**
* Return SQL for casting to char of given field/expression. Default implementation performs implicit cast using
* concatenation with an empty string
*
* @param string $field Table field or SQL expression to be cast
* @return string
*/
public function sql_cast_to_char(string $field): string {
return $this->sql_concat("''", $field);
}
/**
* Returns the SQL to be used in order to CAST one CHAR column to INTEGER.
*

View File

@ -1554,6 +1554,16 @@ class oci_native_moodle_database extends moodle_database {
return 'MOD(' . $int1 . ', ' . $int2 . ')';
}
/**
* Return SQL for casting to char of given field/expression
*
* @param string $field Table field or SQL expression to be cast
* @return string
*/
public function sql_cast_to_char(string $field): string {
return "TO_CHAR({$field})";
}
public function sql_cast_char2int($fieldname, $text=false) {
if (!$text) {
return ' CAST(' . $fieldname . ' AS INT) ';

View File

@ -1453,6 +1453,16 @@ class pgsql_native_moodle_database extends moodle_database {
return '((' . $int1 . ') # (' . $int2 . '))';
}
/**
* Return SQL for casting to char of given field/expression
*
* @param string $field Table field or SQL expression to be cast
* @return string
*/
public function sql_cast_to_char(string $field): string {
return "CAST({$field} AS VARCHAR)";
}
public function sql_cast_char2int($fieldname, $text=false) {
return ' CAST(' . $fieldname . ' AS INT) ';
}
@ -1493,7 +1503,7 @@ class pgsql_native_moodle_database extends moodle_database {
*/
public function sql_group_concat(string $field, string $separator = ', ', string $sort = ''): string {
$fieldsort = $sort ? "ORDER BY {$sort}" : '';
return "STRING_AGG(CAST({$field} AS VARCHAR), '{$separator}' {$fieldsort})";
return "STRING_AGG(" . $this->sql_cast_to_char($field) . ", '{$separator}' {$fieldsort})";
}
public function sql_regex_supported() {

View File

@ -32,6 +32,7 @@ defined('MOODLE_INTERNAL') || die();
* @subpackage dml
* @copyright 2008 Nicolas Connault
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \moodle_database
*/
class dml_test extends database_driver_testcase {
@ -501,7 +502,7 @@ SELECT * FROM {users}
-- line 74 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->one()
-- line 83 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->two()
-- line 92 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->three()
-- line 497 of /lib/dml/tests/dml_test.php: call to test_dml_sql_debugging_fixture->four()
-- line 498 of /lib/dml/tests/dml_test.php: call to test_dml_sql_debugging_fixture->four()
EOD;
$this->assertEquals($this->unix_to_os_dirsep($expected), $out);
@ -3840,6 +3841,44 @@ EOD;
$this->assertEquals(666, $DB->get_field_sql($sql));
}
/**
* Test DML libraries sql_cast_to_char method
*
* @covers ::sql_cast_to_char
*/
public function test_cast_to_char(): void {
$DB = $this->tdb;
$dbman = $DB->get_manager();
$tableone = $this->get_test_table('one');
$tableone->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$tableone->add_field('intfield', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$tableone->add_field('details', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
$tableone->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
$dbman->create_table($tableone);
$tableonename = $tableone->getName();
$DB->insert_record($tableonename, (object) ['intfield' => 10, 'details' => 'uno']);
$DB->insert_record($tableonename, (object) ['intfield' => 20, 'details' => 'dos']);
$tabletwo = $this->get_test_table('two');
$tabletwo->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$tabletwo->add_field('charfield', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
$tabletwo->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
$dbman->create_table($tabletwo);
$tabletwoname = $tabletwo->getName();
$DB->insert_record($tabletwoname, (object) ['charfield' => '10']);
// Test by joining a char field to a cast int field (mixing types not supported across databases).
$sql = "SELECT t1.details
FROM {{$tableonename}} t1
JOIN {{$tabletwoname}} t2 ON t2.charfield = " . $DB->sql_cast_to_char('t1.intfield');
$fieldset = $DB->get_fieldset_sql($sql);
$this->assertEquals(['uno'], $fieldset);
}
public function test_cast_char2int() {
$DB = $this->tdb;
$dbman = $DB->get_manager();

View File

@ -12,6 +12,7 @@ information provided here is intended especially for developers.
an event exists with the given criteria (see MDL-72723 for details).
- Breaking: 3rd party log readers implementing interface sql_reader will need to implement get_events_select_exists()
* Added $strictness parameter to persistent `get_record` method, optionally allowing caller to ensure record exists
* New DML driver method `$DB->sql_cast_to_char` for casting given field/expression to char
* For plugins that override secondary navigation, the namespace for the custom secondary navigation class has
changed. It was (for example) mod_mymodule\local\views\secondary but is now
mod_mymodule\navigation\views\secondary. The old location will continue to work, but is deprecated.