ぐらめぬ・ぜぷつぇんのはてダ(2007 to 2011)

2007年~2011年ごろまで はてなダイアリー に書いてた記事を引っ越してきました。

DboSource::query()がご丁寧にも勝手にfromのテーブル名を返り値の配列のキーにセットしてくれる件


CakePHP 1.1.19 です。

ようやく以下のようなコードで、「さて、どんな構造で返ってくるか・・・。」と試すことが出来ました。

$ds =& ConnectionManager::getDataSource(CAKEAPP_SHOP_ENV);
$sql = "select * from hoge  where id = " . $ds->value('1');
$results = $ds->query($sql);
var_dump($results);

ちなみに

$ds->value('1')

というのは、DboMysqlにおいてはvalue()は一応ちゃんと、

function value($data, $column = null, $safe = false) {
switch ($column) {
default:
    $data = "'" . mysql_real_escape_string($data, $this->connection) . "'";
break;
}
...
}

みたいにmysql_real_escape_string()してくれてます。あ、ちなみに上記コードをそのまま信用しちゃだめですよ。$column部分の判断条件とか、$dataの"空"判断とかbool型独特の処理とかも隠れてますので。

まぁ、'encoding'を指定したときのsetEncoding()では"SET NAMES"を発行してたりするのですが。

で、さて、どんな構造で返ってくるのか・・・。

array(1) {
  [0]=>
  array(1) {
    ["hoge"]=>  # ... テーブル名?
    array(16) {
      ["id"]=>
      string(1) "1"
      ["gender"]=>
      string(1) "f"

・・・誰がいつ、勝手にテーブル名をレコードの戻り値のキーにセットしろと言ったんだよ《゚Д゚》ゴラァァァァァァァァァァァァア!!

(*`Д´)=○)Д゚) ´Д゚)・;’

・・・落ち着いてコードを確認してみると、dbo_mysql.phpでこのようなコードがあり、これが呼ばれているためのようだ。

function resultSet(&$results) {
...
while ($j < $num_fields) {
    $column = mysql_fetch_field($results,$j);
    if (!empty($column->table)) {
        $this->map[$index++] = array($column->table, $column->name);
    } else {
        $this->map[$index++] = array(0, $column->name);
    }
    ...
}
...
}

うわぁ・・・何これ。JDBCを使ったデータアクセスに慣れた身としては、キモイの一言なんだけど。例えばOracle使ってUNIONとかばりばり使う凶悪なSQL発行したときとか、フォローできるの?あるいは他のDBMSとI/F併せられるの?
なんっつーか、これ、複雑なSQLを発行した場合にいやーな結果になりそうな予感がしてならないです。
というか、そういう予感を抱かせる時点でキモイ。

symfonyはなぁ・・・。Creoleが結構JDBCな感じで素直にラップしてくれてて、Propelもそれなりに癖はあるけど比較的「ここまでの用途だったら快適ですよー。」という線引きがわかりやすかった。また最終的にPropelを通さずベタに扱うための「逃げ」というか「マージン」があったからこんな窮屈な感じはしなかったんだけど。

きっつー。