pg4wpその後

たぶんこれに興味のある人は日本全国に10人くらいしかいないと思いますが、WordPressを PostgreSQLで使うドライバ、pg4wpのその後です。
プラグインを入れるたびに新たなエラーが発生して、その都度、いろいろと手を入れています。
今回は、Contact Form 7を入れたらエラーになりました。Contact Form 7が auto_increment付きのテーブルをクリエイトしようとしてエラーになりました。WordPressの標準って主キーにオートインクリメントを使ってないのですかね。それはそれでびっくりです。

if(stripos($sql, 'CREATE TABLE') === 0) {
  $sql = str_ireplace('CREATE TABLE IF NOT EXISTS', 'CREATE TABLE', $sql);

  $a   = preg_split("/(CREATE TABLE | \()/", $sql);
  $tbl = $a[1];

  $sql = preg_replace("/DEFAULT CHARACTER SET .+;/", ";", $sql);
  $sql = preg_replace("/,\s*PRIMARY KEY\s\(.+?\)/i", "", $sql);
  $sql = preg_replace("/text\s+NOT\s+NULL/i", "text default ''", $sql);
  if (stripos($sql, 'auto_increment')) {
    $s = "";
    $a = explode("\n", $sql);
    foreach($a as $v) {
      if (stripos($v, 'auto_increment')) {
        $b = explode(" ", trim($v));
        $key = $b[0];
        $v = $key." integer DEFAULT nextval('".$tbl."_seq'),\r\n";
      }
      $s .= $v;
    }
    $sql = $s;
    $sql = "CREATE SEQUENCE ".$tbl."_seq; ".$sql."; CREATE UNIQUE INDEX ".$tbl."_".$key."_key on ".$tbl." (".$key.");";
  }
}

相変わらず力技です。(ここは笑うところか?)
まず、PostgreSQLには “IF NOT EXISTS”がないのでこれを取っ払って(テーブルがすでにあったらエラーになるので、なかったら実行はなくても可)、”PRIMARY KEY(key)”という指定もないみたいなので、これも取っちゃって、あと、これがクリビツテンギョウなんですけど、MySQLは text NOT NULL属性で値を指定しない(INSERT文に含めない)と、空文字を勝手に入れてくれるのに対して、PostgreSQLはエラーになっちゃうんですね。
これは NOT NULL属性をつけてる主旨からいって、PostgreSQLを支持したいです。でも、INSERT文でエラーになるのは仕方ないので、text NOT NULLは、text default “”にして、NOT NULLを外しちゃいました。
 
あと、面倒なところが、auto_incrementの取扱い。そのまま、SERIALにしちゃえばいいようなものなんですけど、そうすると、シーケンシャル・テーブルの名前が、table名_カラム名_seqという名前になって、wp_optionsなんかで使っている table名_seqルールと合わなくなってしまうこと。
で、SERIALが使えなくて、いちいち、CREATE SEQUENCE、CREATE UNIQUE INDEXみたいなことをやってるわけです。(きっとどっかにもっといい方法があるはずだ)
 
参考:PostgreSQL 日本語ドキュメントはよくできています。

5 Comments so far

  1. Wing on 5月 24th, 2010

    はじめまして。
    PostgreSQLしか提供されていないサーバーに契約してしまい、どうにかこうにかWordpressをテスト運用まで持っていけた者なのですが、まさにこの問題にぶち当たり、メールフォームの設置に難儀しておりました。

    早速、この方法を試してみたいのですが、エントリーにあるソースをどのファイルに記述すれば良いのかが分からないため、もし良ければご教授いただけないでしょうか?

  2. admin on 5月 24th, 2010

    コメントありがとうございます。
    WordPressをどうやって PostgreSQL対応されたのかが文面からはわかりませんが、私と同じ pg4wpをご使用なのであれば、こちらでテスト中のものをおいておきます。(http://ss01.info/pg4wp.lzh)
    まだ、いろいろと抜けがあると思いますので、あくまでも自己責任でお願いします。
    このソースとご自分のプラグインフォルダのソースを比べていただくとどこを書きかえればいいかがわかると思います。
    ソースを読んで動作がわからないようなら、いまのうちに MySQLの動くサーバ(世の中のほとんどのサーバ)へお引越しすることをオススメします。いまもやってて思いますが、WordPressをプラグインを含め、すべてのケースで PostgreSQLに対応させるのは結構大変です。
    力技、決め打ちでやらないといけないところがその都度出てきますので、不慣れな方にはオススメできませんこと、ご了承くださいませ。

  3. Wing on 5月 24th, 2010

    レス有難うございます。
    元々趣味でサイト運営をしてたのですが、それが元で親戚から「仕事の合間に」と頼まれ、与えられた環境がPostgreSQLしか提供されないサーバーでした。
    どうもサーバー周りも縁故で調達したらしく、こちらで主導権を握れないため、仕方なしにと言った具合です。

    説明不足だったのにも関わらず、ファイルまでアップしていただいて恐縮です。
    今更ではございますが、Wordpress2.9.2、pg4wp1.1.0という環境下でContact Form 7 2.2を導入しようと思い躓きました。

    アップしていただいたファイルを差し替えてみたり、関係のありそうなソースだけ抜き出して移植してみたりといろいろ試してみたのですが、上手く動作せるコトが出来ませんでした。

    ご忠告を受けて素直にMySQLの動くサーバーに引越ししたいところですが、前述の都合上、フォーム部分のみWordpressとは切り離した別のフォームで代替したいと思います。

    有難うございました。

  4. admin on 5月 25th, 2010

    もう見てらっしゃらないかもしれませんが、がんばる気があるならひと言だけ。
    Contact Form 7の場合、テーブル作成と新規レコードの追加でエラーになります。
    つまり、テーブルがすでにあって、なにかしらのレコードができていれば、エラーにならないので、MySQLで同等の環境を作って、wp_contact_form_7テーブルの構造とデータをそのまま PostgreSQLにもっていけば(主キーのautoinc属性は外して)、動くと思います。
    また、Contact Form 7のように独自テーブルを持つプラグインではなく、通常の wp_optionsなどにデータを書くプラグインであれば、エラーにならずにインストールできると思いますので、そちらを探されるのもありかなと思います。

  5. Wing on 5月 27th, 2010

    遅くなりましたが、アドバイス有難うございます。
    その後、件のサーバー担当者にテーブルの作成を依頼し、なんとか動作するようになりました。

    テーブル作成後、以下の3ファイルを修正し、pg4wpは何も手を加えないで動作したことをお伝えしておきます。

    ・/contact-form-7/includes/shortcodes.php
     ※修正箇所:106行目
      $text = preg_replace( “/[\x{00a0}\x{200b}] /u”, ” “, $text );をコメントアウト

    ・/contact-form-7/settings.php
     ※修正箇所:36行目
      return strtolower( $wpdb->get_var( “SHOW TABLES LIKE ‘$table’” ) ) == strtolower( $table );を
      return true;に変更
    ・/wp-includes/shortcodes.php
     ※修正箇所:228行目
      $text = preg_replace(“/[\x{00a0}\x{200b}] /u”, ” “, $text);をコメントアウト

    突然の質問にも関わらず、快くご回答くださり有難うございました。