フォーラム


ゲスト  

ようこそ ゲスト さん。このフォーラムに投稿するには 登録が必要です。

ページ: [1]
トピック: ZeosDBO で Firebird に接続する
DEKO
管理者
投稿数: 2691
ZeosDBO で Firebird に接続する
on: 2013/08/27 21:05 Tue

コードで書くとこんな感じです。

uses
..., ZConnection, ZDataset;

procedure TForm1.Button1Click(Sender: TObject);
var
DBC: TZConnection;
QRY: TZQuery;
begin
DBC := TZConnection.Create(Self);
QRY := TZQuery.Create(Self);
try
// TZConnection
DBC.Database := '127.0.0.1:C:\FB_TEST\DATA.FDB';
DBC.User := 'SYSDBA';
DBC.Password := 'masterkey';
DBC.Protocol := 'firebird-2.1';
with DBC.Properties do
begin
Values['codepage'] := 'UNICODE_FSS';
Values['dialect' ] := '3';
end;
// TZQuery
QRY.Connection := DBC;

DBC.Connect;
if DBC.Connected then
begin
QRY.SQL.Text := 'SELECT * FROM TBL_DETAIL';
QRY.Open;
while not QRY.Eof do
begin
// ...
QRY.Next;
end;
QRY.Close;
DBC.Disconnect;
end;
finally
QRY.Free;
DBC.Free;
end;
end;

 
fbclient.dll を GDS32.DLL にリネームする必要はありません。Zeos.inc 中で FIREBIRD_STRICT_DLL_LOADING が指定されていると、以下の名前の DLL を読みに行きます (Protocol: DLL 名)。

  • interbase-6: gds32.dll
  • firebird-1.0: gds32.dll
  • firebird-1.5: fbclient15.dll
  • firebird-2.0: fbclient20.dll
  • firebird-2.1: fbclient21.dll
  • firebird-2.5: fbclient25.dll
  • firebirdd-1.5: fbclientd15.dll (Firebird Embedded Server 1.5)
  • firebirdd-2.0: fbclientd20.dll (Firebird Embedded Server 2.0)
  • firebirdd-2.1: fbclientd21.dll (Firebird Embedded Server 2.1)
  • firebirdd-2.5: fbclientd25.dll (Firebird Embedded Server 2.5)

指定されていなければ、Protocol が (Firebird の) 何であっても以下の名前の DLL を読みに行きます。

  • Firebird Super / Classic Server: fbclient.dll
  • Firebird Embedded Server: fbclientd.dll

※ デフォルトでは FIREBIRD_STRICT_DLL_LOADING はオフです (ピリオドでコメントアウトされています)。

Properties に渡せるパラメータは以下の通りです。

  • codepage=<Firebird で使える文字コード名>
  • createNewDatabase=<DB 作成 SQL 文 (CREATE DATABASE)>
  • dialect=<ダイアレクト>: 1, 2 または 3。通常は 3。
  • RoleName=<ロール名>
  • hard_commit=[yes,no]: yes だとハードコミット (明示的コミット)、no だとソフトコミット (暗黙的コミット)

詳しくは /doc/html フォルダ内の parameters.html を参照してください。但しこのドキュメントは古い (2008/05 時点) ので、正確な仕様についてはソースコードを確認する事をオススメします。

個人的には Interbase / Firebird なら DBX でも FireDAC でもなく「IBX でいいやん」と思ってしまいます。ZeosDBO は "Pro 版 +PostgreSQL" とかそっちの接続に使うのがいいのかな?と思っています。Ent 以上なら FireDAC がありますしね。

DEKO
管理者
投稿数: 2691
Re: ZeosDBO で Firebird に接続する
on: 2015/01/19 02:41 Mon

最近の Zeos は SJIS_0208 な DB を開くと文字化けします。これは SJIS_0208 の変換に何故か EUC-JP が使われているからです。
http://sourceforge.net/p/zeoslib/tickets/115/

また、BLOB でサブタイプが -1 (ユーザ定義) のフィールドはエラーになります。
古い Interbase / Firebird ではユーザ定義の BLOB のサブタイプは -1 が推奨されていたのですが…。
http://sourceforge.net/p/zeoslib/tickets/111/

そして最新の Zeos は Firebird 1.5 以前に接続するとエラーを連発します。これは Zeos が内部的に TRIM() を使っているからです。
(Firebird 1.5 以前には TRIM() 関数は存在しない)
http://zeoslib.sourceforge.net/viewtopic.php?t=19875

古い Firebird から新しい Firebird までをカバーするのであれば、Zeos 7.1.2 を修正するのが最も簡単です。

  • ZDbcInterbase6Utils.pas
  • ZPlainFirebirdDriver.pas

2つのファイルを修正してください。

[ZDbcInterbase6Utils.pas]
    blr_blob, blr_blob2:
begin
case SqlSubType of
{ Blob Subtypes }
{ types less than zero are reserved for customer use }
isc_blob_untyped: Result := stBinaryStream;

{ internal subtypes }
isc_blob_text: Result := stAsciiStream;
isc_blob_blr: Result := stBinaryStream;
isc_blob_acl: Result := stAsciiStream;
isc_blob_ranges: Result := stBinaryStream;
isc_blob_summary: Result := stBinaryStream;
isc_blob_format: Result := stAsciiStream;
isc_blob_tra: Result := stAsciiStream;
isc_blob_extfile: Result := stAsciiStream;
isc_blob_debug_info: Result := stBinaryStream;

{ ADD DEKO BEGIN }
else
{ User defined subtypes}
Result := ZDbcIntfs.stBinaryStream;
{ ADD DEKO END }
end;
end;

 

[ZPlainFirebirdDriver.pas]
  { MOD DEKO BEGIN }
// Self.AddCodePage('SJIS_0208', CS_SJIS_0208, ceAnsi, zCP_EUC_JP, '', 2); {Japanese}
Self.AddCodePage('SJIS_0208', CS_SJIS_0208, ceAnsi, zCP_SHIFTJS, '', 2); {Japanese}
{ MOD DEKO END }

 
Zeos 7.1.3 以降には TRIM() の問題があるため、上記の修正を行っても Firebird 1.5 以前のサーバに接続すると問題が発生します。

DEKO
管理者
投稿数: 2691
Re: ZeosDBO で Firebird に接続する
on: 2015/01/19 17:15 Mon

最新の Zeos では緩和されているようですが、少し前の Zeos は結果セットを異常にキャッシュします。
これの何が問題かと言いますと、

while not EOF do
begin
...
Next;
end;

 
このようないたって普通のコードを書いただけでメモリを大量に消費します。これは BLOB フィールドを持つテーブルを読み込んだ場合に顕著で、青天井でキャッシュするためメモリ不足に陥ります。タスクマネージャでメモリ増加を観察してみてください。

回避するには Firebird の FIRST SKIP を使って部分的に結果セットを処理します。

[Firebirdでの補足事項 | 取得行数の制限、取得開始行指定:FIRST,SKIP (Firebird Wiki)]
http://firebirdwiki.jp/index.php?SELECT

…DBGrid?そんなものを使ったら死ねますよ (^^;A

DEKO
管理者
投稿数: 2691
Re: ZeosDBO で Firebird に接続する
on: 2015/10/29 04:18 Thu

Zeos で Firebird のシステムテーブル (RDB$) を操作する場合には、ClientCharSet を 'NONE' にしなければならない事があります。
例えば RDB$FUNCTIONS テーブルは以下のようになっています。

No.     名前                    型                              文字コード                      
1 RDB$FUNCTION_NAME (RDB$FUNCTION_NAME) CHAR(31) CHARACTER SET UNICODE_FSS
2 RDB$FUNCTION_TYPE (RDB$FUNCTION_TYPE) SMALLINT
3 RDB$QUERY_NAME (RDB$FIELD_NAME) CHAR(31) CHARACTER SET UNICODE_FSS
4 RDB$DESCRIPTION (RDB$DESCRIPTION) BLOB CHARACTER SET UNICODE_FSS
5 RDB$MODULE_NAME (RDB$FILE_NAME) VARCHAR(255)
6 RDB$ENTRYPOINT (RDB$EXTERNAL_NAME) CHAR(31)
7 RDB$RETURN_ARGUMENT (RDB$FIELD_POSITION) SMALLINT
8 RDB$SYSTEM_FLAG (RDB$SYSTEM_FLAG) SMALLINT

 
普通、システムテーブルのフィールドは UNICODE_FSS の VARCHAR で構成されていますが、RDB$ENTRYPOINT は 型が CHAR() で、RDB$MODULE_NAME と RDB$ENTRYPOINT の文字コードは何故か NONE です。

これの何がマズいかを ClientCharSet = UTF8 の場合で考えてみます。RDB$FUNCTION_NAME 等は文字コードが UNICODE_FSS なので、読みだした時には UNICODE_FSS -> UTF8 変換が行われて正常に値を読みだせます。問題は NONE です。NONE フィールドは ClientCharSet = UTF8 なので無理矢理 UTF-8 で読みだされます。

この時、NONE フィールドの 1 文字構成バイトは 1 なのですが、UTF8 は 4 なので、CHAR(31) のフィールドは 31 / 4 = 7 となり、7文字で切り詰められてしまいます。

おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos
おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos
おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos, おのれ Zeos

この件を回避するには、システムテーブルを操作する場合には ClientCharSet を 'NONE' に変更します。Zeos は ClientCharSet = NONE の場合、内部的な文字コード変換を行いません。そしてシステムテーブルの操作が終わったら ClientCharSet を元に戻しておきます。

この件に関してですが BLOB で読み込んだり AsBytes で読んでも結果は変わりません。フィールドにアクセスした時点で内部的な文字コード変換は終わっているからです。CAST() も考えてみましたが、確か文字コード変換のために使う事はできなかったと思います (少なくとも Firebird の全バージョンで使える方法はなかったように記憶しています)。NONE を AsBytes で読んだ時は生データ (バイナリ) を返して欲しいのですが…。

システムテーブルの (少なくとも CHAR 型の) NONE だけは ClientCharSet をデフォルトとみなして変換してはいけないのです。普通のテーブルのデータは変換しても問題ないと思いますけれど。

ページ: [1]
WP Forum Server by ForumPress | LucidCrew
バージョン: 1.7.5 ; ページロード: 0.039 sec.