From fe2eecace037ea1abf78b16130e5826832e95c7d Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org> Date: Thu, 21 May 2015 13:05:34 +0100 Subject: [PATCH] Issue #2475187 by amateescu: Add a user-space implementation for LIKE BINARY in SQLite --- .../Database/Driver/sqlite/Connection.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php index 69103bef8964..247d6532a054 100644 --- a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php +++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php @@ -112,6 +112,12 @@ public static function open(array &$connection_options = array()) { $pdo->sqliteCreateFunction('rand', array(__CLASS__, 'sqlFunctionRand')); $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. $pdo->sqliteCreateCollation('NOCASE_UTF8', array('Drupal\Component\Utility\Unicode', 'strcasecmp')); @@ -256,6 +262,24 @@ public static function sqlFunctionRegexp($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} */ @@ -325,6 +349,8 @@ public function mapConditionOperator($operator) { static $specials = array( '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; } -- GitLab