結果の取得とUnicode
クエリ結果の取得
SQL文がSELECTのように複数(0個以上)の結果を返すとき、sqlite3_step()を何度も呼び出すことでその結果が得られます。
sqlite3_step()は結果の個数だけSQLITE_ROW、そして最後にSQLITE_DONEを返します。結果の取得は、
- const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
- double sqlite3_column_double(sqlite3_stmt*, int iCol);
- int sqlite3_column_int(sqlite3_stmt*, int iCol);
- sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
- const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
にステートメント・ハンドルとカラム位置(0起点)を与えることで得られます。
sqlite3_stmt* statement; const char* command = "SELECT * FROM mul_table WHERE x = 5;" sqlite3_prepare_v2(db, command, -1, &statement, 0); while ( sqlite3_step(statement) == SQLITE_ROW ) { int x = sqlite3_column_int(statement,0); int y = sqlite3_column_int(statement,1); int z = sqlite3_column_int(statement,2); cout << x << '*' << y << '=' << z << endl; }
Unicodeの扱い
SQLiteで扱う文字はUTF-8もしくはUTF-16となっており、ここまでの説明はUTF-8のものです。文字コードをUTF-16とする関数にはsqlite3_column_text16()のように末尾に16がつけられています。このとき、文字列を表す型はchar*ではなくvoid* です。wchar_t*ではないことに注意してください(SQLiteはwchar_t型をサポートしない処理系を考慮してvoid*を使っているのでしょう)。
まとめとして、SQLiteの主要APIを使ったUTF-16(Unicode)版サンプルコードを示します。
/* * SQLite のC++によるサンプル(Visual C++) * cl -MD -EHsc -I. trial.cpp sqlite3.lib */ #include <iostream> // wcout, endl #include <string> // wstring #include <locale> // locale #include <sqlite3.h> // SQLite3 struct Record { wchar_t* shop; wchar_t* dish; int price; double score; }; using namespace std; typedef const wchar_t* cwp; int main() { /* * Unicode出力のためのlocale設定 */ wcout.imbue(locale("japanese")); sqlite3* db; int result; /* * データベースのオープン */ sqlite3_open16(L"trial.db", &db); sqlite3_stmt* statement; const void* command; /* * シングル・ステートメント SQL の実行 */ command = L"DROP TABLE IF EXISTS 飯屋"; sqlite3_prepare16_v2(db, command, -1, &statement, 0); sqlite3_step(statement); sqlite3_finalize(statement); command = L"CREATE TABLE 飯屋 ( 店名 TEXT, 品名 TEXT, 価格 INTEGER, 評価 FLOAT);"; sqlite3_prepare16_v2(db, command, -1, &statement, 0); sqlite3_step(statement); sqlite3_finalize(statement); /* * マルチ・ステートメント SQL の実行 */ command = L"INSERT INTO 飯屋 VALUES ( '蓬莱', 'ラーメン', 500, 2.5 );" L"INSERT INTO 飯屋 VALUES ( '崑崙', 'ラーメン', 550, 3.0 )"; while ( *static_cast<cwp>(command) ) { sqlite3_prepare16_v2(db, command, -1, &statement, &command); result = sqlite3_step(statement); sqlite3_finalize(statement); } /* * パラメータのバインド */ Record data[] = { { L"来来軒", L"ラーメン", 600, 3.0 }, { L"来来軒", L"チャーハン", 500, 4.5 }, { L"来来軒", L"ニラレバ", 650, 2.0 }, { L"激旨食堂", L"チャーハン", 500, 4.8 }, { L"激旨食堂", L"ギョーザ", 350, 3.5 }, { 0 } }; command = L"INSERT INTO 飯屋 VALUES ( ?, ?, ?, ? )"; sqlite3_prepare16_v2(db, command, -1, &statement, 0); for ( Record* rec = data; rec->shop; ++rec ) { sqlite3_reset(statement); sqlite3_bind_text16(statement, 1, rec->shop , -1, SQLITE_STATIC); sqlite3_bind_text16(statement, 2, rec->dish , -1, SQLITE_STATIC); sqlite3_bind_int (statement, 3, rec->price); sqlite3_bind_double(statement, 4, rec->score); result = sqlite3_step(statement); } sqlite3_finalize(statement); /* * クエリの実行と値の取得 */ command = L"SELECT * FROM 飯屋 WHERE 評価 >= 3.0"; sqlite3_prepare16_v2(db, command, -1, &statement, 0); while ( sqlite3_step(statement) == SQLITE_ROW ) { wcout << static_cast<cwp>(sqlite3_column_text16(statement,0)) << " | " << static_cast<cwp>(sqlite3_column_text16(statement,1)) << " | " << sqlite3_column_int (statement,2) << " | " << sqlite3_column_double(statement,3) << endl; } /* * データベースのクローズ */ sqlite3_close(db); }
