วิธีใช้บล็อกพารามิเตอร์ธุรกรรมกับ Firebird 3 OO Api

ฉันกำลังเล่นกับอินเทอร์เฟซ Firebird.pas ใหม่ที่มาพร้อมกับ Firebird 3 ฉันประสบปัญหาเมื่อฉันพยายามใช้บล็อกพารามิเตอร์ธุรกรรมที่กำหนดเอง ดูเหมือนว่าฉันจะได้รับข้อผิดพลาด "รูปแบบที่ไม่ถูกต้องสำหรับบล็อกพารามิเตอร์ธุรกรรม" เสมอ หากฉันเพิ่มแท็กใดๆ ลงในบล็อก ตัวอย่างเดียวที่ฉันได้เห็นเกี่ยวกับวิธีการทำเช่นนี้คือเอกสาร "Using_OO_API.html" ที่มาพร้อมกับ Firebird 3 นี่คือโค้ดสำหรับสร้างข้อผิดพลาดอีกครั้ง ข้อเสนอแนะใด ๆ ชื่นชม!

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 แหล่งที่มา
comment
ฉันขอแนะนำให้คุณถามรายชื่อผู้รับจดหมายของ Firebird เนื่องจากฉันสงสัยว่าภายนอกนักพัฒนาหลักของ Firebird API นี้ยังไม่ได้เห็นประโยชน์มากนัก ฉันสงสัยว่าโอกาสที่จะตอบที่นี่ไม่สูงมาก   -  person Mark Rotteveel    schedule 12.05.2016
comment
ขอบคุณมาร์ค ฉันจะลองดูเหมือนกัน   -  person MarkF    schedule 12.05.2016


คำตอบ (1)


ดูเหมือนจะมีปัญหากับ IXpbBuilder (อาจเฉพาะเจาะจงกับ TPB หรือ InsertTag) ซึ่งทำให้สร้างบัฟเฟอร์พารามิเตอร์ธุรกรรมที่ไม่ถูกต้อง ซึ่งสามารถแก้ไขได้ด้วยการสร้างบัฟเฟอร์ด้วยมือตามโค้ดต่อไปนี้:

//  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
ทำได้ดีมากสำหรับการโพสต์โซลูชันของคุณเอง +1 ฉันหวังว่าผู้คนจำนวนมากจะทำเช่นนี้แทนที่จะละทิ้งคำถามของพวกเขา - person MartynA; 15.05.2016