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 } }