Firebird 2.1 final release
Moderators: gto, cipto_kh, EgonHugeist
Hi all,
I use only simple TZConnection+TZQuery combinantion.
The problem with double TZQuery.Open necessity seems to be solved with ZeosLib building with directive {$DEFINE FOSNOMETA}. But there is comment:
//PATCH TO DO NO METADATALOADING / UNTESTED HIGH RISK
Is there someone who can tell, where it can prove and how high the risk is?
This directive is used only in one specific place - the one where is the problem:
TZAbstractRODataset.InternalInitFieldDefs:
{$IFNDEF FOSNOMETA}
Required := IsWritable(I) and (IsNullable(I) = ntNoNulls);
{$ENDIF}
The AV come in this call stack:
TZAbstractRODataset.InternalInitFieldDefs -> TZAbstractResultSetMetadata.IsWritable(1) ->
TZAbstractResultSetMetadata.LoadColumns -> TZAbstractResultSetMetadata.LoadColumn ->
TZAbstractResultSetMetadata.ReadColumnByName -> TZAbstractResultSetMetadata.GetTableColumns -> TZInterbase6DatabaseMetadata.GetColumns -> TZAbstractDatabaseMetadata.AddResultSetToCache
Here the AV come IMHO because resultSet of previous internal metadata query has no records (maybe?).
Thanks Fisa.
I use only simple TZConnection+TZQuery combinantion.
The problem with double TZQuery.Open necessity seems to be solved with ZeosLib building with directive {$DEFINE FOSNOMETA}. But there is comment:
//PATCH TO DO NO METADATALOADING / UNTESTED HIGH RISK
Is there someone who can tell, where it can prove and how high the risk is?
This directive is used only in one specific place - the one where is the problem:
TZAbstractRODataset.InternalInitFieldDefs:
{$IFNDEF FOSNOMETA}
Required := IsWritable(I) and (IsNullable(I) = ntNoNulls);
{$ENDIF}
The AV come in this call stack:
TZAbstractRODataset.InternalInitFieldDefs -> TZAbstractResultSetMetadata.IsWritable(1) ->
TZAbstractResultSetMetadata.LoadColumns -> TZAbstractResultSetMetadata.LoadColumn ->
TZAbstractResultSetMetadata.ReadColumnByName -> TZAbstractResultSetMetadata.GetTableColumns -> TZInterbase6DatabaseMetadata.GetColumns -> TZAbstractDatabaseMetadata.AddResultSetToCache
Here the AV come IMHO because resultSet of previous internal metadata query has no records (maybe?).
Thanks Fisa.
Oh, God!
I just tested the latest ZEOSLIB_TESTING_REV387 with Firebird 2.1.1 without changing anything in my code and IT WORKED!!!! Waiting for this since a looong time. If I had skills to code Zeos I could help you in this, but I am just an user.
Thanks Draconius for publishing your test results!
Thanks Zeoslib team for this GREAT piece of software!
Prometeus
I just tested the latest ZEOSLIB_TESTING_REV387 with Firebird 2.1.1 without changing anything in my code and IT WORKED!!!! Waiting for this since a looong time. If I had skills to code Zeos I could help you in this, but I am just an user.
Thanks Draconius for publishing your test results!
Thanks Zeoslib team for this GREAT piece of software!
Prometeus
I've several day on resolving that problem and, taking a look at the bug fixes doc, I read that
(CORE-1868) The server could crash in isc_dsql_free_statement().
fixed by A. Peshkoff
I think that was the problem.
If you want I can send you the changes i've made .. anyway I did a new unit (specific for Firebird 2.1)
(CORE-1868) The server could crash in isc_dsql_free_statement().
fixed by A. Peshkoff
I think that was the problem.
If you want I can send you the changes i've made .. anyway I did a new unit (specific for Firebird 2.1)
I just curious how to make a driver like that. I think there is a lot of functionality addition between FB 2.0 and 2.1, isn't it? If it covers the API changed for FB 2.1 then it should be added.
As I know for example the 2.1 version has returning clause for insert or update and it is nice if the new 2.1 protocol can handle it![Smile :)](./images/smilies/icon_smile.gif)
As I know for example the 2.1 version has returning clause for insert or update and it is nice if the new 2.1 protocol can handle it
![Smile :)](./images/smilies/icon_smile.gif)
here you can found all the dll to place in lib/firebird/windows/32bit/2.1.1.17910
Hello,
I got some problems with BLOB field using Firebird 2.1.1 . I guess this situation belongs to Firebird release, but not sure. Did someone got this problem too? The error message is something like "INVALID BLOB ID". I tried this with a restored database (filled with real data) through Firebird 2.1.1 and with a database created from zero through Firebird 2.1.1. The error appeared in both cases but not with all BLOBs.
I got some problems with BLOB field using Firebird 2.1.1 . I guess this situation belongs to Firebird release, but not sure. Did someone got this problem too? The error message is something like "INVALID BLOB ID". I tried this with a restored database (filled with real data) through Firebird 2.1.1 and with a database created from zero through Firebird 2.1.1. The error appeared in both cases but not with all BLOBs.
Last edited by Prometeus on 27.07.2008, 23:48, edited 2 times in total.
Hello,
No, this is the first time I saw this error. Until Firebird 2.04 no problems at all and with all database I have used with Firebird + Zeos. The worse part is that with the same update statement sometime the error appears but not always. And it is related with Blob fields indeed.
The statement is a simple update like 'UPDATE .... WHERE (x = y) AND (k > j)'. I am a bit busy with a project I'm involved and could not continue using version 2.1.1 in production database, so I came back to version 2.04 until this problem gets fixed. I saw at Firebird forums that there was an 'INVALID BLOB ID' bug that was fixed in previous releases but I never had got it until this 2.1.1 version.
Maybe its a Firebird bug. I'll try finding some time in order to check further this problem.
Thanks.
No, this is the first time I saw this error. Until Firebird 2.04 no problems at all and with all database I have used with Firebird + Zeos. The worse part is that with the same update statement sometime the error appears but not always. And it is related with Blob fields indeed.
The statement is a simple update like 'UPDATE .... WHERE (x = y) AND (k > j)'. I am a bit busy with a project I'm involved and could not continue using version 2.1.1 in production database, so I came back to version 2.04 until this problem gets fixed. I saw at Firebird forums that there was an 'INVALID BLOB ID' bug that was fixed in previous releases but I never had got it until this 2.1.1 version.
Maybe its a Firebird bug. I'll try finding some time in order to check further this problem.
Thanks.
Coulb be the problem you have?
Hello,
I am not sure as I detected this problem when editing a BLOB, not inserting twice as the bug you pointed out reported. I need to test it more, but there is an affirmation that changes occurred in FB 2.1 API for BLOB fields. That is a bad news if someone did not fix this in Zeos. So, I will be using previous version until this get fixed. It's a shame as Firebird 2.1 has great new features.
Thanks.
I am not sure as I detected this problem when editing a BLOB, not inserting twice as the bug you pointed out reported. I need to test it more, but there is an affirmation that changes occurred in FB 2.1 API for BLOB fields. That is a bad news if someone did not fix this in Zeos. So, I will be using previous version until this get fixed. It's a shame as Firebird 2.1 has great new features.
Thanks.
Until now I have found no problems.
I created a new test that perform a delete, an insert, an update
and a null update. Test works correctly.
procedure TZTestDbcInterbaseCase.TestUpdateBlobs;
var
Connection: IZConnection;
PreparedStatement: IZPreparedStatement;
Statement: IZStatement;
ResultSet: IZResultSet;
TextStream: TStream;
ImageStream: TMemoryStream;
TempStream: TStream;
begin
Connection := CreateDbcConnection;
Statement := Connection.CreateStatement;
CheckNotNull(Statement);
Statement.SetResultSetType(rtScrollInsensitive);
Statement.SetResultSetConcurrency(rcReadOnly);
Statement.ExecuteUpdate('DELETE FROM BLOB_VALUES WHERE B_ID='
+ IntToStr(TEST_ROW_ID));
TextStream := TStringStream.Create('ABCDEFG');
ImageStream := TMemoryStream.Create;
ImageStream.LoadFromFile('../../../database/images/zapotec.bmp');
PreparedStatement := Connection.PrepareStatement(
'INSERT INTO BLOB_VALUES (B_ID, B_TEXT, B_IMAGE) VALUES(?,?,?)');
PreparedStatement.SetInt(1, TEST_ROW_ID);
PreparedStatement.SetAsciiStream(2, TextStream);
PreparedStatement.SetBinaryStream(3, ImageStream);
CheckEquals(1, PreparedStatement.ExecuteUpdatePrepared);
ResultSet := Statement.ExecuteQuery('SELECT * FROM BLOB_VALUES'
+ ' WHERE b_id=' + IntToStr(TEST_ROW_ID));
CheckNotNull(ResultSet);
Check(ResultSet.Next);
CheckEquals(TEST_ROW_ID, ResultSet.GetIntByName('B_ID'));
TempStream := ResultSet.GetAsciiStreamByName('B_TEXT');
CheckEquals(TextStream, TempStream);
TempStream.Free;
TempStream := ResultSet.GetBinaryStreamByName('B_IMAGE');
CheckEquals(ImageStream, TempStream);
TempStream.Free;
// Update blob
TextStream.Free;
ImageStream.Free;
TextStream := TStringStream.Create('GFEDCBA');
ImageStream := TMemoryStream.Create;
ImageStream.LoadFromFile('../../../database/images/dogs.jpg');
PreparedStatement := Connection.PrepareStatement(
'UPDATE BLOB_VALUES SET B_TEXT =?,B_IMAGE=? WHERE B_ID=?');
PreparedStatement.SetInt(3, TEST_ROW_ID);
PreparedStatement.SetAsciiStream(1, TextStream);
PreparedStatement.SetBinaryStream(2, ImageStream);
CheckEquals(1, PreparedStatement.ExecuteUpdatePrepared);
ResultSet := Statement.ExecuteQuery('SELECT * FROM BLOB_VALUES'
+ ' WHERE b_id=' + IntToStr(TEST_ROW_ID));
CheckNotNull(ResultSet);
Check(ResultSet.Next);
CheckEquals(TEST_ROW_ID, ResultSet.GetIntByName('B_ID'));
TempStream := ResultSet.GetAsciiStreamByName('B_TEXT');
CheckEquals(TextStream, TempStream);
TempStream.Free;
TempStream := ResultSet.GetBinaryStreamByName('B_IMAGE');
CheckEquals(ImageStream, TempStream);
TempStream.Free;
// Update null binary blob
TextStream.Free;
TextStream := TStringStream.Create('GFEDCBA');
PreparedStatement := Connection.PrepareStatement(
'UPDATE BLOB_VALUES SET B_TEXT =?,B_IMAGE=? WHERE B_ID=?');
PreparedStatement.SetInt(3, TEST_ROW_ID);
PreparedStatement.SetAsciiStream(1, TextStream);
PreparedStatement.SetNull(2,stBinaryStream);
CheckEquals(1, PreparedStatement.ExecuteUpdatePrepared);
ResultSet := Statement.ExecuteQuery('SELECT * FROM BLOB_VALUES'
+ ' WHERE b_id=' + IntToStr(TEST_ROW_ID));
CheckNotNull(ResultSet);
Check(ResultSet.Next);
CheckEquals(TEST_ROW_ID, ResultSet.GetIntByName('B_ID'));
TempStream := ResultSet.GetAsciiStreamByName('B_TEXT');
CheckEquals(TextStream, TempStream);
CheckNull(ResultSet.GetBinaryStreamByName('B_IMAGE'));
TempStream.Free;
// Update null ascii blob
PreparedStatement := Connection.PrepareStatement(
'UPDATE BLOB_VALUES SET B_TEXT =?,B_IMAGE=? WHERE B_ID=?');
PreparedStatement.SetInt(3, TEST_ROW_ID);
PreparedStatement.SetNull(1,stAsciiStream);
PreparedStatement.SetNull(2,stBinaryStream);
CheckEquals(1, PreparedStatement.ExecuteUpdatePrepared);
ResultSet := Statement.ExecuteQuery('SELECT * FROM BLOB_VALUES'
+ ' WHERE b_id=' + IntToStr(TEST_ROW_ID));
CheckNotNull(ResultSet);
Check(ResultSet.Next);
CheckEquals(TEST_ROW_ID, ResultSet.GetIntByName('B_ID'));
CheckNull(ResultSet.GetAsciiStreamByName('B_TEXT'));
CheckNull(ResultSet.GetBinaryStreamByName('B_IMAGE'));
ResultSet.Close;
TextStream.Free;
ImageStream.Free;
Statement.Close;
end;
I created a new test that perform a delete, an insert, an update
and a null update. Test works correctly.
procedure TZTestDbcInterbaseCase.TestUpdateBlobs;
var
Connection: IZConnection;
PreparedStatement: IZPreparedStatement;
Statement: IZStatement;
ResultSet: IZResultSet;
TextStream: TStream;
ImageStream: TMemoryStream;
TempStream: TStream;
begin
Connection := CreateDbcConnection;
Statement := Connection.CreateStatement;
CheckNotNull(Statement);
Statement.SetResultSetType(rtScrollInsensitive);
Statement.SetResultSetConcurrency(rcReadOnly);
Statement.ExecuteUpdate('DELETE FROM BLOB_VALUES WHERE B_ID='
+ IntToStr(TEST_ROW_ID));
TextStream := TStringStream.Create('ABCDEFG');
ImageStream := TMemoryStream.Create;
ImageStream.LoadFromFile('../../../database/images/zapotec.bmp');
PreparedStatement := Connection.PrepareStatement(
'INSERT INTO BLOB_VALUES (B_ID, B_TEXT, B_IMAGE) VALUES(?,?,?)');
PreparedStatement.SetInt(1, TEST_ROW_ID);
PreparedStatement.SetAsciiStream(2, TextStream);
PreparedStatement.SetBinaryStream(3, ImageStream);
CheckEquals(1, PreparedStatement.ExecuteUpdatePrepared);
ResultSet := Statement.ExecuteQuery('SELECT * FROM BLOB_VALUES'
+ ' WHERE b_id=' + IntToStr(TEST_ROW_ID));
CheckNotNull(ResultSet);
Check(ResultSet.Next);
CheckEquals(TEST_ROW_ID, ResultSet.GetIntByName('B_ID'));
TempStream := ResultSet.GetAsciiStreamByName('B_TEXT');
CheckEquals(TextStream, TempStream);
TempStream.Free;
TempStream := ResultSet.GetBinaryStreamByName('B_IMAGE');
CheckEquals(ImageStream, TempStream);
TempStream.Free;
// Update blob
TextStream.Free;
ImageStream.Free;
TextStream := TStringStream.Create('GFEDCBA');
ImageStream := TMemoryStream.Create;
ImageStream.LoadFromFile('../../../database/images/dogs.jpg');
PreparedStatement := Connection.PrepareStatement(
'UPDATE BLOB_VALUES SET B_TEXT =?,B_IMAGE=? WHERE B_ID=?');
PreparedStatement.SetInt(3, TEST_ROW_ID);
PreparedStatement.SetAsciiStream(1, TextStream);
PreparedStatement.SetBinaryStream(2, ImageStream);
CheckEquals(1, PreparedStatement.ExecuteUpdatePrepared);
ResultSet := Statement.ExecuteQuery('SELECT * FROM BLOB_VALUES'
+ ' WHERE b_id=' + IntToStr(TEST_ROW_ID));
CheckNotNull(ResultSet);
Check(ResultSet.Next);
CheckEquals(TEST_ROW_ID, ResultSet.GetIntByName('B_ID'));
TempStream := ResultSet.GetAsciiStreamByName('B_TEXT');
CheckEquals(TextStream, TempStream);
TempStream.Free;
TempStream := ResultSet.GetBinaryStreamByName('B_IMAGE');
CheckEquals(ImageStream, TempStream);
TempStream.Free;
// Update null binary blob
TextStream.Free;
TextStream := TStringStream.Create('GFEDCBA');
PreparedStatement := Connection.PrepareStatement(
'UPDATE BLOB_VALUES SET B_TEXT =?,B_IMAGE=? WHERE B_ID=?');
PreparedStatement.SetInt(3, TEST_ROW_ID);
PreparedStatement.SetAsciiStream(1, TextStream);
PreparedStatement.SetNull(2,stBinaryStream);
CheckEquals(1, PreparedStatement.ExecuteUpdatePrepared);
ResultSet := Statement.ExecuteQuery('SELECT * FROM BLOB_VALUES'
+ ' WHERE b_id=' + IntToStr(TEST_ROW_ID));
CheckNotNull(ResultSet);
Check(ResultSet.Next);
CheckEquals(TEST_ROW_ID, ResultSet.GetIntByName('B_ID'));
TempStream := ResultSet.GetAsciiStreamByName('B_TEXT');
CheckEquals(TextStream, TempStream);
CheckNull(ResultSet.GetBinaryStreamByName('B_IMAGE'));
TempStream.Free;
// Update null ascii blob
PreparedStatement := Connection.PrepareStatement(
'UPDATE BLOB_VALUES SET B_TEXT =?,B_IMAGE=? WHERE B_ID=?');
PreparedStatement.SetInt(3, TEST_ROW_ID);
PreparedStatement.SetNull(1,stAsciiStream);
PreparedStatement.SetNull(2,stBinaryStream);
CheckEquals(1, PreparedStatement.ExecuteUpdatePrepared);
ResultSet := Statement.ExecuteQuery('SELECT * FROM BLOB_VALUES'
+ ' WHERE b_id=' + IntToStr(TEST_ROW_ID));
CheckNotNull(ResultSet);
Check(ResultSet.Next);
CheckEquals(TEST_ROW_ID, ResultSet.GetIntByName('B_ID'));
CheckNull(ResultSet.GetAsciiStreamByName('B_TEXT'));
CheckNull(ResultSet.GetBinaryStreamByName('B_IMAGE'));
ResultSet.Close;
TextStream.Free;
ImageStream.Free;
Statement.Close;
end;