Commit fe2eecac authored by catch's avatar catch

Issue #2475187 by amateescu: Add a user-space implementation for LIKE BINARY in SQLite

parent 6e8eb8ee
...@@ -112,6 +112,12 @@ public static function open(array &$connection_options = array()) { ...@@ -112,6 +112,12 @@ public static function open(array &$connection_options = array()) {
$pdo->sqliteCreateFunction('rand', array(__CLASS__, 'sqlFunctionRand')); $pdo->sqliteCreateFunction('rand', array(__CLASS__, 'sqlFunctionRand'));
$pdo->sqliteCreateFunction('regexp', array(__CLASS__, 'sqlFunctionRegexp')); $pdo->sqliteCreateFunction('regexp', array(__CLASS__, 'sqlFunctionRegexp'));
// SQLite does not support the LIKE BINARY operator, so we overload the
// non-standard GLOB operator for case-sensitive matching. Another option
// would have been to override another non-standard operator, MATCH, but
// that does not support the NOT keyword prefix.
$pdo->sqliteCreateFunction('glob', array(__CLASS__, 'sqlFunctionLikeBinary'));
// Create a user-space case-insensitive collation with UTF-8 support. // Create a user-space case-insensitive collation with UTF-8 support.
$pdo->sqliteCreateCollation('NOCASE_UTF8', array('Drupal\Component\Utility\Unicode', 'strcasecmp')); $pdo->sqliteCreateCollation('NOCASE_UTF8', array('Drupal\Component\Utility\Unicode', 'strcasecmp'));
...@@ -256,6 +262,24 @@ public static function sqlFunctionRegexp($pattern, $subject) { ...@@ -256,6 +262,24 @@ public static function sqlFunctionRegexp($pattern, $subject) {
return preg_match($pattern, $subject); return preg_match($pattern, $subject);
} }
/**
* SQLite compatibility implementation for the LIKE BINARY SQL operator.
*
* SQLite supports case-sensitive LIKE operations through the
* 'case_sensitive_like' PRAGMA statement, but only for ASCII characters, so
* we have to provide our own implementation with UTF-8 support.
*
* @see https://sqlite.org/pragma.html#pragma_case_sensitive_like
* @see https://sqlite.org/lang_expr.html#like
*/
public static function sqlFunctionLikeBinary($pattern, $subject) {
// Replace the SQL LIKE wildcard meta-characters with the equivalent regular
// expression meta-characters and escape the delimiter that will be used for
// matching.
$pattern = str_replace(array('%', '_'), array('.*?', '.'), preg_quote($pattern, '/'));
return preg_match('/^' . $pattern . '$/', $subject);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
...@@ -325,6 +349,8 @@ public function mapConditionOperator($operator) { ...@@ -325,6 +349,8 @@ public function mapConditionOperator($operator) {
static $specials = array( static $specials = array(
'LIKE' => array('postfix' => " ESCAPE '\\'"), 'LIKE' => array('postfix' => " ESCAPE '\\'"),
'NOT LIKE' => array('postfix' => " ESCAPE '\\'"), 'NOT LIKE' => array('postfix' => " ESCAPE '\\'"),
'LIKE BINARY' => array('postfix' => " ESCAPE '\\'", 'operator' => 'GLOB'),
'NOT LIKE BINARY' => array('postfix' => " ESCAPE '\\'", 'operator' => 'NOT GLOB'),
); );
return isset($specials[$operator]) ? $specials[$operator] : NULL; return isset($specials[$operator]) ? $specials[$operator] : NULL;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment