Re: [firebird-support] Re: FB3 returning clause and new API

2016-09-15 Thread Martin Schreiber mse00...@gmail.com [firebird-support]
On Thursday 15 September 2016 15:06:58 'Mark Rotteveel' m...@lawinegevaar.nl 
[firebird-support] wrote:
> You either need to generate the necessary metadata yourself, but then you
> either have to guess, or have the user provide the type. You can't use
> openCursor as insert ... returning doesn't have a cursor; just like an
> executable procedure it has a single result that is returned on execute.
>
Does calling IAttachment.prepare() in order to get the output message metadata 
produce a performance penalty, expecially an additional server roundtrip? I 
assume so. The format of the received data must be known in FB-client library 
when the data arrives, so it should be possible to provide an 
IMessageMetadata after execute().
A very comfortable solution would be when openCursor() would work for all 
statement types because of the problem that it is not known if openCursor() 
or execute() must be called before parsing the SQL statement in user code or 
preparing the statement.
It seems that calling openCursor() with
"
insert into TABLE1 (STR1) values ('aabbccdd') returning PK
"
actually returns a valid IMessageMetadata by IResultSet.getMetadata(). What 
apparentely not works is fetchNext()...

Martin


Re: [firebird-support] Re: FB3 returning clause and new API

2016-09-15 Thread Martin Schreiber mse00...@gmail.com [firebird-support]
On Thursday 15 September 2016 12:25:31 Norbert Saint Georges n...@tetrasys.eu 
[firebird-support] wrote:
>
> below, a bit dirty but functional code in codetyphon, reading the
> buffer is RS
>
Thanks, but do I read the code correct, that you also use 
IAttachment.prepare() in order to get the messagemetadata? Does this cause an 
additional server roundtrip?
With IAttachment.execute() there is no messagemetadata available and with the 
statement
"
insert into TABLE1 (STR1) values ('aabbccdd') returning PK
"
IAttachment.openCursor() seems not to work.

Martin


[firebird-support] Re: FB3 returning clause and new API

2016-09-15 Thread Norbert Saint Georges n...@tetrasys.eu [firebird-support]
Martin Schreiber mse00...@gmail.com [firebird-support] a écrit :
> On Thursday 15 September 2016 11:09:43 Dimitry Sibiryakov s...@ibphoenix.com 
> [firebird-support] wrote:
>> 15.09.2016 11:14, Martin Schreiber mse00...@gmail.com [firebird-support]  
>> wrote:
>>> What if one wants to use
>>> IAttachment.execute() where no IStatement is available?
>> 
>>(S)he must provide IMetadata built with builder.
>
> I am implementing a Firebird 3 connection component for MSEide+MSEgui (a Free 
> Pascal toolkit) so I don't know the returned data of the statements in the 
> first place.
> In case of input params I implemented an own IMessageMetadata derivate which 
> uses the type information of TParam in order to setup the metadata. In case 
> of "returning" the data type is unknown without parsing the SQL statement.
> It seems I always need to prepare the statement first?
>
> Martin
below, a bit dirty but functional code in codetyphon, reading the 
buffer is RS

unit UserData;
{$mode delphi}
{$H+}

interface

uses
  Classes, SysUtils, lNet, Firebird, DateUtils,
  Tzutil, stdctrls, fgl,
  TgzIo,
  TzDeflate,
  TzCompres,
  FBRecordU;

type
  FBSockException = class(Exception);
  TByteArray = array of byte;
  TListoutBuffer = array of TByteArray;
  buf_byte_ptr = ^buf_byte;
  buf_byte = array[0..4095] of byte;
  buf_AnsiChar = array of AnsiChar;
  buf_AnsiCharptr = ^buf_AnsiChar;

  InMessage = record
n: SmallInt;
nNull: WordBool;
end;
  OutMessage = record
relationId: SmallInt;
relationIdNull: WordBool;
relationName: array[0..93] of AnsiChar;
relationNameNull: WordBool;
  end;

  TDataEvent = procedure (Data: AnsiString) of object;

TServerObjectWorkerThread = class;
TThrdExeProc  = procedure of object;
TServerObjectWorkerThread = class(TThread)
protected
FName : String;
FStarted  : Boolean;
FThrdExeProc  : TThrdExeProc;
public
procedure Execute; override;
property  Name: String  read  FName
write FName;
property  Started : Boolean read  FStarted
write FStarted;
property  ThrdExeProc : TThrdExeProcread  FThrdExeProc
write FThrdExeProc;
end;


  TUserData = class
private
  _userdata : string;
  _asocket  : TLSocket;
  _fmemo: TMemo;
  st : IStatus;
  master : IMaster ;
  util : IUtil;
  dpb : IXpbBuilder;
  prov : IProvider;
  att : IAttachment;
  tra : ITransaction;
  stmt: IStatement;
  rs: IResultSet;
  inMetadata, outMetadata: IMessageMetadata;
  inBuffer: InMessage;
outBuffer: array of byte;
outBufferptr: ^TByteArray;
strm: TMemoryStream;
  procedure writeuserdata(fdata:String);
  procedure PrintError(s : IStatus; fmessage:string);
private
  procedure sendfirstbuffer;
  procedure senddata(fdata:ansistring);
  procedure sendSize(fint:uint);
  Procedure SendCompressedString(str: ansistring);
  Procedure SendCompressedBytes(str: tBytesStream);
  Procedure SendRecord(str : ansiString);
  Function CompressToString(str: ansistring):ansistring;
  function concatbyte(a, b: array of byte):TByteArray;
public
  constructor create(fsocket:TLSocket;amemo:tmemo);
  destructor destroy; override;
  property  userdata : string read _userdata write writeuserdata;
  const
 RAW_WBITS = 15;

  end;

implementation


{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
* * *}
procedure TServerObjectWorkerThread.Execute;

begin

end;


constructor TUserData.create(fsocket:TLSocket; amemo:TMemo);
begin
_asocket := fsocket;
_asocket.SetState(ssNoDelay,true);
_fmemo   := amemo;
_userdata := '';
strm := TMemoryStream.create;
end;
destructor TUserData.destroy;
begin
   if att<> nil then
att.detach(st);
att := nil;
   if dpb <> nil then
dpb.dispose;
dpb := nil;
   if prov <> nil then
prov.release;
   prov := nil;
   if st <> nil then begin
st.dispose();
   end;
   st := nil;
   if util<> nil then
   util := nil;
   if master<>nil then
   master := nil;
   _userdata:='';
   if inMetadata <> nil then
   inMetadata := nil;
   if outMetadata <> nil then
   outMetadata := nil;
   _asocket.UserData:=nil;
   if strm<> nil then
   freeandnil(strm);
   inherited destroy;
end;

procedure TUserdata.PrintError(s : IStatus; fmessage:string);
var
maxMessage : Integer;
outMessage : PAnsiChar;
begin
maxMessage := 256;
outMessage := StrAlloc(maxMessage);
util.formatStatus(outMessage, maxMessage, s);
_fmemo.Append(concat(outMessage,#13#10,fmessage));