-
Notifications
You must be signed in to change notification settings - Fork 5
Japanese
名前の通り、Firebird のデータベースを別のデータベースに変換します。例えば…
- SJIS_0208 の DB を UNICODE_FSS / UTF-8 にコンバートしたい!
- (実は CharSet が "NONE" のまま使っちゃってるんだ...)
- Firebird サーバのバージョンアップついでに ODS のバージョンも上げたい!
- バックアップを取るついでにスウィープしてファイルサイズも小さくしたい!
という場合に使えます。MIT ライセンスのオープンソースで、Delphi XE4 以降でコンパイルできます。すぐに使えるバイナリも配布されています。 Firebird Database Converter の動作に必要なもの
ローカルで完結したいのであれば、Firebird サーバーのインストールが必要ですが、Firebird サーバーがリモートに存在し、データベースをリモート/ローカルで変換する場合には特に用意するものはありません。
変換元 / 変換先用として、
- Firebird 1.0 クライアント
- Firebird 1.5 クライアント
- Firebird 2.0 クライアント
- Firebird 2.1 クライアント
- Firebird 2.5 クライアント
が同梱されており、さらに変換先用として。
- Firebird Embedded Server 1.5
- Firebird Embedded Server 2.0
- Firebird Embedded Server 2.1
- Firebird Embedded Server 2.5
が同梱されています。つまり、すべてのバージョンへ変換できるという事です。但し、新しいバージョンから古いバージョンへのコンバートは当然うまくいかない事もあります。
自前でコンパイルして使いたいのであれば、以下の環境が必要となります。
- Embarcadero Delphi (XE4 以降)
- ZeosDBO (7.1.2)
- AsyncCalls (2.99)
ZeosDBO は TDataSet 派生の DB 接続コンポーネントです (概要はこちら)。簡単に言えば FireDAC みたいなものです。AsyncCalls はマルチスレッドのライブラリです。
Firebird Database Converter では僕がよく使う IBX は一切使われていません。これは Firebird と Interbase の API や SQL 構文の差異を吸収できないためです。DB アクセスだけなら クライアントライブラリのリネーム程度で問題なく動作しますが (SQL 投げてるだけなので)、IBConsole の雑談でも書きましたが Firebird のちょっと込み入った処理には IBX は不向きです。コード量が少なくて済むので使えるものなら使いたかったのですけどね。
FireDAC を使ってもよかったのですが、Professional ユーザがコンパイルできませんので、ZeosDBO を使う事にしました…あ、言い忘れていましたが、Firebird Database Converter の開発には私も一枚噛んでいます (^^;A
日本語化したい場合には frmuMain.dfm (フォームファイル) と、uFBConvConsts.pas の文字列定数だけ翻訳すれば OK です。もちろん他の言語でも同様です。
Firebird Database Converter に ZeosDBO を使うのは早々に決まりました。何やらメタデータを吐く機能があり、これを使えばコンバートに必要な情報を DB から取得できそうだったからです...でもね?
おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos
メタデータの取得ができると聞いて IBX の IBExtract みたいなのを想像していたのですが、ロクスッポ有益な情報が取れません。これではコンバート用のメタデータなんか作れません。
困りましたが仕方ないので uFBExtract を作りました (^^;A
ソースコードを見て頂ければ解ると思いますが、uFBExtract がパクっているのはその名前だけです。内部構造は全くと言っていい程異なります。そもそも IBExtract は IBX 内で使われる事が前提であり、単独で使われることは想定されていませんし、BigInt 等 Firebird 独自のデータ型等も正しく取得できません。さらっと「uFBExtract を作った」と書いていますが、ODS バージョンの異なる Firebird データベースをいくつも解析して作られています…結構難解です。
で、あらかたメタデータが吐けるようになった段階でおかしな事に気付きました。
- 変換すると文字化けするぞ?
- BLOB があるとコンバートがやたら遅いぞ?
またか…
おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos、おのれ Zeos
この件ですが、実は Delphi Forum に既に投稿してあります。いくつかの解決策は Firebird日本ユーザー会や Firebird の書籍でおなじみ林さんが Zeos のバグトラッカーに報告&パッチ提供されています。
-
#111 Firebird Blob Sub Type
Blob サブタイプ -1 でエラーになる -
#114 Truncate system field value with multibyte character set on Firebird
マルチバイト環境だとシステムテーブルのフィールド名を取得しようとした時にフィールド名が途中で切れてしまう -
#115 Firebird SJIS_0208 is set to EUC
文字コードが Shift_JIS (SJIS_0208) でも何故か EUC_JP で変換される (Lazurus / FPC 対応のせい?)
致命的なのが TRIM の件 (http://zeoslib.sourceforge.net/viewtopic.php?t=19875) です。これは多くのユーザが指摘していますが、Zeos では Firebird 1.0 / 1.5 を指定できるようになっているのに、7.1.2 よりも後のバージョンだと Firebird 1.0 / 1.5 なサーバでエラーが出まくります。これはシステムテーブルから情報を取得するのに TRIM() という関数を使っているからですが、TRIM() は Firebird 2.0.x 以降にしか存在しません (以前は UDF)。
Zeos 7.1.2 にはバグがあり、7.1.3 以降だと回避不可能なバグ (仕様) があるため、Firebird Database Converter では 7.1.2 にパッチをあてたものを使う事にしました。Zeos は LGPL なので、この改変された Zeos も公開されています。最新版の Zeos は追いかけていませんが…マトモに動作するようになったのかな?
それと完全に余談ですが、Zeos は文字コード変換が一段多いような気がします。普通ならサーバの文字コードとクライアントの文字コードだけ指定すればいいじゃないですか?DB 接続のミドルウェアって。でも Zeos はもう一つ文字コード変換を挟んでいるようなのです。例の EUC_JP 変換ロジックとか本来は不要な処理ですよね?文字化けするのを (文字コード変換ロジックを一段増やして) 無理矢理直したという経緯があるのでしょうかね?
Zeos を使ってみたいと思われた方は ClientCodepage (クライアントの文字コード) / ControlsCodePage (GUI の文字コード) にご注意ください。「Firebird Database Converter のソースコード中の文字コード指定は変な事になってるなぁ?」と思われるかも知れませんが、実際問題としてああしないと文字化けします (w
さて、Firebird Database Converter の使い方です。まずは変換元の設定から。
- 変換元の Firebird サーバに接続するクライアントのバージョンです。
- 変換元の Firebird サーバホスト名です。ローカルで変換するには localhost や 127.0.0.1 を指定します。
- 変換元の Firebird サーバポート番号です。ポート番号を変更していなければ 3050 でいいです。
- 変換元のデータベースファイル名です。Firebird サーバがリモートにある場合にはサーバから見たパスで記述する必要があります。ローカルファイルの場合には Explorer からファイルをドラッグ&ドロップする事もできます。
- ローカルにデータベースファイルがある場合には参照ダイアログを開いて指定する事が出来ます。
- 変換元の Firebird サーバに接続するためのユーザ名です。通常は SYSDBA でいいです。
- 変換元の Firebird サーバに接続するためのパスワードです。Windows の場合にはデフォルトで masterkey ですが、Linux サーバの場合には masterkey ではない事があります。
- 変換元のサーバに接続できるかどうかのテストを行います。
変換元のサーバのバージョンと 1. で指定したクライアントのバージョンに相違がある場合には上記のダイアログが出ます。[はい] を押すと 1. を 変換元のサーバのバージョンと同じものに変更します。 - 変換元のデータベースの文字コードです。判らない場合にはそのままにしておいてください。
- 変換元のデータベースの文字コードを自動判別し、9. を変更します。
- 変換元のデータベースの情報を表示します。
ODS (On Disk Structure) 番号等を取得できます。
次は変換先の設定です。
- 変換先の Firebird サーバに接続するクライアントのバージョンです。変換先には同梱されている Firebird Embedded Server を使う事もできます。
- 変換先の Firebird サーバホスト名です。ローカルで変換するには localhost や 127.0.0.1 を指定します。
- 変換先の Firebird サーバポート番号です。ポート番号を変更していなければ 3050 でいいです。
- 変換先のデータベースファイル名です。Firebird サーバがリモートにある場合にはサーバから見たパスで記述する必要があります。
- ローカルにデータベースを保存する場合には参照ダイアログを開いて保存先およびファイル名を指定する事が出来ます。
- 変換先の Firebird サーバに接続するためのユーザ名です。通常は SYSDBA でいいです。
- 変換先の Firebird サーバに接続するためのパスワードです。Windows の場合にはデフォルトで masterkey ですが、Linux サーバの場合には masterkey ではない事があります。
- 変換先のサーバに接続できるかどうかのテストを行います。
変換先のサーバのバージョンと 1. で指定したクライアントのバージョンに相違がある場合には上記のダイアログが出ます。[はい] を押すと 1. を変換先のサーバのバージョンと同じものに変更します。 - 変換先のデータベースの文字コードです。デフォルトで Unicode 系の文字コード (UNICODE_FSS / UTF8) が指定されます。
変換オプションの設定です。
-
Create empty database
空の DB を作成します。 -
Metadata Only
メタデータだけを生成します。メタデータは複数の SQL を列挙したもので、理屈的にはメタデータから DB を構成できます (内容も含めて)。 -
Verbose mode
変換状況を表示します。 -
Strict check
このチェックボックスの値は firebird.conf の RelaxedAliasChecking に反映されます。RelaxedAliasChecking の意味についてですが、詳細については林さんのブログの記事 (http://blog.tomnekosoft.com/tomnekosoft.php?itemid=678) を確認してください。 -
Conversion from Integer to BigInt
Integer (32bit) のフィールドを BigInt (64bit) に置換してからコンバートします。
Firebird Database Converter には fbconverter.ini という設定ファイルがあり、書き換える事で挙動を変化させる事ができます。
-
DEFAULT_CHARSET
移行元データベースのデフォルトキャラクタセット。
(Default: SJIS_0208) -
MAX_ERROR_LINE
Firebird サーバからエラーが返ってきた時に表示するエラーの最大行数。エラーに含まれる SQL が長大な場合に無駄にログが長くなるのを防止するための行数制限。
(Default: 5) -
POST_DATA_SPLIT_SIZE
テーブルデータの移行時に分割処理するレコード数。マルチスレッドの場合は自動で "POST_DATA_SPLIT_SIZE / スレッド数" が設定される。最低値は 100。
(Default: 1000) -
USE_MULTI_THREAD
マルチスレッド動作の有効(1)/無効(0)。
(Default: 1) -
NUMBER_OF_IMPORT_THREAD
マルチスレッド有効時のスレッド数を指定。最低値は 2、最高値は "POST_DATA_SPLIT_SIZE / 2" となる。
(Default: 4) -
WORK_DIR
VerboseMode で使用する作業用フォルダ。変換処理と同等のメタデータはここに保存される。
(Default: %USERPROFILE%\AppData\Roaming\Firebird Converter)
幾つか注意点を。
-
クライアント / サーバのバージョンは一致させるべきか?
特にこだわりがない限り一致させておいた方がいいかと思います。一致していなくてもサーバより新しいバージョンのクライアントなら問題は起きにくいとは思いますが、Firebird Database Converter は同梱されているクライアントを使うので、わざわざサーバと異なるバージョンを使うメリットはない気がしますが…? -
誰かが使っている DB のコンバートは可能か?
Firebird Database Converter がやっているのは DB ファイルの丸コピーではないので可能です。ただ、サーバに負荷がかかったりする事があるので、なるべくなら誰も接続していない時間帯にやるのがいいでしょう。ローカルでの作業なら、もちろんその限りではありません。 -
コンバートすると VARCHAR のサイズが変わるんだけど?
コンバートの際に文字コードを変更すると、Firebird での文字数の扱いの違いにより VARCHAR の文字数が変更されます。こうしないと既存のデータが失われますし、いざ運用しようとしても文字列が格納できなくなって困る事になるでしょう。キリの悪い文字数になってしまうかもしれませんが、キー項目でなければ ALTER TABLE ALTER でサイズ変更する事ができます。
"その文字コードでは1文字が最大何バイトで構成されるか?" という情報は、Firebird のシステムテーブル RDB$CHARACTER_SETS の RDB$BYTES_PER_CHARACTER に格納されており、Firebird Database Converter では変換元と変換先の文字コードの "1文字構成バイトサイズ" から計算して VARCHAR のサイズを変更します。VARCHAR のサイズ上限を超える場合には 32765 が設定されます。 -
文字コード NONE の DB はどうコンバートされるのか?
NONE は SJIS_0208 とみなされます。NONE に SJIS_0208 以外の文字コードで書き込んでいる場合にはその文字コードを明示的に指定してください。
ソースコード中では SJIS_0208 に決め打ちされていますが、これは Windows の ANSI 文字コードと Firebird がサポートしている文字コードを 1:1 で関連付けさせる事ができないからです。英語圏で使うのなら NONE が指定された時のデフォルトを WIN1252 にすべきだと思いますが、すべての国と地域に対応させようとすると…。 -
Strict check を外さないとコンバートできなかったけれど?
Strict check を外さないとコンバートできなかったのであれば、ビューやストアドプロシージャ、トリガの文法が Firebird 2.0 以降に合致していない事を意味します。この場合、実稼働させる Firebird サーバで採れる手段は二つあります。
― ビューやストアドプロシージャ、トリガを Firebird 2.0 以降の仕様に合わせて修正する。
― 実稼働させる Firebird サーバの firebird.conf の RelaxedAliasChecking を 1 に書き換えて Firebird 1.5.x 以前と互換性のあるモードで運用する。
根本的な解決にならないので前者をオススメします。 -
マルチスレッド動作に関して
実は当方の環境ではテスト中に何度かエラーが出ました。それでも [OK] を押せば正しく変換はできました。
― AsyncCalls の使い方は本当にこれでいいのか?
― そもそもだけど Zeos はスレッドセーフなのか?
という疑問が残ります。変換に何時間もかかるようならマルチスレッドオフで使う事をオススメします。コンバート速度は総合的にマルチスレッドオンの方が速かったと思いますが「速度が倍違う」といった事はありません。比較的小さな Firebird のデータベースファイルをお持ちであれば、まずそちらで確認された方がいいかもしれません…あまりにも小さいとマルチスレッドのテストになりませんけれど (^^;A




