Upgrading RODA stream read erro

hi,
i’m upgrading from
RODA 9.4.107.1363 to
RODA 9.5.111.1399

i wasn’t expection any problem but i get stream errors when i want to save data
also, i’m still depending on DA3 (this fails on startup app btw)

it crashes in
:004d067c TWriter.WriteVariant + $54
uDABinAdapter.Writer_WriteVariant(???,Variant array of Byte)
uDABinAdapter.VariantToWriter(???,Variant array of Byte,$ACB3110)
uDABinAdapter.TDABinDataStreamer.DoWriteDelta(TDADelta($A36F030) as IDADelta)
uDADataStreamer.TDADataStreamer.WriteDelta(???)
uDADataStreamer.TDADataStreamer.WriteDelta(???,TDACDSDataTable($6EEA490) as IDADataset)

calling code:
FStream := Binary.Create;
LocalAdapter.WriteDelta(FStream,LocalDataTable);
localdatatable is a TDACDSDataTable

it’s a service that updates data serverside…

// Old values
for x := 0 to (Source.LoggedFieldCount - 1) do begin
  //fWriter.WriteVariant(Source.Changes[i].OldValues[x]);
  VariantToWriter(Source.LoggedFieldTypes[x], Source.Changes[i].OldValues[x], fWriter);
end;

=>
procedure VariantToWriter(aDataType : TDADataType; const aSourceVariant : Variant; aWriter : TWriter);
var
p: pointer;
lSize: cardinal;
begin
case aDataType of
=> datatype is DatMemo
=>
procedure Writer_WriteVariant(AWriter: TWriter; AValue: Variant);
begin
{$IFNDEF FPC}
AWriter.WriteVariant(AValue);

avariant is variant array of byte…
here it crashes

Hello

Upon entering the VariantToWriter method what is the aDataType value? Also do you use FPC, Lazarus or Delphi?

datatype is DatMemo

using delphi…

in sql server the field is ‘text’
the schema table is datMemo
now i debugged the LocalAdapter.ReadDataset
and the values i see in the TDACDSDatatable are correct (the datmemo field)
but when modifying a value the value i ‘see’ in the delta is not a string, i see chinese characters
so probably something gets converted from string to another format…?

Yes, most probably incorrect String <-> WideString (or similar) conversion did happen. Could you create a testcase for this and sent it to support@ ?

Thanks, logged as bugs://81589

test case not easy…
so far i debugged it to the point that the value of the field in the dataset.post is indeed converted to a variant array of byte…

ok went through all changes between my old version and the latest one
this is the cause of the problem, in the latest a datMemo also is considered as a variant array of bytes
so is this intentional?

As a workaround you can use events of the bin1 streamer to convert such array of byte to a string:

procedure TMyForm.DataStreamerBeforeFieldValueSerialization(
  const aField: TDAField; var Value: Variant);
begin
  if aField.DataType in [datWideMemo] then
    Value := AnsiBytesToString(Value);
end;

it’s not a datwidememo?

it’s rather undoable to define that event for all binadapters that are being created on the fly (threaded)
so why the change in code?
it breaks existing code…
isn’t there a way to modify the uDaBinadapter to cope with that change?

isn’t this the procedure that should support the changed datMemo type in uDaBinAdapter?
(apparently i can’t get it to indent properly)

procedure VariantToWriter(aDataType : TDADataType; const aSourceVariant : Variant; aWriter : TWriter);
var
  p: pointer;
  lSize: cardinal;
begin
  case aDataType of
    datBlob: begin
        case VarType(aSourceVariant) of
          varEmpty:begin
              lSize := 0;
              aWriter.Write(lSize, SizeOf(lSize));
            end;
          8209:begin { 8209 is binary array }
              lSize := VarArrayHighBound(aSourceVariant, 1)-VarArrayLowBound(aSourceVariant, 1)+1;
              p := VarArrayLock(aSourceVariant);
              try
                aWriter.Write(lSize, SizeOf(lSize));
                aWriter.Write(p^, lSize);
              finally
                VarArrayUnlock(aSourceVariant);
              end;
            end;
          else begin
            DAError(True,err_InvalidVariantTypeDForBlob,[VarType(aSourceVariant)]);
          end;
        end;
      end;
    else begin
      Writer_WriteVariant(aWriter, aSourceVariant);
    end;
  end;
end;

same for VariantToWriterAsStr ?

i also don’t see how the workaround should work, since in the procedure where the event gets called:

TDABinDataStreamer.DoWriteDatasetData…
datMemo: fWriter.WriteString(VarToStr(val));

so a datMemo is already a string?

but the delta is writing a datMemo as an array which can’t be handled by TWriter…

i’ve made the following changes:

procedure VariantToWriterAsStr(aDataType : TDADataType; const aSourceVariant : Variant; aWriter : TWriter);
var
p: pointer;
s: string;
lVt: TValueType;
lSize: cardinal;
begin
case aDataType of
datBlob,datMemo: begin


procedure VariantToWriter(aDataType : TDADataType; const aSourceVariant : Variant; aWriter : TWriter);
var
p: pointer;
lSize: cardinal;
begin
case aDataType of
datBlob,datMemo: begin


function ReaderToVariant(aDataType : TDADataType; aReader : TReader): Variant;
var
p: pointer;
sze : cardinal;
begin
case aDataType of
datBlob,datMemo : begin


that seems to do the trick, can you confirm the validity of these changes?
are there any other changes needed?

ps: this is a major showstopper for us, 80% is still using TDaBinDatastreamer/DA3 so i either need to get this resolved asap or i’m forced to downgrade and thus can’t migrate to delphi RIO…

Yes, the change looks correct (especially if it works for you).

ok, but are you gonna change the stock DA units also? i’de rather not drag it along as patched unit…

Sure. I’ll log an issue to formally review the changes made and to merge them into the main codebase.

1 Like

Thanks, logged as bugs://81598