PythonからMySQLdbやpg(PostgreSQL)やsqliteを使う場合、それぞれモジュールがあってそれを通して使うことになっているが、これらはだいたいPython Database API Specification(python.org)に準拠している(日本語訳はこちら(python.jp))ことになっている。
そしてこのAPI仕様では、DBのcursorへのexecuteメソッドでSQLを投げることになっている。私はこのexecuteメソッドに入れる文字列を作る際にescapeしなければ、いわゆる「SQLインジェクションなんとか」が起きるものと理解していた。MySQLdbにはescape_stringが定義されているのはそのためだと。
しかし、違うのですよ。sqliteモジュールにescape_stringメソッドがないので困るなぁと思ってみたけど、実際はexecuteメソッドの第1引き数がフォーマットになっていて、こいつの%s変換で勝手にescapeしてくれるのです(厳密にはparamstyleを設定するとこれ以外の書き方もできる)。例えば、
import sqlite db=sqlite.connect("somedb", encoding="UTF-8") c=db.cursor() c.execute("SELECT * FROM yourtbl WHERE name=%s", ("ほげtest'in,teststr表"))
みたいな。というわけで、MySQLdbでいちいちescape_stringを通してから”format”%(args)の(Pythonの標準のフォーマット文字列変換)を使っていた私の作業は非常に無駄だったということになります。参考までに、これまではこんなカッコ悪い書き方をしていた。
import MySQLdb db=MySQLdb.connect(db="somedb", user='name', passwd='pass') c=db.cursor() c.execute("SELECT * FROM yourtbl WHERE name='%s'" %(MySQLdb.escape_string("ほげtest'in,teststr表")))
ちなみにこのsqlite(sqlite.org)は非常に便利ですね。Berkley DB(sleepycat.com)系のもの並みのzero-configurationでけっこうちゃんとSQLが使えて。DBが1ファイルなので持ち運びも楽だし、コマンドも1つ。dump(mysqldumpみたいなの)はこんな感じで、そのまま食わせればいい。
# sqlite somedb .dump > dumpfile # sqlite somedb2 < dumpfile
うーむ。これからはMySQL使うよりもsqlite使ってたほうがカッコいいかもな。