Ethna で MySQL の予約語とかぶっているテーブル名を AppObject で扱う場合エラーするのを治すたった一つだけの方法

はじめまして。エンジニアの今野です。社内の圧力に屈したため Blog を書くことになりました。よろしくお願いします。

Ethna 2.5.0 を案件で使用していて release など MySQL の予約語になっているテーブルを AppObject で扱う場合不正なクエリが発行され動かないケースがありました。以下は debug log からの抜粋。

2010/03/09 16:46:17 Appid(DEBUG): SELECT COUNT(DISTINCT `release`.``) AS `id_count` FROM `release`
2010/03/09 16:46:17 Appid(ERR): Query Error SQL[SELECT COUNT(DISTINCT `release`.``) AS `id_count` FROM `release` ] CODE[1054] MESSAGE[SELECT COUNT(DISTINCT `release`.``) AS `id_count` FROM `release`  [nativecode=1054 ** Unknown column 'release.' in 'field list']] [ERROR CODE(4)]

MySQL の query log はこんな感じ。 release が予約語なので不正なクエリ。

13 Query       SELECT * FROM release LIMIT 0

Ethna の AppObject は prop_def を書かなくてもテーブル構造から勝手に prop_def を作ってくれる機能があるのですが、そこでテーブル名をエスケープしていない為に不正なクエリが実行されてしまい $prop_def の定義がおかしくなってしまうようですね。

$prop_def を手書きしてしまうか、テーブル名を変えればしのげるのですが、それでは若干悔しいので Ethna_DB_PEAR クラスを継承してサクッと治してしまいます。Ethna が include 出来る場所に Appid_DB_PEAR.php と言うファイル名で以下の内容で保存しましょう。 (Appid はご利用のプロジェクト名に置き換えてね!)

<?php
require_once 'Ethna/class/DB/Ethna_DB_PEAR.php';

class Appid_DB_PEAR extends Ethna_DB_PEAR
{
    function getMetaData($table)
    {
        return parent::getMetaData($this->db->quoteIdentifier($table));
    }
}

Controller クラスに教え込みます。

var $class = array(
    /*
    *  TODO: When you override Configuration class, Logger class,
    *        SQL class, don't forget to change definition as follows!
    */
    'class'         => 'Ethna_ClassFactory',
    'backend'       => 'Ethna_Backend',
    'config'        => 'Ethna_Config',
    'db'            => 'Appid_DB_PEAR',    // ← ここを変更
    'error'         => 'Ethna_ActionError',
    'form'          => 'Appid_ActionForm',
    'i18n'          => 'Ethna_I18N',
    'logger'        => 'Ethna_Logger',
    'plugin'        => 'Ethna_Plugin',
    'session'       => 'Ethna_Session',
    'sql'           => 'Ethna_AppSQL',
    'view'          => 'Appid_ViewClass',
    'renderer'      => 'Ethna_Renderer_Smarty',
    'url_handler'   => 'Appid_UrlHandler',
);

これで治りました。 Ethna_DB_PEAR::getMetaData() 自体がエラーするわけでは無いので最初ハマりましたが、同じような現象で困っている方の参考になればと思います。 (と言うか予約語とかぶるようなテーブルを作るなって話ですよね……。)

しばらくは Ethna ネタで記事の投稿を行っていく予定です。では、お粗末さまでした!

preload preload preload