/ 最近 .rdf 追記 編集 設定 本棚

脳log[20060214] SQLite: logic error or missing database. (解決) | [コミック] むんこ【らいか・デイズ 1 (1) (まんがタイムコミックス)】 芳文社



2006年02月14日 (火)

SQLite: logic error or missing database. (解決)

Apacheサービスを HTTPDアカウント(Usersグループ)で走らせるようになってから、sqlite3.dllを使う、Rubyで書かれた CGIスクリプトが「logic error or missiing database」を出すようになった。

エラーを直接投げてるのは Rubyのライブラリの sqlite3-rubyだけど、エラーメッセージは SQLiteのライブラリ(sqlite3.dll)に由来している。

エラーを出す原因となった SQLは以下。

SELECT * FROM sqlite_master WHERE type='table' OR type='view' ORDER BY name;

データベース内のテーブルとビューの一覧を取り出すためのありふれた SQL文。

問題をややこしくしたのは

SELECT * FROM sqlite_master WHERE type='table' ORDER BY name;

だとか

SELECT * FROM sqlite_master WHERE type='view';

でも同じエラーが出るのに

SELECT * FROM sqlite_master WHERE type='table';

だとエラーが出なかったこと。

結論から言うと SQL文は悪くない。

Apacheを SYSTEMアカウントで動かすとエラーが出なくなったので、Apache(と Apacheが CGIとして起動する Ruby)が HTTPDアカウント(Usersグループ)で動いてることに原因があると考えた。それなら書き込み権限がないせいでエラーになってるのかもしれない。

データベースファイルやデータベースファイルを入れるディレクトリには当然 HTTPDに対して書き込み権限を付けてある。

SysInternalsの FileMonを使って確認したところ、ruby.exeが C:\WINDOWS\sqlite_XXXXXX(文字化け) を CREATEしようとして Denyされている。

sqlite-3.3.4の os_win.cに

char *sqlite3WinFullPathname(const char *zRelative)

という関数があり、Cygwinや WINCE以外の WINDOWSプラットフォームではそこから

GetFullPathNameW/A

という APIが呼ばれている。おそらくこの APIが "C:\WINDOWS\sqlite_XXXXXXX" というパスの出所だろう。

ここをいじって

"%TEMP%\sqlite_XXXXXXX"
=> "%USERPROFILE%\Local Settings\Temp\sqlite_XXXXXXX
=> "C:\Documents and Settings\HTTPD\Local Settings\Temp\sqlite_XXXXXXX"

上のような Tempディレクトリにファイルを作成するようにするのもアリだろうが、そういう変更をすると SQLiteのバージョンアップに追従するのが面倒になるので Rubyスクリプトの方で対処する。

sqlite3-rubyでは

db = SQLite3::Database.new('hoge.db');
db.temp_store = 2; # 2=memory, 1=file

SQLでなら

PRAGMA temp_store = MEMORY;

(参照) Pragma statements supported by SQLite

SQLの方は試してないけど、sqlite3-rubyの方で対処したところエラーが出なくなった。

エラーメッセージが的外れなのでここまで来るのに苦労した。

 あっれ〜〜?

PRAGMA temp_store_directory;

PRAGMA temp_store_directory = 'directory-name';

Query or change the setting of the "temp_store_directory" - the directory where files used for storing temporary tables and indices are kept. This setting lasts for the duration of the current connection only and resets to its default value for each new connection opened.

When the temp_store_directory setting is changed, all existing temporary tables, indices, triggers, and viewers are immediately deleted. In practice, temp_store_directory should be set immediately after the database is opened.

The value directory-name should be enclosed in single quotes. To revert the directory to the default, set the directory-name to an empty string, e.g., PRAGMA temp_store_directory = ''. An error is raised if directory-name is not found or is not writable.

The default directory for temporary files depends on the OS. For Unix/Linux/OSX, the default is the is the first writable directory found in the list of: /var/tmp, /usr/tmp, /tmp, and current-directory. For Windows NT, the default directory is determined by Windows, generally C:\Documents and Settings\user-name\Local Settings\Temp\. Temporary files created by SQLite are unlinked immediately after opening, so that the operating system can automatically delete the files when the SQLite process exits. Thus, temporary files are not normally visible through ls or dir commands.

%TEMP%フォルダでなく %WINDIR%にテンポラリファイルを作ろうとするのは Windowsのせい?俺のせいでした。

httpd.confに次の行を加えるべし。

PassEnv TEMP

[][マンガ][コミック] むんこ【らいか・デイズ 1 (1) (まんがタイムコミックス)】 芳文社

確かに、確かに萌えが存在している。ギャップだとか弱点に萌えが宿るのは真実。何かのインタビューで桜庭さんが仰っていた通りです。

http://www5a.biglobe.ne.jp/~dai_/diary/diary0602.htm#05 (DAIさん帝国)