別に設定を変えたわけでもないのに、突然、Movable Type で特定の記事を保存して再構築するとエラーが発生するようになってしまった。カテゴリーアーカイブの構築でしくっているらしい。その記事が属するのは1000個以上も記事がある大きなカテゴリーだった。
同じ症状で困っている人がいるかもしれないので、今回見つけた暫定的な解決方法とそこに至るまでの経路について書いておくことにする。ちなみにMovable Type のバージョンは MTOS 4.24(追記:4.25でも同じ症状)。DBは Sqlite3 を選択している。
まず設定ファイル mt-config.cgi に以下の行を追加した。
DebugMode 1
これでエラー発生時に詳細な情報が表示されるようになる。でてきたエラーメッセージは以下の通り。
Can't call method "execute" on an undefined value at extlib/Data/ObjectDriver/Driver/DBI.pm line 137.
DBI.pm のその行周辺をみてみると以下のようになっている。
my $sth = $orig_args->{no_cached_prepare} ? $dbh->prepare($sql) : $dbh->prepare_cached($sql);
$sth->execute(@{ $stmt->{bind} }); ←ここでエラー
$sth の値が undefined になってエラーが発生しているのだ。ソースファイルのエラー発生箇所の直前に以下の行を挿入して、さらに詳細なエラーメッセージとスタックトレースを表示する。
Carp::confess (DBI->errstr) if $sth;
すると、
too many SQL variables(1) at dbdimp.c line 271 ...(以下略)
同じく Carp::confess を使ってSQL式が入っている変数 $sql の中身をのぞいてみると、確かに SQL変数 '?' が1000個以上も使われている。何らかの上限に達したのかもしれない。でも、そのカテゴリーの記事を削除して減らしてみても症状は変わらないし、そもそも最後の記事を追加したときは別に平気だった。
今のテンプレートではそんなにたくさんの記事を参照する必要はないはずなので、何かおかしいことになっているのは間違いないが、そちらを追求していくことを考えると途方にくれそうだったので、対症療法で、強制的にフェッチするエントリーの個数に制限をかけることにした。ここでは 300 にしてある。
llib/MT/ArchiveType/Category.pm の archive_group_entries という関数に以下のように1行挿入する。
sub archive_group_entries {
my $obj = shift;
my ( $ctx, %param ) = @_;
my $limit = $param{limit};
if ( $limit && ($limit eq 'auto') ) {
my $blog = $ctx->stash('blog');
$limit = $blog->entries_on_index if $blog;
}
$limit = 300 unless $limit; #← これを挿入
これでエラーが発生しなくなった。