From 109fbd5a15465676fc3ac418ca1ba90dd76153ec Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Thu, 12 Oct 2017 11:17:26 +0800 Subject: [PATCH] MDL-46269 dml: Add casesensitive argument to sql_regex() --- lib/dml/moodle_database.php | 4 ++- lib/dml/mysqli_native_moodle_database.php | 19 ++++++++++-- lib/dml/pgsql_native_moodle_database.php | 8 ++++-- lib/dml/tests/dml_test.php | 35 ++++++++++++++--------- 4 files changed, 48 insertions(+), 18 deletions(-) diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php index 874182345be..1b72c00955c 100644 --- a/lib/dml/moodle_database.php +++ b/lib/dml/moodle_database.php @@ -2341,10 +2341,12 @@ abstract class moodle_database { /** * Returns the driver specific syntax (SQL part) for matching regex positively or negatively (inverted matching). * Eg: 'REGEXP':'NOT REGEXP' or '~*' : '!~*' + * * @param bool $positivematch + * @param bool $casesensitive * @return string or empty if not supported */ - public function sql_regex($positivematch=true) { + public function sql_regex($positivematch = true, $casesensitive = false) { return ''; } diff --git a/lib/dml/mysqli_native_moodle_database.php b/lib/dml/mysqli_native_moodle_database.php index 1934699c1f3..2232e2c09c2 100644 --- a/lib/dml/mysqli_native_moodle_database.php +++ b/lib/dml/mysqli_native_moodle_database.php @@ -1738,10 +1738,25 @@ class mysqli_native_moodle_database extends moodle_database { /** * Return regex positive or negative match sql * @param bool $positivematch + * @param bool $casesensitive * @return string or empty if not supported */ - public function sql_regex($positivematch=true) { - return $positivematch ? 'REGEXP' : 'NOT REGEXP'; + public function sql_regex($positivematch = true, $casesensitive = false) { + $collation = ''; + if ($casesensitive) { + if (substr($this->get_dbcollation(), -4) !== '_bin') { + $collationinfo = explode('_', $this->get_dbcollation()); + $collation = 'COLLATE ' . $collationinfo[0] . '_bin '; + } + } else { + if ($this->get_dbcollation() == 'utf8_bin') { + $collation = 'COLLATE utf8_unicode_ci '; + } else if ($this->get_dbcollation() == 'utf8mb4_bin') { + $collation = 'COLLATE utf8mb4_unicode_ci '; + } + } + + return $collation . ($positivematch ? 'REGEXP' : 'NOT REGEXP'); } /** diff --git a/lib/dml/pgsql_native_moodle_database.php b/lib/dml/pgsql_native_moodle_database.php index aaac5c87ef8..44d298c03a6 100644 --- a/lib/dml/pgsql_native_moodle_database.php +++ b/lib/dml/pgsql_native_moodle_database.php @@ -1260,8 +1260,12 @@ class pgsql_native_moodle_database extends moodle_database { return true; } - public function sql_regex($positivematch=true) { - return $positivematch ? '~*' : '!~*'; + public function sql_regex($positivematch = true, $casesensitive = false) { + if ($casesensitive) { + return $positivematch ? '~' : '!~'; + } else { + return $positivematch ? '~*' : '!~*'; + } } /** diff --git a/lib/dml/tests/dml_test.php b/lib/dml/tests/dml_test.php index 87865851c35..866625da722 100644 --- a/lib/dml/tests/dml_test.php +++ b/lib/dml/tests/dml_test.php @@ -4347,6 +4347,9 @@ class core_dml_testcase extends database_driver_testcase { public function test_sql_regex() { $DB = $this->tdb; $dbman = $DB->get_manager(); + if (!$DB->sql_regex_supported()) { + $this->markTestSkipped($DB->get_name().' does not support regular expressions'); + } $table = $this->get_test_table(); $tablename = $table->getName(); @@ -4356,27 +4359,33 @@ class core_dml_testcase extends database_driver_testcase { $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); $dbman->create_table($table); - $DB->insert_record($tablename, array('name'=>'lalala')); + $DB->insert_record($tablename, array('name'=>'LALALA')); $DB->insert_record($tablename, array('name'=>'holaaa')); $DB->insert_record($tablename, array('name'=>'aouch')); + // Regex /a$/i (case-insensitive). $sql = "SELECT * FROM {{$tablename}} WHERE name ".$DB->sql_regex()." ?"; $params = array('a$'); - if ($DB->sql_regex_supported()) { - $records = $DB->get_records_sql($sql, $params); - $this->assertCount(2, $records); - } else { - $this->assertTrue(true, 'Regexp operations not supported. Test skipped'); - } + $records = $DB->get_records_sql($sql, $params); + $this->assertCount(2, $records); + // Regex ! (not) /.a/i (case insensitive). $sql = "SELECT * FROM {{$tablename}} WHERE name ".$DB->sql_regex(false)." ?"; $params = array('.a'); - if ($DB->sql_regex_supported()) { - $records = $DB->get_records_sql($sql, $params); - $this->assertCount(1, $records); - } else { - $this->assertTrue(true, 'Regexp operations not supported. Test skipped'); - } + $records = $DB->get_records_sql($sql, $params); + $this->assertCount(1, $records); + + // Regex /a$/ (case-sensitive). + $sql = "SELECT * FROM {{$tablename}} WHERE name ".$DB->sql_regex(true, true)." ?"; + $params = array('a$'); + $records = $DB->get_records_sql($sql, $params); + $this->assertCount(1, $records); + + // Regex ! (not) /.a/ (case sensitive). + $sql = "SELECT * FROM {{$tablename}} WHERE name ".$DB->sql_regex(false, true)." ?"; + $params = array('.a'); + $records = $DB->get_records_sql($sql, $params); + $this->assertCount(2, $records); }