Cara menggunakan blok parameter transaksi dengan Firebird 3 OO Api

Saya telah bermain-main dengan antarmuka Firebird.pas baru yang disertakan dengan Firebird 3. Saya mengalami masalah saat mencoba menggunakan blok parameter transaksi khusus. Sepertinya saya selalu mendapatkan kesalahan "format tidak valid untuk blok parameter transaksi" jika saya menambahkan tag apa pun ke blok tersebut. Satu-satunya contoh yang pernah saya lihat tentang cara melakukan ini adalah dokumen "Using_OO_API.html" yang disertakan dengan Firebird 3. Berikut kode untuk mereproduksi kesalahan. Setiap saran dihargai!

procedure TForm1.Connect2ButtonClick(Sender: TObject);
var
  Master: IMaster;
  Status: IStatus;
  Dispatcher: IProvider;
  Util: IUtil;
  dpb: IXpbBuilder;
  tpb: IXpbBuilder;
  Attachment: IAttachment;
  Transaction: ITransaction;
  Statement: IStatement;
  ErrorString: AnsiString;
  StatusVector: NativeIntPtr;
  UseCustomTransaction: Boolean;
begin
  // Connect to Firebird 3 and use a custom transaction object.
  try
    Master := fb_get_master_interface();
    Status := Master.getStatus();

    Dispatcher := master.getDispatcher();
    Util := Master.getUtilInterface();
    dpb := Util.getXpbBuilder(status, IXpbBuilder.DPB, nil, 0);
    dpb.insertString(status, isc_dpb_user_name, 'SYSDBA');
    dpb.insertString(status, isc_dpb_password, 'sillypw');
    Attachment := Dispatcher.attachDatabase(status, PAnsiChar('myserver:testdb'), dpb.getBufferLength(status), dpb.getBuffer(status));

    UseCustomTransaction := True;
    if UseCustomTransaction then
    begin
      // Transaction := attachment.startTransaction(status, 0, nil);
      tpb := Util.getXpbBuilder(status, IXpbBuilder.TPB, nil, 0);
      tpb.insertTag(status, isc_tpb_version3);
      tpb.insertTag(status, isc_tpb_write);
      tpb.insertTag(status, isc_tpb_read_committed);
      tpb.insertTag(status, isc_tpb_nowait);
      tpb.insertTag(status, isc_tpb_rec_version);

      // This always seems to error with "invalid format for transaction parameter block"
      Transaction := attachment.startTransaction(status, tpb.getBufferLength(status), tpb.getBuffer(status));
    end
    else
    begin
      // Creating default transaction works fine. As an aside, what are the default transaction properties?
      Transaction := attachment.startTransaction(status, 0, nil);
    end;

    Statement := attachment.prepare(status, transaction, 0,
          'select rdb$relation_id relid, rdb$relation_name csname ' +
          '  from rdb$relations ' +
          '  where rdb$relation_id < ?',
             3, 0);

    Memo1.Lines.Add('Simple Plan: ' + Statement.getPlan(status, false));
    Memo1.Lines.Add('Detailed Plan: ' + Statement.getPlan(status, true));
    Memo1.Lines.Add('');

        transaction.rollback(status);

        Statement.free(status);
        attachment.detach(status);

    dpb.dispose;
    if UseCustomTransaction then
      tpb.dispose;

  except
    on E: FbException do
    begin
      SetLength(ErrorString, 2000);
      StatusVector := E.getStatus().getErrors();
      // Note that fb_interpret does not seem to appear in firebird.pas so we added it by hand.
      //   function fb_interpret(s: PAnsiChar; n: Cardinal; var statusVector: NativeIntPtr): Integer; cdecl;    external 'fbclient';
      SetLength(ErrorString, fb_interpret(PAnsiChar(ErrorString), 2000, StatusVector));
      ShowMessage(String(ErrorString));
    end
  end;

end;

person MarkF    schedule 12.05.2016    source sumber
comment
Saya sarankan Anda bertanya di milis Firebird-devel, karena saya menduga bahwa di luar pengembang inti Firebird, API ini belum banyak digunakan; Saya menduga peluang mendapatkan jawaban di sini tidak terlalu tinggi.   -  person Mark Rotteveel    schedule 12.05.2016
comment
Terima kasih Markus. Saya akan mencobanya juga.   -  person MarkF    schedule 12.05.2016


Jawaban (1)


Tampaknya ada masalah dengan IXpbBuilder (mungkin khusus untuk TPB atau InsertTag) sehingga membuat buffer parameter transaksi tidak valid. Hal ini dapat diatasi dengan membuat buffer secara manual seperti pada kode berikut:

//  var TransParamBuffer: TBytes
SetLength(TransParamBuffer, 5);
TransParamBuffer[0] := isc_tpb_version3;
TransParamBuffer[1] := isc_tpb_write;
TransParamBuffer[2] := isc_tpb_read_committed;
TransParamBuffer[3] := isc_tpb_nowait;
TransParamBuffer[4] := isc_tpb_rec_version;
Transaction := attachment.startTransaction(status, Length(TransParamBuffer), @TransParamBuffer[0]);
person MarkF    schedule 15.05.2016
comment
Bagus sekali untuk memposting solusi Anda sendiri, +1. Saya berharap lebih banyak orang melakukan hal ini daripada mengabaikan q mereka. - person MartynA; 15.05.2016