Bug #25691 TBlobField vs TVarBytesField - invalid class typecast
Submitted: 18 Jan 2007 10:22 Modified: 6 Apr 2007 10:38
Reporter: Raigedas Email Updates:
Status: Not a Bug Impact on me:
None 
Category:Connector / ODBC Severity:S3 (Non-critical)
Version:3.51.12 OS:Windows (win xp)
Assigned to: CPU Architecture:Any

[18 Jan 2007 10:22] Raigedas
Description:
I am working on two Delphi7 programs. The first one started to work correctly (the were problems when saving text entered into TDBMemo) after i have upgraded MySQL server from mysql-5.0.19-win32 to mysql-5.0.27-win32. Unfortunatelly the second one failed after upgrade... this second one stores and receives jpeg image content into LongBlob field. After upgrade i have an error when trying to receive (SELECT) that field: 
"invalid class typecast".
Program worked with every older mysql version (last checked was 5.0.19) without problems... After some investigation, i have found out that my code treated the field on old mysql as TBlobField, and it treats now it as TVarBytesField on new mysql. And actually i treat this change as a bug, because good/working programs started to fail.

my Delphi code that throws error:

procedure expADOQueryGetFieldAsBlob(fieldname: ShortString; var stream : TMemoryStream); stdcall;
var blob: TStream;
begin
//showmessage(expADOQuery.FieldByName(fieldname).ClassName); // just to check field classname
blob := expADOQuery.CreateBlobStream(expADOQuery.FieldByName(fieldname), bmRead); // there i get an error
try
  blob.Seek(0, soFromBeginning);
  try
  stream.CopyFrom(blob, blob.Size);
  except
    end;
finally
  blob.Free;
  end;
end;

How to repeat:

1. create table with LongBlob field
2. insert data with content of jpeg image
3. use this code to retrieve data:

procedure expADOQueryGetFieldAsBlob(fieldname: ShortString; var stream : TMemoryStream); stdcall;
var blob: TStream;
begin
//showmessage(expADOQuery.FieldByName(fieldname).ClassName); // just to check field classname
blob := expADOQuery.CreateBlobStream(expADOQuery.FieldByName(fieldname), bmRead); // there i get an error
try
  blob.Seek(0, soFromBeginning);
  try
  stream.CopyFrom(blob, blob.Size);
  except
    end;
finally
  blob.Free;
  end;
end;
[18 Jan 2007 13:37] Valeriy Kravchuk
Thank you for a problem report. Please, send exact CREATE TABLE statement used. How large is your typical JPEG image, in bytes? What connector (Connector/ODBC, Connector/Net, etc) do you use in your application?
[18 Jan 2007 14:13] Raigedas
connector?
i use ODBC 3.51.12. And i use ADO components (TADOConnection, TADOQuery) in Delphi to connect to database.

size? 
it is not bigger than 500 KB. actually it is just a small preview. and you know, i use LongBlob which is capable to store up to 4GiB!

table?
ok, i can give an exactly the same create statement that i use:
CREATE TABLE tfd_otherimage (
  cfd_id bigint not null auto_increment,
  cwidth int(4),
  cheight int(4),
  cpreview longblob,
  cpreviewwidth int(2),
  cpreviewheight int(2),
  cext char(30),
  ccd_id bigint,
  cfile_id bigint,
  primary key (cfd_id)
);
[6 Apr 2007 10:38] Tonci Grgin
Hi and sorry for the delay.

I think the problem lies in copying between streams, you should look for help on that elsewhere. I tested BLOB stream creation and seek and found no problems:
 - MySQL server 5.0.38BK on WinXP SP2 Pro localhost
 - MyODBC 3.51.14GA
 - Delphi 6

Test case:
var
  stream: TStream;
  blob: TStream;
  BlobFld: TField;
begin
  ADOConnection1.Open;
  if ADOConnection1.Connected then
  begin
    ADOQuery1.Open;
    BlobFld := ADOQuery1cpreview;
    blob := ADOQuery1.CreateBlobStream(BlobFld, bmRead);
    try
      blob.Seek(0, soFromBeginning);
      ShowMessage(IntToStr(blob.Size)); //Shows correct BLOB size
      ShowMessage(IntToStr(blob.Position)); // Shows 0 correctly
    finally
      blob.Free;
      ADOQuery1.Close;
      ADOConnection1.Close;
    end;
  end;