Zend_Db_Selectの不穏な動き

( diary )

最近、こう日記を更新していけども。まぁHDがいかれるやらSATAのコネクタの規格を間違って購入してることやらなんやらほんにゃら。 そろそろ、俺のサーバもクラウドかな。まだやらんけどさ。

マニュアル上ではこんな感じで記述されていてクラスでもSQL(文字列)でも埋め込める事ができるらしいのだけれど

$sql1 = $db->select();
$sql2 = "SELECT ...";
 
$select = $db->select()
    ->union(array($sql1, $sql2))
    ->order("id");

でも実際この通り実装してみるエラー発生、原因としてはどうやらMysql5でZendが吐いたSQLを実行すると エラーが発生する模様。Mysql4ではどうも発生しなかったみたい。Zendの仕様なのかなと思ったので しょうが無く文字列にしてごねごね作成することにした。

$sql1 = $db->select();
$sql2 = "SELECT ...";
 
$select = $db->select()
    ->union(array("(".$sql1->__toString().")", "(".$sql2.")"))
    ->order("id");

でも、この書き方腑に落ちないですね。SQLは低レイヤーで抽象化されるべきもの。しかもUNIONするときは括弧で括ったほうが SQL的には推奨されてるはずなんだけどねーー。

Mysqlマニュアル

この辺、いじって括弧で括らせれば問題解決されるかも。でもZendのオリジナルソースいじるの気がひけるなー。 継承したいところだけど結構クラスが入り組んでて大変なことになりかねないのでソースいじったほうがてっとり早いんだろうなー。

この辺いじる。

    /**
     * Render UNION query
     *
     * @param string   $sql SQL query
     * @return string
     */
    protected function _renderUnion($sql)
    {
        if ($this->_parts[self::UNION]) {
            $parts = count($this->_parts[self::UNION]);
            foreach ($this->_parts[self::UNION] as $cnt => $union) {
                list($target, $type) = $union;
                if ($target instanceof Zend_Db_Select) {
                    $target = $target->assemble();
                }
// この辺かな
                //$sql .= $target;
                $sql .= '(' . $target . ')';
                if ($cnt < $parts - 1) {
                    $sql .= ' ' . $type . ' ';
                }
            }
        }

        return $sql;
    }