sqlite3_errmsg()
について
関数sqlite3_errmsg()
はデータベースハンドラsalite3*
を引数にとり、そのデータベースハンドラで直前に発生したエラーに関するメッセージを返す。
例えば、存在しないファイルに対して読み込み専用オプションをつけてsqlite3_open_v2()
を呼び出すと、以下のようにエラーが発生する。
const char *not_exist_file = "notexist.sqlite";
sqlite3 *db = NULL;
int rc = sqlite3_open_v2(not_exist_file, &db, SQLITE_OPEN_READONLY, NULL);
if (rc != SQLITE_OK)
{
printf("[%s]\n", sqlite3_errmsg(db)); // [unable to open database file]
}
sqlite3_close(db);
エラーが発生していない場合は、以下の例のように、"not an error"
を返す。
sqlite3 *db = NULL;
int rc = sqlite3_open("filePath.sqlite", &db);
if (rc == SQLITE_OK)
{
printf("[%s]\n", sqlite3_errmsg(db)); // [not an error]
}
sqlite3_close(db);
sqlite3_errmsg()
にNULL
を渡してみる
公式リファレンスによると、関数sqlite3_open()
およびsqlite3_open_v2()
は、DB接続のオープンに失敗した場合も、引数として渡されたデータベースハンドラに非NULL
の値を書き込む。ただし、メモリ領域の確保に失敗した場合は、データベースハンドラにNULL
が書き込まれる。
そこで、メモリ領域確保に失敗したことを想定して、sqlite3_errmsg()
にNULL
を渡してみる。
int main(int argc, char **argv)
{
printf("[%s]\n", sqlite3_errmsg(NULL)); // [out of memory]
}
"out of memory"
という文字列が返された。
上記のコードでは、実際にはメモリ領域の確保を試行していない。sqlite3_errmsg()
にNULL
が渡される状況とは、メモリ領域の確保に失敗した、すなわちメモリ枯渇状況である、と判断してこのメッセージを返す仕様としているのだろう。
以上を踏まえて
以上の実験から、sqlite3_open()
またはsqlite3_open_v2()
が返す値がSQLITE_OK
でなかった場合のエラーメッセージ取得は、データベースハンドラがNULL
か非NULL
かにかかわらず、以下のように記述すれば良いことになる。
sqlite3 *db = NULL;
const char *errMsg;
int rc = sqlite3_open("filePath.sqlite", &db); /* もしくはsqlite3_open_v2関数の呼び出し */
if (rc != SQLITE_OK)
{
errMsg = sqlite3_errmsg(db);
// errMsgをログや標準エラーなどに出力
// その他、必要なエラーハンドリング
}
sqlite3_close(db);
まとめ
-
sqlite3_open()
およびsqlite3_open_v2()
はエラー発生時に以下の挙動をする。- メモリ領域確保エラーの場合:引数として渡したデータベースハンドラに
NULL
を書き込む - それ以外のエラーの場合:引数として渡したデータベースハンドラに非
NULL
値を書き込む。
- メモリ領域確保エラーの場合:引数として渡したデータベースハンドラに
-
sqlite3_errmsg()
にはNULL
を渡しても安全なので、エラー発生時には引数のNULL
チェックを行わずにsqlite3_errmsg()
にデータベースハンドラを渡して良い。
参考
- 公式リファレンス
-
Opening A New Database Connection:
sqlite3_open()
,sqlite3_open_v2()
について。 -
Error Codes And Messages:
sqlite3_errmsg()
について。
-
Opening A New Database Connection: