Я не могу найти ничего, связанного с использованием COLLATE в DQL-запросе с Doctrine (и, конечно, это не работает).
Моя конкретная проблема:
У меня есть таблица с utf8_general_ci
charset. У меня есть одно конкретное поле, в котором есть акцентированные символы (например, «á», «ű», «ő» и т. Д.),
Основное сравнение с utf8_general_ci
не может определить разницу между регулярными символами и их акцентированными парами (a = á, u = ű, o = ő), что отлично подходит для большинства запросов, которые попадают на эту таблицу ! Поэтому, если я скажу:
col1 | col2 ------|------- 1 | árvíz ------|------- 2 | arviz
Этот запрос вернет оба результата:
SELECT * FROM `table` WHERE `col2` = 'arviz'
Опять же, это отлично для меня для большинства случаев использования!
Но есть одна конкретная функциональность, где мне нужно определить разницу, и в обычной MySQL я мог бы использовать:
SELECT * FROM `table` WHERE `col2` COLLATE utf8_bin = 'arviz'
Это возвращает только безударную версию.
Вопрос в том, может ли что-то подобное сделать, используя либо createQuery (запись dql) Doctrine, либо построитель запросов?
Я думаю, что прочитал всю соответствующую документацию, но не могу найти способ сделать это. Возможно ли как-то?
Следуя предложению Cerad написать пользовательскую функцию DQL: http://www.doctrine-project.org/2010/03/29/doctrine2-custom-dql-udfs.html
Мне удалось создать это:
namespace MyCompany\MyBundle\DQL; use Doctrine\ORM\Query\AST\Functions\FunctionNode; use Doctrine\ORM\Query\Lexer; class CollateFunction extends FunctionNode { public $expressionToCollate = null; public $collation = null; public function parse(\Doctrine\ORM\Query\Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->expressionToCollate = $parser->StringPrimary(); $parser->match(Lexer::T_COMMA); $parser->match(Lexer::T_IDENTIFIER); $lexer = $parser->getLexer(); $this->collation = $lexer->token['value']; $parser->match(Lexer::T_CLOSE_PARENTHESIS); } public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) { return sprintf( '%s COLLATE %s', $this->expressionToCollate->dispatch($sqlWalker), $this->collation ); } }
Когда он зарегистрирован в config.yml ( http://symfony.com/doc/current/cookbook/doctrine/custom_dql_functions.html ), он будет искать функцию «Собрать» с двумя аргументами: поле и кодировку (без действительной кодировки обнаружение еще).
Работает как (написано на DQL)
COLLATE( field , collation )
И создает (в runable MySQL)
`field` COLLATE collation
Сортировка Ofcourse должна быть допустимой кодировкой (например, utf8_bin
), или вы получите ошибку MySQL.
Я предполагаю, что есть более простое решение, но я могу только создать это как «функцию». По крайней мере проблема решена.