GUID Insertion problem

By: Borland Staff

Abstract: Inserting GUIDs with BDE and IBX doesn't work because a tParam does not support an ftBytes datatype

Problem:
Having problem storing binary GUID values  from IBX or BDE, 
what can one do to fix it?


Solution:
This insertion problem is NOT with InterBase.  The problem is with BDE and IBX. 
Basically there are two issues.

1) the TParam object doesn't support ftBytes datatype (supported by
TField).  This makes it hard (must hack it) to set the params value with
the GUID.
2) BDE and IBX don't handle the transfer from TParam to InterBase
correctly (once you have set the param's value).

This requires a change to both IBX code and also user code to workaround the problem. 
 The necessary changes to both are explained below.

This code snippet addresses issue 1.  It is a hack to get the Params
data value set.  This snippet uses a temporary Field object to assign
the value to the Param as a variant.


Here is the code to get the GUID assigned to the Param component.

----------------------
Changes to user code:
----------------------
var
  fld: TBytesField;
  ptr: PBytearray;
  i: Integer;
  value: variant;

  ...

  qryGuid.Params.Items[0].DataType := ftBytes;
  fld := TBytesField.Create(self);
  value := VarArraycreate([0, 15], varByte);
  ptr := @InsertGuid;
  for i := 0 to 15  do
    value[i] := ptr[i];

  qryGuid.Params[0].AssignFieldValue(fld, Value);


The following changes address issue 2.  This will help you workaround
the problem with IBX.  Unfortunately, the BDE suffers from the same
problem and will have to be fixed for this to work there also.

------------------------
Changes to IBQuery.pas:
------------------------
You must add code to handle the ftBytes datatype to the SetParams method
of the TIBQuery component.

Inside the case statement for determining the datatype you must add code
to handle the ftBytes datatype.

Here is the code :

      case Params[i].DataType of
       // new code to handle ftBytes datatype
       ftBytes:
        begin
          GetMem(Buffer,Params[i].GetDataSize);
          try
            Params[i].GetData(Buffer);
            SQLParams[i].AsPointer := Buffer;
          finally
            FreeMem(Buffer);
          end;
        end;

You must define the Buffer as type pointer as well:

var
Buffer: Pointer;

----------------------
Changes to IBSQL.pas:
----------------------
In the method TIBXSQLVAR.SetAsPointer you must dereference the sqldata
field of the FXSQLVAR structure.  It just requires adding a ^ to this
existing line of code:

    Move(Value^, FXSQLVAR^.sqldata, FXSQLVAR^.sqllen);

You must add the ^ to dereference the sqldata field like such:

    Move(Value^, FXSQLVAR^.sqldata^, FXSQLVAR^.sqllen);


Server Response from: ETNASC03