Некорректная политика UTF
1. Входной мусор, выходной мусор
Что касается некорректного UTF, SQLite придерживается политики «мусор на вход, мусор на выход» (GIGO). Если вы вставите некорректный UTF в базу данных SQLite, а затем попытаетесь запросить эти данные, то полученные данные могут не совпадать с введёнными. Если вы ввели мусор, то не жалуйтесь, если получите другой мусор на выходе.
В рамках данного обсуждения «некорректный UTF» может означать следующие ситуации:
Некорректные пары суррогатов в UTF-16.
Некорректные многобайтовые последовательности в UTF-8.
Использование большего количества байтов UTF-8, чем необходимо для представления одного кодового пункта. (Пример: кодирование 'A' в виде двухбайтовой последовательности 0xc1, 0x01 вместо одного байта 0x41.)
Символы NUL (U+0000), вставленные в строки.
Некорректные последовательности комбинирующих символов.
Последовательности байтов UTF-8 или UTF-16, которые кодируют числа, не являющиеся определёнными символами Unicode.
1.1. Некорректный UTF никогда не вызовет ошибки памяти
Если вы вставите некорректный UTF в базу данных SQLite, то SQLite не гарантирует, какой текст вы получите на выходе. Однако гарантируется, что некорректный UTF никогда не вызовет ошибок памяти (переполнение массивов, чтение или запись в неинициализированную память и т. д.), по крайней мере, для встроенной обработки SQLite. Другими словами, некорректный UTF не приведёт к сбою SQLite.
Это обещание относится только к основным компонентам SQLite, а не к предоставляемым приложением расширениям, конечно. Если приложение добавляет новые определяемые приложением SQL-функции, виртуальные таблицы, правила сортировки или другие расширения, а база данных содержит некорректный UTF, то некорректный UTF может передаваться в эти расширения. Если некорректный UTF вызывает сбой одного из этих расширений, то это проблема расширения, а не SQLite.
2. Отсутствие проверки правил форматирования текста
SQLite не пытается проверять правила форматирования UTF. Вы можете вставить некорректный UTF в поле TEXT, и SQLite не будет жаловаться. Оно сохранит некорректный текст, как сможет. SQLite рассматривает себя как движок хранения данных, а не как движок проверки форматов текста.
3. Максимальные усилия по сохранению текста
SQLite не гарантирует всегда сохранение некорректного UTF, но прилагает к этому усилия. В общем случае, если вы вставите некорректный UTF в SQLite, вы получите точно такую же последовательность байтов на выходе, если вы не попросите SQLite преобразовать текст каким-либо образом.
Например, если вы вставите UTF-16LE с некорректными суррогатами в столбец TEXT таблицы базы данных с PRAGMA encoding=UTF16LE, а затем запросите этот столбец с помощью sqlite3_column_text16(), вы, вероятно, получите тот же самый некорректный UTF-16. Но если вы вставите то же самое некорректное UTF-16LE в базу данных с PRAGMA encoding=UTF8, содержимое должно быть преобразовано в UTF8 при хранении, что может привести к необратимым изменениям содержимого. Или если вы вставите то же самое некорректное UTF-16LE в базу данных с PRAGMA encoding=UTF16LE, а затем прочитаете его с помощью sqlite3_column_text(), то во время считывания должно произойти преобразование UTF16 в UTF8, и это преобразование может привести к необратимым изменениям.
Или, предположим, вы работаете с UTF-8 (самый распространённый случай). Некорректный UTF-8, как правило, проходит через базу данных без изменений в своей последовательности байтов. Однако если вы попытаетесь преобразовать некорректный UTF-8 с помощью SQL-функции, такой как substr() или replace(), или если вы попытаетесь выполнить сопоставление строк с оператором LIKE, то вы можете получить неожиданные результаты.
Иными словами, SQLite не пытается активно исказить ваш некорректный текст. Но когда вы просите SQLite выполнить преобразования с некорректным UTF, нет гарантии, что эти преобразования будут обратимыми или даже осмысленными.
4. Некорректный UTF в схеме базы данных
Если схема базы данных содержит имена (имена таблиц, столбцов, индексов и т. д.), которые являются некорректным UTF, SQLite продолжит работать нормально. Для SQLite эти имена — просто последовательности байтов. SQLite не интересует, являются ли они корректным UTF или нет.
При генерации сообщений об ошибках (например, с помощью sqlite3_errmsg()) иногда SQLite встраивает части схемы базы данных в сообщение об ошибке. Если эти встроенные элементы схемы являются некорректным UTF, то и полученное сообщение об ошибке может быть некорректным UTF. Аналогично, вывод из PRAGMA integrity_check и подобных операторов иногда включает имена элементов схемы. Если эти имена элементов схемы некорректны, то вывод команды также будет некорректным UTF.
Последнее изменение этой страницы: 2023-12-05 14:43:20 UTC
SQLite is in the Public Domain.
https://sqlite.org/invalidutf.html