▼ 2008/02/02(土) Cakephpでsqliteの続き。editとdeleteの修正
(追記)もっと効率的な修正方法があります。CakePHP1.2bとSQLite不具合のもっと簡単な直し方
以前にSQliteでのnew時(insert)の不具合を修正したのだけれど、今度は、editとdeleteでも不具合があることがわかった。しばらくMySQLのお勉強をしていたので、sqliteはほっておいたんだけど、やっぱりsqliteが恋しいので戻ってきた。
こちらでも、同じ認識の方がいるらしい。
CakePHPではまったこと15(sqliteを使っているときのupdate)
この方、いろいろtips書いておられて、頭が下がります。
なお、これらの不具合は、次期バージョンでは修正されるらしいので、つかのまのtips。これを書いている今でも、本家がアップデートしたら、この記事の意味はありません。また scaffoldもどきでの動作は確認していますが、自分でsave文は書いていないのでそこは未テストです。
そして、このeditとdeleteは、cakephpが作るSQL文の最終形をハックする形にしたので、複雑なテーブル構成の場合は、何らかの不具合がでる可能性が大いにあります。なお、テーブル名にピリオドがあるとそれだけでNGです。
環境
まずは、DELETEのSQL文から
本来であれば、SQL文の生成過程を修正するのが王道であり、おそらく本家はそのように対処するのでしょうが、それはとてつもなく大変なので、こんな感じの「応急措置」です。
では、いってみましょうか。
まずは、
そして、このファイルの一番下の「}」直前に、以下を付け加える。
なお、わかる人からみたら、「無謀な修正」なので、自己責任で。私の少ないテストしか経ていないので、他で動作しない可能性もたくさんあります。
本当は preg_replaceをつなげなくて(みっともない)、配列に一気に渡したほうがいいのだと思うけど、試行錯誤でこうなったので、このままにしておきます。
IN句のカッコをとるところなんかはいいかげんで、正直怖いです。何か別にカッコを使っていれば、それを取ってしまうので、そこで新たな不具合を生むおそれアリ。(このスクリプト全般がそうなんだけど)
(追記)
入力データの中に ') や IN(' や "." などがあると消去されます。入れるデータによってはうまくいかないです。(このようなやり方では仕方ない)
繰り返しですが時期バージョンでは修正されるそうなので、そうなったらすぐに本家に従いましょう。
SQLiteファンとしては早く対処して欲しい。しかし無料だから強くもいえんしね。皆さんもドネーションぐらいはしましょう。paypalで20秒でできちゃったよ。
なお、この同じファイルで、SQliteでのnew時(insert)の不具合を修正をやっておかないとinsertできません。
うーむ。ベータ版とはいえ。。。楽じゃないよcakephp。
以前にSQliteでのnew時(insert)の不具合を修正したのだけれど、今度は、editとdeleteでも不具合があることがわかった。しばらくMySQLのお勉強をしていたので、sqliteはほっておいたんだけど、やっぱりsqliteが恋しいので戻ってきた。
こちらでも、同じ認識の方がいるらしい。
CakePHPではまったこと15(sqliteを使っているときのupdate)
この方、いろいろtips書いておられて、頭が下がります。
なお、これらの不具合は、次期バージョンでは修正されるらしいので、つかのまのtips。これを書いている今でも、本家がアップデートしたら、この記事の意味はありません。また scaffoldもどきでの動作は確認していますが、自分でsave文は書いていないのでそこは未テストです。
そして、このeditとdeleteは、cakephpが作るSQL文の最終形をハックする形にしたので、複雑なテーブル構成の場合は、何らかの不具合がでる可能性が大いにあります。なお、テーブル名にピリオドがあるとそれだけでNGです。
環境
cake_1.2.0.6311-beta SQLite2 ←3ではありません。まずは、どこがおかしいのか列挙してみよう。以下は、MySQLでは通っても、SQLiteではNGのものである。
まずは、DELETEのSQL文から
- DELETE TabelName FROM TableName
というあり得ない形になっていた。真ん中のテーブル名が不要
- WHERE FieldName IN('1')
みたいな形になっていた。sqliteでは、deleteでIN句は使用不能。WHEWRE FieldName='1'であることが必要。
- "TableName"."FieldName" as "TabaleAlias"."FieldName"
になっていた。deleteでasは使えないので、as以降を消去。deleteで複数テーブルを一気に消去することはないだろうから、たぶん大丈夫。
本来であれば、SQL文の生成過程を修正するのが王道であり、おそらく本家はそのように対処するのでしょうが、それはとてつもなく大変なので、こんな感じの「応急措置」です。
では、いってみましょうか。
まずは、
- \cake\libs\model\datasources\dbo\dbo_sqlite.phpを
- \app\models\datasources\dbo\dbo_sqlite.phpにこぴーして、以下の修正&追加。
function _execute($sql) {
return sqlite_query($this->connection, $sql);
}
を探しだし、以下のように修正する。
function _execute($sql) {
return sqlite_query($this->connection, $this->spok_escape($sql));
}
そう、SQLの実行直前でエスケープするという、脆弱性を生みかねない危険な方法。そして、このファイルの一番下の「}」直前に、以下を付け加える。
なお、わかる人からみたら、「無謀な修正」なので、自己責任で。私の少ないテストしか経ていないので、他で動作しない可能性もたくさんあります。
function spok_escape($sql){
#UPDATE修正
if( substr($sql,0,6)==='UPDATE' ) {
#テーブルasの除去
$sql=preg_replace("/\sAS\s\"[^\"]+\"/",' ',$sql);
#テーブル名の除去
$sql=preg_replace("/\s\"[^\"]+\"\./",' ',$sql);
#INを=に
$sql=preg_replace("/\sIN\s*\('/"," ='",$sql);
#INの後ろカッコ除去
$sql=preg_replace("/'\)/","' ",$sql);
}
#DELLTE修正
if( substr($sql,0,6)==='DELETE' ) {
#deleteとfromの間にテーブルが入っていたのを除去
$sql=preg_replace("/[^\.]*FROM/",'DELETE FROM',$sql);
#inの処理
$sql=preg_replace("/\sIN *\('/"," ='",$sql);
$sql=preg_replace("/'\)/","' ",$sql);
#テーブルasの除去
$sql=preg_replace("/\sAS\s\"[^\"]+\"/",' ',$sql);
#テーブル名の除去
$sql=preg_replace("/\s\"[^\"]+\"\./",' ',$sql);
}
return $sql;
}
正規表現なので、//の間を一字一句間違えても動作しません。なお、バックスラッシュは半角の¥マークです。このブログでは、システムの関係で、/になっております。コピペで大丈夫と思うけど。本当は preg_replaceをつなげなくて(みっともない)、配列に一気に渡したほうがいいのだと思うけど、試行錯誤でこうなったので、このままにしておきます。
IN句のカッコをとるところなんかはいいかげんで、正直怖いです。何か別にカッコを使っていれば、それを取ってしまうので、そこで新たな不具合を生むおそれアリ。(このスクリプト全般がそうなんだけど)
(追記)
入力データの中に ') や IN(' や "." などがあると消去されます。入れるデータによってはうまくいかないです。(このようなやり方では仕方ない)
繰り返しですが時期バージョンでは修正されるそうなので、そうなったらすぐに本家に従いましょう。
SQLiteファンとしては早く対処して欲しい。しかし無料だから強くもいえんしね。皆さんもドネーションぐらいはしましょう。paypalで20秒でできちゃったよ。
なお、この同じファイルで、SQliteでのnew時(insert)の不具合を修正をやっておかないとinsertできません。
うーむ。ベータ版とはいえ。。。楽じゃないよcakephp。
- TB-URL http://www.cpa-lab.com/tech/045/tb/
-
▼
CakePHP1.2bとSQLite不具合のもっと簡単な直し方
CPA-LABテクニカル 私、nightlyって知りませんでした。ソフト開発の世界では、nightly buildとは、開発途上版ということなのですね。で、CakePHPでは、そのnightly buildが公開されていると。だからそれを使えばいいだぞ、と。こちらCakePHPでは...
1: 2008年07月23日(水) 深夜1時24分