WordPress の dbDelta() でテーブルが作成されない
WordPress のプラグインで、独自のDBテーブルを使いたいとき、dbDelta という便利な関数がある。プラグインのバージョンアップの際に、DDL の違いを見分けて、自動的に DBスキーマを更新してくれるという、Rails のマイグレーションみたいなやつだ。
DDL の違いを自動的に見て対応してくれるために、その SQL はルールに従って書く必要がある。 http://codex.wordpress.org/Creating_Tables_with_Plugins によれば、以下の決まりがある。
- それぞれのフィールドはSQLの別々の行に書くこと
- PRIMARY KEY という文字列と、主キーの定義の間はスペース2つ分空けること
- キーワードKEYを使うこと。同義語のINDEXは使えない。少なくとも1つのキーを含めること
- アポストロフィーやバックティック('や`)でフィールド名を囲まないこと
それだけではない。上記に加えて、SQL のキーワードは大文字で書かなくてはいけない。
ダメだった例
create table wp_xxx (
  id bigint not null auto_increment,
  token varchar(32),
  payer_id varchar(32),
  amount int,
  primary key (id)
) ENGINE=InnoDB DEFAULT CHARSET = utf8;
成功した例
CREATE TABLE xxx (
  id bigint NOT NULL AUTO_INCREMENT,
  token varchar(32),
  payer_id varchar(32),
  amount int,
  UNIQUE KEY id (id)
) ENGINE=InnoDB DEFAULT CHARSET = utf8;
wp-admin/includes/upgrade.php を見ると、大文字しか見ていなかった。SQLは大文字で書くのが標準とはいえ、個人的には小文字で書く方が好きなので、ちょっとはまった。
        // Create a tablename index for an array ($cqueries) of queries
        foreach($queries as $qry) {
                if (preg_match("|CREATE TABLE ([^ ]*)|", $qry, $matches)) {
                        $cqueries[ trim( $matches[1], '`' ) ] = $qry;
                        $for_update[$matches[1]] = 'Created table '.$matches[1];
                } else if (preg_match("|CREATE DATABASE ([^ ]*)|", $qry, $matcs)) {
                        array_unshift($cqueries, $qry);
                } else if (preg_match("|INSERT INTO ([^ ]*)|", $qry, $matches)) {
                        $iqueries[] = $qry;
                } else if (preg_match("|UPDATE ([^ ]*)|", $qry, $matches)) {
                        $iqueries[] = $qry;
                } else {
                        // Unrecognized query type
                }
        }