Python / PHP SQLite запрашивает польскую букву Ł / ł в FTS4 / FTS5

Поскольку SQLite FTS4 / FTS5 tokenizer = unicode61 дает нам:

a=A=ą=Ą=ä=Ä ...
z=ż=ź=Z=Ż=Ź=Ž=ž ...
etc...

Почему не l = ł = L = Ł ??? Разве это не ошибка?

Как запросить SQLite на клавиатуре, не имеющей польских символов ł / Ł? Например, запрос имени Żabczyński как «zabczynski» - получил результат, а для имени Włast как «wlast» - 0 результатов (должно быть как сотни ...) У меня есть обход в PHP, но он не работает со словами с l и ł, например opłacalny.

<?
$q = $_POST["q"];
//
$pat = '/(\b\w*[lł]\w*\b)/iu';
    $q = preg_replace_callback($pat,function($macz){
        return "(" . str_replace("ł","l",$macz[1]) . "* OR " . str_replace("l","ł",$macz[1]) . "*)";
    },$q);
// so query 'andrzej wlast' looks 'andrzej (wlast* OR włast*)'
...
    $sql = "SELECT ...";
    $pdo = $db->prepare($sql);
    //
    $pdo->execute([":q" => "$q*"]);
    //
    $odp = $pdo->fetchAll(PDO::FETCH_ASSOC);
?>

Есть идеи? Вы не можете установить кодировку в sqlite, например utf8_general_ci, utf8_polish_ci, utf8_unicode_ci ... Или да, это возможно?

Есть ли способ решить эту проблему на Python? На платформе нет ICU (общий сервер).

🤔 А знаете ли вы, что...
PHP является интерпретируемым языком программирования.


1
216
2

Ответы:

К сожалению, нет, в SQLite нет таблиц сопоставления, таких как MySQL, потому что он раздувает то, что должно быть очень маленькой и переносимой библиотекой.

Вы можете преобразовать свои запросы во что-то вроде этого:

SELECT * FROM foo WHERE word REGEXP '^[ZŻ]abczy[nń]ski$';
SELECT * FROM foo WHERE word REGEXP '^W[lł]ast$';

В Python это довольно просто:

def collatify(string, equivalents):
    for original, replacement in equivalents.items():
        string = string.replace(original, '[%s%s]' % (original, replacement))
    return string

collatify('Żabczyński', { "Ż": "Z", "ń": "n" })

Опять же, к сожалению, это сделает невозможным использование индексов для поиска по этим полям.

Лучше выполнить противоположную операцию, «усилить» ваши строки и ввести их в базу данных в качестве дополнительного столбца (с собственным индексом!); затем «усильте» свой запрос и посмотрите, как он работает. Еще лучше, посмотрите, совпадает ли ваш "asciified" запрос с исходным; если это так, используйте столбец «asciified» (поскольку пользователь ввел только символы ASCII); если они различаются, то пользователь ввел символы, специфичные для польского, и предположительно введет их все правильно, поэтому используйте исходный столбец. Таким образом, если пользователь вводит «abczyński», вы ищите «abczyński» в исходном столбце и находите его там. Если пользователь вводит "Zabczynski", предположите, что он может быть асцифицированным, и выполните поиск в столбце asciified; если бы они были там, он нашел бы «Лабчинский», «Забчинский», «Лабчинский» и «Забчинский». Если пользователь вводит «Zabczyński» или «abczynski», вероятно, он должен знать польский язык, поэтому ищите в исходном столбце и не возвращайте результатов. Вся эта победа достигается за счет сохранения только одной дополнительной копии вашей колонки.


Перейдите на MySQL или Postgres. У SQLite есть свои ограничения.