PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » SQLite и сортировка без учета регистра


SQLite и сортировка без учета регистра

Сообщений 1 страница 3 из 3

1

Не работает с кириллицей.
Как победить не меняя регистр первой буквы?

Код:
UseSQLiteDatabase()
If CreateFile(0, "Baza.bd") : CloseFile(0) : EndIf
OpenDatabase(0, "Baza.bd", "", "")

DatabaseUpdate(0, "CREATE TABLE tab (im TEXT)")
DatabaseUpdate(0, "INSERT INTO tab VALUES ('Брюква'),('Банан'),('бамбук'),('Бузина'),('Береза')")

DatabaseQuery(0, "SELECT im FROM tab ORDER BY im COLLATE NOCASE") ;Не работает с кириллицей
While NextDatabaseRow(0)
  Debug GetDatabaseString(0, 0)
Wend
FinishDatabaseQuery(0)

0

2

Известная проблема SQLite https://ru.stackoverflow.com/questions/ … овии-where
https://habr.com/ru/articles/150543/

NOCASE: тоже, что и BINARY, но игнорирует регистр для 26 букв латинского алфавита (и только для них).
А вот функция сравнения строк для collation NOCASE:

Код:
/*
**
** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
** sqlite3_strnicmp() APIs allow applications and extensions to compare
** the contents of two buffers containing UTF-8 strings in a
** case-independent fashion, using the same definition of "case
** independence" that SQLite uses internally when comparing identifiers.
*/

SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
  register unsigned char *a, *b;
  a = (unsigned char *)zLeft;
  b = (unsigned char *)zRight;
  while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
  return UpperToLower[*a] - UpperToLower[*b];
}
SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
  register unsigned char *a, *b;
  a = (unsigned char *)zLeft;
  b = (unsigned char *)zRight;
  while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
  return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
}

// UpperToLower - это таблица, которая переводит символ "в себя" для всех символов кроме 'A'..'Z' (которые переводятся в 'a'..'z')

Что привлекает внимание? Что строка якобы UTF-8 формата, но все символы строки обрабатываются подряд: нет извлечения и перекодировки символов в UTF-32.

Если долго медитировать над этим кодом, то можно понять, что он, как ни странно, корректно работает и на строках UTF-8, и на любой другой одно-символьной кодировке (например, windows-1251). Откровениями в понимании «почему так» можно делится в комментариях :).

Это плавно подводит нас к пониманию важного тезиса, что

SQLite не интересуется реальным форматом строки UTF-8 до момента, когда требуется выполнять перекодировку строки в UTF-16.

Разумеется, упорядочивание реальных UTF-8 строк стандартными collation даст довольно странные результаты. Но равенство будет работать корректно, а сравнение будет транзитивным и не нарушит работу SQLite.

Выходит, действительно, в базе SQLite можно хранить строки в кодировке, скажем, windows-1251 при условии, что вы нигде не используете UTF-16. Это касается и как строковых литералов внутри SQL, так и строк, передаваемых через привязку параметров.

0

3

Спасибо... Как бы не хотелось, буду делать UCase первой буквы при занесении в базу.

Отредактировано Andruk (17.08.2025 17:03:31)

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » SQLite и сортировка без учета регистра