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