Case insensitive utf8 select

后端 未结 3 829
无人及你
无人及你 2021-01-13 15:15

In SQLite I want to case-insensitive \"SELECT LIKE name\" works fine for normal latin names, but when the name is in UTF-8 with non-latin characters then the se

3条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-01-13 15:46

    An improved version of LIKE overloading via a UDF:

    $db->sqliteCreateFunction('like',
        function ($pattern, $data, $escape = null) use ($db)
        {
            static $modifiers = null;
    
            if (isset($modifiers) !== true)
            {
                $modifiers = ((strncmp($db->query('PRAGMA case_sensitive_like;')->fetchColumn(), '1', 1) === 0) ? '' : 'i') . 'suS';
            }
    
            if (isset($data) === true)
            {
                if (strpbrk($pattern = preg_quote($pattern, '~'), '%_') !== false)
                {
                    $regex = array
                    (
                        '~%+~S' => '.*',
                        '~_~S' => '.',
                    );
    
                    if (strlen($escape = preg_quote($escape, '~')) > 0)
                    {
                        $regex = array
                        (
                            '~(? '.*',
                            '~(? '.',
                            '~(?:' . preg_quote($escape, '~') . ')([%_])~S' => '$1',
                        );
                    }
    
                    $pattern = preg_replace(array_keys($regex), $regex, $pattern);
                }
    
                return (preg_match(sprintf('~^%s$~%s', $pattern, $modifiers), $data) > 0);
            }
    
            return false;
        }
    );
    

    Respects the case_sensitive_like PRAGMA and correctly handles x LIKE y ESCAPE z syntax.

    I also wrote another version that does basic and extended romanization of x and y values, so that an accented character will match it's unaccented counterpart, for instance: SELECT 'Á' LIKE 'à%';.

    You can star the gist to keep an eye on occasional updates.

提交回复
热议问题