Posts Tagged ‘SQLite3’

SQLite3 strftime関数とsyslog出力の組み合わせで、gccの最適化どハマリ

6月 8th, 2010 by KUMA | コメントは受け付けていません。 | Filed in 技術メモ

これと似たような問題だったのだが、strftimeを使用したSQLをデバッグのためSYSLOGで出力したところ、gccの-O0では何も問題なく出力されるのだが、-O1以上の最適化をかけるとセグメンテーション違反で落ちた。

環境は以下。

  • gcc 4.3.2
  • SQLite 3.5.9
  • rsyslogd 3.18.6

以下のようなコードで発生。


char *sql = sqlite3_mprintf("SELECT strftime(\'%%s\', \'now\');");

syslog(LOG_DEBUG, sql);

sqlite3_free(sql);

どうやら原因はsyslog関数の中でvfprintfを行っており、エスケープした%sを再評価して存在しない可変引数を参照して落ちてるらしい。

最適化させないと、うまいことメモリ空間かレジスタを初期化して変なところに飛ばないようにしてくれてるんだと思われ。詳細は追わず。

仕方が無いので、エスケープしなおすのも面倒だから、strftimeを使用したSQLはデバッグ出力しないようにした。

Tags: , , ,

SQLite3.5.9 sqlite3_mprintfのバグ?

4月 30th, 2010 by KUMA | コメントは受け付けていません。 | Filed in 技術メモ

Debian LennyのパッケージとなっているSQLite 3.5.9でstrftime関数とsqlite3_mprintfの組み合わせでどうもバグを踏んだっぽい。

↓な感じのコードを書いたら、再現。


char str[] = "SELECT strftime('%%Y-%%m-%%d 00:00:00', '%u', 'unixepoch', 'localtime');"
char *sql = sqlite3_mprintf(str, 1272628349);

そしたらこんなふうにsqlには文字列が展開されてた。

select strftime('%Y-No such file or directory--1076202408 00:00:00', '1272628349', 'unixepoch', 'localtime');

どうも%%のエスケープがうまく解釈出来ないようなので、strftimeを使用しない方法で回避した。

最新のSQLiteで治っているかは未確認。時間があったら調べる。

Tags: , ,

SQLite3でPreparedStatementを使用する

4月 19th, 2010 by KUMA | コメントは受け付けていません。 | Filed in 技術メモ

SQLite3で大量(といっても数百件だが、組み込みでCPUが貧弱かつトランザクションが必要なため出来る限り処理を早くする必要がある)にSelect/Insert文を発行する可能性があるパターンが出てきてしまったので、高速化のためPreparedStatementを使うことにした。

ここを参考にさせて貰いつつ、本家のドキュメントを読むと↓のような手順になるようだ。
原文と一緒に意訳も載せたが、意訳意味ないな…

  1. Create the object using sqlite3_prepare_v2() or a related function.
    sqlite3_prepare_v2を使ってsqlite3_stmtハンドルを作成する。
  2. Bind values to host parameters using the sqlite3_bind_*() interfaces.
    sqlite3_bind_*を使ってSQL内の「?」「?n」「:v」「@v」「$v」を実際に値に割り当てる。nは任意の数値、vは任意のラベル名
  3. Run the SQL by calling sqlite3_step() one or more times.
    sqlite3_stepを使ってSQLを実行する。Selectなどの場合は複数回回して一行づつレコードをもらう。
  4. Reset the statement using sqlite3_reset() then go back to step 2. Do this zero or more times.
    sqlite3_resetでstatementをリセットし、2から繰り返すことで、Bindingを変更してSQLを実行できる。
  5. Destroy the object using sqlite3_finalize().
    一通り終わったら sqlite3_finalizeを使って、1で作ったsqlite3_stmtハンドルを開放する。

sqlite3_stmtはsqlite3_freeで開放しないってところが注意点かな。

ここによると、

sqlite3_prepareとsqlite3_stepを使ってINSERT処理を最適化すると、最適化しない場合より2.2~2.3倍速くなる。

とのことなので、十分効果は見込める予想。

Tags: , ,

SQLite3の日時操作

3月 19th, 2010 by KUMA | コメントは受け付けていません。 | Filed in 技術メモ

毎回必要になる度にググってるのでメモっておく。

SQLite3のdatetime()は相対時間など、いろいろオプションを付けられる。

SELECT datetime(‘now’, ‘localtime’, ‘-1 days’);

↑のような指定をすると、昨日の現在と同じ時間がローカルタイムで返ってくる。

パラメータは矛盾しなければ複数指定が可能。

詳しくはこのページを参照。

消えると怖いので英語の原典もリンクしておく。

Tags: ,