Radek Chalupa   konzultace a školení programování, vývoj software na zakázku

Databáze SQLite v C++ - kódování textů

7.12.2019

Pro správné zobrazení specifických národních znaků (které nejsou součástí základní 1-bytové ANSI znakové sady) máme v současné době v zásadě 2 možnosti: UTF-8 a UTF-16. V Linuxových distribucích se standardně používá UTF-8, zatímco ve Windows UTF-16, tj. "široké znaky", v C/C++ ukládané do 2-bytového typu wchar_t.

Prvním krokem je volba kódování, ve které budou texty interně uloženy v databázi. Pro ty, kteří se nyní obávají že budou postaveni před nutnost nezvratného osudového rozhodnutí je zde dobrá zpráva: SQLite nabízí při načítání dat jednoduchý způsob volby znakové sady, ve které nám budou data naservírována, a to bez ohledu na to v jakém kódování jsou interně uložena. Případná nutná konverze z jedné znakové sady do druhé je provedena interně v kódu SQLite a časová náročnost této konverze není nijak zásadní.

Nejjednodušším způsobem jak bez dalšího určit interní ukládání textů, je volba funkce kterou vytvoříme databázový soubor. V předchozích částech této série jsme použili funkci sqlite3_open, která nastaví jako výchozí kódování UTF-8. Kromě této však existují další 2 funkce pro vytvoření/otevření databáze. Tou první je rozšířená varianta sqlite3_open_v2, která má oproti sqlite3_open další upřesňující parametry, ale jinak také nastaví UTF-8 a také parametr cesty k souboru je pointr na pole 1-bytových char. Pokud chceme nastavit kódování na UTF-16, máme k disposici funkci sqlite3_open16, která kromě nastavení interního kódování na UTF-16 má parametr pro cestu k souboru typu const void* a očekává že na vstupu bude cesta zadána jako pole "širokých znaků", tedy wchar_t*.

Kódování však můžeme také nastavit bez ohledu na to kterou ze zmíněných funkcí použijeme. Pokud tedy například v Linuxu použijeme (z důvodu zadání cesty jako UTF-8) funkci sqlite3_open a chceme přesto ukládat v UTF-16, požijeme následující příkaz PRAGMA:

sqlite3_exec(_sqlite3, "PRAGMA encoding = 'UTF-16'", nullptr, nullptr, nullptr);

kde _sqlite3 je platný pointr na předtím vytvořenou databázi. Ale POZOR! Uvedený příkaz musíme spustit před vytvářením tabulek v databázi.

Dalším krokem je získání textových dat v požadovaném kódování. V předchozích částech jsme si ukázali v rámci "prepared statement" použití funkce sqlite3_column_text

const unsigned char* sqlite3_column_text(sqlite3_stmt*, int iCol);

která vrátí text jako pole znaků char v kódování UTF-8. Pokud jsme ve Windows, budeme nejspíše chtít získat texty v UTF-16. K tomuto účelu použijeme funkci sqlite3_column_text16.

const void* sqlite3_column_text16(sqlite3_stmt*, int iCol);

Tato funkce v případě potřeby provede interně konverzi z UTF-8 na UTF-16 a vrátí text v kódování UTF-16, přičemž můžeme provést přetypování z návratového typu const void* na wchar_t*.