Page 1 of 2

[patch_done] Firebird 2.1 driver

Posted: 17.11.2008, 19:16
by seawolf
Starting from version 2.1, Firebird deprecate function isc_interprete to fb_interpret (which is claimed to be more reliable)

In order to use that driver correctly it necessary to do some changes:

Unit ZDbcInterbase6;

TZInterbase6Driver = class(TZAbstractDriver)
private
FInterbase6PlainDriver: IZInterbase6PlainDriver;
FInterbase5PlainDriver: IZInterbase5PlainDriver;
FFirebird10PlainDriver: IZFirebird10PlainDriver;
FFirebird15PlainDriver: IZFirebird15PlainDriver;
FFirebird20PlainDriver: IZFirebird20PlainDriver;
FFirebird21PlainDriver: IZFirebird21PlainDriver;
// embedded drivers
FFirebirdD15PlainDriver: IZFirebird15PlainDriver;
FFirebirdD20PlainDriver: IZFirebird20PlainDriver;
FFirebirdD21PlainDriver: IZFirebird21PlainDriver;

constructor TZInterbase6Driver.Create;
begin
FInterbase6PlainDriver := TZInterbase6PlainDriver.Create;
FInterbase5PlainDriver := TZInterbase5PlainDriver.Create;
FFirebird10PlainDriver := TZFirebird10PlainDriver.Create;
FFirebird15PlainDriver := TZFirebird15PlainDriver.Create;
FFirebird20PlainDriver := TZFirebird20PlainDriver.Create;
FFirebird21PlainDriver := TZFirebird21PlainDriver.Create;

// embedded drivers
FFirebirdD15PlainDriver := TZFirebirdD15PlainDriver.Create;
FFirebirdD20PlainDriver := TZFirebirdD20PlainDriver.Create;
FFirebirdD21PlainDriver := TZFirebirdD21PlainDriver.Create;
end;

function TZInterbase6Driver.GetPlainDriver(
const Url: string): IZInterbasePlainDriver;
var
Protocol: string;
begin
Protocol := ResolveConnectionProtocol(Url, GetSupportedProtocols);

if Protocol = FInterbase5PlainDriver.GetProtocol then
Result := FInterbase5PlainDriver
else if Protocol = FInterbase6PlainDriver.GetProtocol then
Result := FInterbase6PlainDriver
else if Protocol = FFirebird10PlainDriver.GetProtocol then
Result := FFirebird10PlainDriver
else if Protocol = FFirebird15PlainDriver.GetProtocol then
Result := FFirebird15PlainDriver
else if Protocol = FFirebird20PlainDriver.GetProtocol then
Result := FFirebird20PlainDriver
else if Protocol = FFirebird21PlainDriver.GetProtocol then
Result := FFirebird21PlainDriver
// embedded drivers
else if Protocol = FFirebirdD15PlainDriver.GetProtocol then
Result := FFirebirdD15PlainDriver
else if Protocol = FFirebirdD20PlainDriver.GetProtocol then
Result := FFirebirdD20PlainDriver
else if Protocol = FFirebirdD21PlainDriver.GetProtocol then
Result := FFirebirdD21PlainDriver

// Generic driver
else Result := FInterbase6PlainDriver;
Result.Initialize;
end;

function TZInterbase6Driver.GetSupportedProtocols: TStringDynArray;
begin
SetLength(Result, 9);
Result[0] := 'interbase-5';
Result[1] := 'interbase-6';
Result[2] := 'firebird-1.0';
Result[3] := 'firebird-1.5';
Result[4] := 'firebird-2.0';
Result[5] := 'firebird-2.1';
// embedded drivers
Result[6] := 'firebirdd-1.5';
Result[7] := 'firebirdd-2.0';
Result[8] := 'firebirdd-2.1';
end;

Inside the attached zip you found 2 files:
ZplainDriver21.pas is the new driver file
ZPlainFirebirdDriver.pas I added the IZFirebird21PlainDriver,IZFirebirdD21PlainDriver classes

Moreover it is necessary add

ZPlainFirebird21 in '..\..\src\plain\ZPlainFirebird21.pas';

on all Zplain.dpk

Posted: 18.11.2008, 23:07
by mdaems
Thanks Seawolf!

Committed to Testing branch (SVN rev 519).

I'm checking with Michael if we should also add this one to 6.6.X.

Mark

Posted: 09.04.2009, 15:06
by SlavoF
ZEOSLIB_TESTING_REV617.zip
D2009
Firebird 2.1

ZPlainFirebirdDriver.pas:
function TZFirebird21PlainDriver.isc_interprete(buffer: PAnsiChar;
status_vector: PPISC_STATUS): ISC_STATUS;
var
bufsize : integer;
begin
bufsize := 0;
Result := FIREBIRD_API.fb_interpret(buffer, bufsize, status_vector);
end;

Result is always = 0

in project:
ZConnection.Connected is true , also DB file not exists

if take isc_interprete from TZFirebirdBaseDriver:

begin
Inherited;
// bufsize := 0;
// Result := FIREBIRD_API.fb_interpret(buffer, bufsize, status_vector);
end;

all is OK

Posted: 14.04.2009, 21:51
by mdaems
Seawolf?

Do you have trouble with this version? My test suite runs with this testing branch version without trouble.

Mark

Posted: 15.04.2009, 21:57
by seawolf
Yes, I have the same problem. I'm currently debugging a test application which should raise an error. Unfortunately fb_interpret does not report any error. If I change this

function TZFirebird21PlainDriver.isc_interprete(buffer: PAnsiChar;
status_vector: PPISC_STATUS): ISC_STATUS;
var
bufsize : integer;
begin
bufsize := 0;
Result := FIREBIRD_API.fb_interpret(buffer, bufsize, status_vector);
end;

to this

function TZFirebird21PlainDriver.isc_interprete(buffer: PAnsiChar;
status_vector: PPISC_STATUS): ISC_STATUS;
begin
Result := FIREBIRD_API.isc_interprete(bufsize, status_vector);
end;

All works fine. Anyway as soon as possible i send you an update to fix that problem

Posted: 15.04.2009, 22:38
by mdaems
So this means there's something wrong with the fb_interprete call or it should be used in an other way?

Mark

Posted: 18.04.2009, 14:28
by seawolf
I've tried with fb 2.1.1 and 2.1.2 but fb_interpret function seems not work as expected. So, for the moment, i suggest you to change that function as yuo can see below. I wrote to the Firebird dev team in order to understand why isc_interprete works as expected and fb_interpret no. As soon as I will have a response I send yo a patch.

function TZFirebird21PlainDriver.isc_interprete(buffer: PAnsiChar;
status_vector: PPISC_STATUS): ISC_STATUS;
//var
//bufsize : integer;
begin
inherited;
//bufsize := 0;
//Result := FIREBIRD_API.fb_interpret(buffer, bufsize, status_vector);
end;

Posted: 18.04.2009, 15:50
by seawolf
Please forget previous post. You have to change

ZdbcInterbase6Utils

procedure CheckInterbase6Error(PlainDriver: IZInterbasePlainDriver;
StatusVector: TARRAY_ISC_STATUS; LoggingCategory: TZLoggingCategory = lcOther;
SQL: string = '');
var
Msg: array[0..1024] of AnsiChar;
PStatusVector: PISC_STATUS;
ErrorMessage, ErrorSqlMessage: string;
ErrorCode: LongInt;
begin
if (StatusVector[0] = 1) and (StatusVector[1] > 0) then
begin
ErrorMessage := '';
PStatusVector := @StatusVector;
PlainDriver.isc_interprete(Msg, @PStatusVector);
// while PlainDriver.isc_interprete(Msg, @PStatusVector) > 0 do
// ErrorMessage := ErrorMessage + ' ' + StrPas(Msg);


ErrorCode := PlainDriver.isc_sqlcode(@StatusVector);
PlainDriver.isc_sql_interprete(ErrorCode, Msg, 1024);
ErrorMessage := StrPas(Msg);
// ErrorSqlMessage := StrPas(Msg);


{$IFDEF INTERBASE_EXTENDED_MESSAGES}
if SQL <> '' then
SQL := Format(' The SQL: %s; ', [SQL]);
{$ENDIF}

if ErrorMessage <> '' then
begin
DriverManager.LogError(LoggingCategory, PlainDriver.GetProtocol,
ErrorMessage, ErrorCode, ErrorSqlMessage + SQL);

{$IFDEF INTERBASE_EXTENDED_MESSAGES}
raise EZSQLException.CreateWithCode(ErrorCode,
Format('SQL Error: %s. Error Code: %d. %s',
[ErrorMessage, ErrorCode, ErrorSqlMessage]) + SQL);
{$ELSE}
raise EZSQLException.CreateWithCode(ErrorCode,
Format('SQL Error: %s. Error Code: %d. %s',
[ErrorMessage, ErrorCode, ErrorSqlMessage]));
{$ENDIF}
end;
end;
end;

isc_interprete returns StatusVector which is parsed by isc_sqlcode and isc_sql_interprete

so Msg is always equal to ErrorSqlMessage because the error message is contained in StatusVector

Posted: 19.04.2009, 20:01
by mdaems
Why call
PlainDriver.isc_interprete(Msg, @PStatusVector);
AND
ErrorCode := PlainDriver.isc_sqlcode(@StatusVector); PlainDriver.isc_sql_interprete(ErrorCode, Msg, 1024);
?
When reading API docs you should need only one of them, with the second version prefered when using the dsql interface (as I believe we do)

Mark

Posted: 24.04.2009, 14:04
by SlavoF
Mark, seawolf
Thanks
but I still waiting
changes in ZdbcInterbase6Utils don't help me
by me FB 2.1 work so far better with 2.0 driver

Posted: 24.04.2009, 14:17
by seawolf
Sorry for the mess. Some days ago I wrote to the Firebird-support team and this is the response

Taking a look at this word

Because you passed zero bufsize into fb_interpret. It just did nothing.

function TZFirebird21PlainDriver.isc_interprete(buffer: PAnsiChar;
status_vector: PPISC_STATUS): ISC_STATUS;
var
bufsize : integer;
begin
// bufsize := 0; <--- remove or comment it
Result := FIREBIRD_API.fb_interpret(buffer, bufsize, status_vector);
end;

Posted: 24.04.2009, 14:31
by SlavoF
hmm... :roll:
why not initialized ? then too equals 0 , or not ?
and what is expected to be the value of bufsize ?

result = "Out of memory"

Posted: 24.04.2009, 18:43
by seawolf
First of all is a local variable, but I think it is possible to set it to 255 (but in this case message will be truncated after 255 chars)

Bufsize is the size of the output buffer

Posted: 27.04.2009, 08:37
by SlavoF
yes, now it's works correctly
:thanks:

Posted: 03.05.2009, 23:53
by mdaems
Hi,

Seems like setting it to 1024 makes more sense because that's the buffersize definede in CheckInterbase6Error. Or is there some fpc call that can find this buffer input parameter length automatically?

Mark