Jan 14, 2006

DBコンバート後に受信済みのトラックバックを参照できない問題への対処

このブログで長らく公開してきたmt-db-convert.cgi、およびMovable Type 3.2に同梱のmt-db2sql.cgiに大きめのバグを発見しました。どちらのツールでもコンバート後にすでに受信済みのトラックバックを参照できないという問題が生じ得ます。

現在下記にて配布している0.20以降のバージョンでは、すでに対策済みです。

Ogawa::Buzz: mt-db-convert.cgi: MTデータベースの相互変換 CGIスクリプト

過去に一度でもmt-db-convert.cgiかmt-db2sql.cgiを使ってデータベースを変換したことがある場合には、(顕在化していなくても)潜在的には問題がある可能性があります。不安を煽っても仕方がないので、問題の有無を検査したり、データベースを訂正するためのプログラムも用意しましたので、症状に心当たりがある人は試してみるとよいでしょう。

問題の詳細

mt-db2sql.cgiもmt-db-convert.cgiも、新規のデータベースを作成して元のデータベースからMT::Object単位でコピーしていきます(MTではブログを表現する大抵のデータ構造がMT::Objectのサブクラスとして表現されています)。コピーはサブクラス(オブジェクトの種類)ごとにまずAuthorクラスのオブジェクトを順にコピーし、次にBlogクラスを、さらにCategory, Comment, Entry (中略) Trackback, TBPing (後略)をそれぞれコピーしていきます。

ところが、MT::ObjectのうちEntryとCategoryの保存時には、対象のオブジェクトがトラックバック可能な場合、データベースにTrackbackオブジェクトがあるかどうか問い合わせ、なければ新規に生成して保存するようになっています。

これはトラックバック可能な新規エントリーを作成したりする場合には正常に機能します。一方、コンバート時にTrackbackクラスより先にEntryクラスをコピーすることを考えると多少事情が異なります。新規データベースにはTrackbackオブジェクトは存在しませんから、まずEntryコピー時にTrackbackオブジェクトを一通り新規生成した後、さらにTrackbackコピー時にそれが上書きされることになります。この結果、あるEntryオブジェクトに対応するTrackbackオブジェクトが複数存在する状態が作られます。

例えば、Entryが3個あり、それぞれに関連付けられたTrackbackオブジェクトのidが1,3,5であるという状態を仮定します。Entryのコピー時にはidが1,2,3のTrackbackオブジェクトが新規生成され、Trackbackのコピー時にはidが1,3,5のTrackbackオブジェクトが作成されます。したがって、新しいデータベースには1,2,3,5という4つのTrackbackオブジェクトが作られることになります。

さて、Movable TypeのTrackbackクラスは、エントリーやカテゴリーのトラックバックインタフェースの抽象ですが、EntryオブジェクトとTBPingオブジェクト(受信した個々のトラックバックデータ)を関連付ける役割もあります。さらに悪いことには、関連付ける際にMovable TypeはIDの一番小さいTrackbackオブジェクトしか参照しません。したがって、参照されなかったTrackbackオブジェクトに関連付けられたTBPingオブジェクトも参照されません。この結果として、過去に受信したTBPingとEntryとを関連付けられなくなります。

この問題を避けるには、コピー時に必ずTrackbackクラスを先にコピーするか、Entryに対応付けられたTrackbackオブジェクトが複数あっても正常に動作するように本体プログラムを修正する必要があります。

冒頭でも述べたように、mt-db-convert.cgiの0.20以降では前者の対処を行ってあります。mt-db2sql.cgiへの対処はOgawa::Buzz: MT 3.2日本語版 Unofficial Patchに追加しました。

検査・修正用プログラム

簡単なデータベースの検査・修正用のプログラムを用意しました。

mt-tbfixer.cgi

上記のCGIスクリプトをmt.cgiなどと同じディレクトリにアップロードし、実行権限を与えて、ブラウザなどから起動してください。

何もオプションを与えなければデータベースの検査をしてくれます。

MT::Trackback(id=194) conflicts with (id=198) for entry 928
   MT::TBPing(id=998) can be moved from MT::Trackback(id=194) to (id=198)
   MT::Trackback(id=194) can be removed
MT::Trackback(id=118) conflicts with (id=129) for entry 859
   MT::Trackback(id=118) can be removed
...
 
15 conflicts are found in MT::Trackback!
5 conflicts are found in MT::TBPing!

この例では、mt-db-convert.cgiやmt-db2sql.cgiの実行時に誤って作られたTrackbackオブジェクトが15個あり、それらのトラックバックインタフェースに送信された5件のTBPingオブジェクトがあることが分かります。前者の値が0ならばまったく問題はありません。

次にデータベースの訂正を行うには、まずデータベースのバックアップを取ってください

バックアップしましたね?

いいんですね?

…では続けます。今度は「http://.../mt-tbfixer.cgi?__mode=fix」のように「?__mode=fix」というオプションを付けて起動します。

MT::Trackback(id=194) conflicts with (id=198) for entry 928
   MT::TBPing(id=998) is moved from MT::Trackback(id=194) to (id=198)
   MT::Trackback(id=194) is removed
MT::Trackback(id=118) conflicts with (id=129) for entry 859
   MT::Trackback(id=118) is removed
...
 
15 conflicts are found and fixed in MT::Trackback!
5 conflicts are found and fixed in MT::TBPing!
 
You should perform rebuilding for all MT contents.

と表示された時点で修正作業は終了しています。最後にすべてのページを再構築すれば、コンバートの際に見えなくなっていたトラックバックが表示されていることでしょう。

注: このスクリプトはテストが相当不足しています。チャレンジャーをお待ちしています。
注: このスクリプトはカテゴリーのトラックバックインタフェースを考慮していません。今のところ重要度が低いと考えて先送りしていますが、そのうち実装します。

About Me

My Photo

つくばで働く研究者

Total Pageviews

Amazon

Copyright 2012 Ogawa::Buzz | Powered by Blogger
Design by Web2feel | Blogger Template by NewBloggerThemes.com