Board index » delphi » invalid variant type copying streamed contents of TADOStream into a Buffer

invalid variant type copying streamed contents of TADOStream into a Buffer

I am using D7 and TBetterADODataSet [wraps ADO26_TLB]
I want to get the stream into a buffer so I can compress and send it [using
a TByteDynArray] in a SOAP call.
I am currently able to do this with kbmTables [standard MemoryStreams] per
the bottom code snippet,
but I do not know the syntax to get a TADOStream into the buffer.

Please advise.

TYIA,

Robert Baker

*********** Calling Routine ************
procedure TfrmMapping.Button4Click(Sender: TObject);
var
  ADOStream: _Stream;
  OutStream : TMemoryStream;
  MyDataSet : TBetterADODataSet;
begin
  ADOStream := CoStream.Create;
  begin
      MyDataSet := BetterADODataSet.TBetterADODataSet.Create(nil);
      MyDataSet.ConnectionString := 'Provider=SQLOLEDB.1;Password=;Persist
Security Info=True;User ID=;Initial....
      MyDataSet.Commandtext := 'SELECT * FROM Test';
      MyDataSet.Open;
      OutStream := TMemoryStream.Create;
    try
      MyDataSet.SaveToADOStream(ADOStream, pfXML{pfADTG});
      ADOStream.Position:=0;
      CompressADOStream(ADOStream, OutStream);
    finally
      ADOStream := Nil;
      OutStream.Free;
    end;
    DataSource3.DataSet := MyDataSet;
    MyDataSet.Open;
  end;
end;

  procedure CompressADOStream(ADOStream: _Stream; outStream: TMemoryStream);
  var InpBuf,OutBuf: Pointer;
  var InpBytes,OutBytes: integer;
    str: string;
  begin
    InpBuf := nil;
    OutBuf := nil;
    try
      GetMem(InpBuf, ADOStream.size);
      ADOStream.Position := 0;
      InpBytes := ADOStream.Read(OleVariant(InpBuf^));
      CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
      outStream.Write(OutBuf^,OutBytes);
    finally
      if InpBuf <> nil then FreeMem(InpBuf);
      if OutBuf <> nil then FreeMem(OutBuf);
    end;
  end;

*********** This Works ***********
procedure CompressStream(inpStream,outStream: TStream);
  var InpBuf,OutBuf: Pointer;
  var InpBytes,OutBytes: integer;
  begin
    InpBuf := nil;
    OutBuf := nil;
    try
      GetMem(InpBuf,inpStream.size);
      inpStream.Position := 0;
      InpBytes := inpStream.Read(InpBuf^,inpStream.size);
      CompressBuf(InpBuf,InpBytes,OutBuf,OutBytes);
      outStream.Write(OutBuf^,OutBytes);
    finally
      if InpBuf <> nil then FreeMem(InpBuf);
      if OutBuf <> nil then FreeMem(OutBuf);
    end;
  end;

Robert Baker

 

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Here's an example that supports ADO versions that do not have native
streaming built in:

function RecordsetToMemoryStream(const ARecordset: _Recordset):
TMemoryStream;
var
  vStreamAdapter : TStreamAdapter;
begin
  Result := TMemoryStream.Create;
  vStreamAdapter := TStreamAdapter.Create(Result);
  try
    if not (CoMarshalInterface(
      (vStreamAdapter as IStream),
      IID__Recordset,
      ARecordset,
      MSHCTX_LOCAL,
      nil,
      MSHLFLAGS_NORMAL
    ) = S_OK) then
    begin
      raise Exception.CreateFmt('Unable to marshal recordset. %s.',
[SysErrorMessage(GetLastError)]);
    end;
  finally
    vStreamAdapter := nil;
  end;
end;

function MemoryStreamToRecordset(const AMemoryStream: TMemoryStream):
_Recordset;
var
  vStreamAdapter : TStreamAdapter;
begin
  Result := CoRecordset.Create;
  vStreamAdapter := TStreamAdapter.Create(AMemoryStream);
  try
    if not CoUnMarshalInterface((vStreamAdapter as IStream), IID__Recordset,
Result) = S_OK then
    begin
      raise Exception.CreateFmt('Unable to unmarshal recordset. %s.',
[SysErrorMessage(GetLastError)]);
    end;
  finally
    vStreamAdapter := nil;
  end;
end;

Quote
"Robert Baker" <zxy...@hotmail.com> wrote in message

news:3e6297b0$1@newsgroups.borland.com...
Quote
> I am using D7 and TBetterADODataSet [wraps ADO26_TLB]
> I want to get the stream into a buffer so I can compress and send it
[using
> a TByteDynArray] in a SOAP call.
> I am currently able to do this with kbmTables [standard MemoryStreams] per
> the bottom code snippet,
> but I do not know the syntax to get a TADOStream into the buffer.

> Please advise.

> TYIA,

> Robert Baker

> *********** Calling Routine ************
> procedure TfrmMapping.Button4Click(Sender: TObject);
> var
>   ADOStream: _Stream;
>   OutStream : TMemoryStream;
>   MyDataSet : TBetterADODataSet;
> begin
>   ADOStream := CoStream.Create;
>   begin
>       MyDataSet := BetterADODataSet.TBetterADODataSet.Create(nil);
>       MyDataSet.ConnectionString := 'Provider=SQLOLEDB.1;Password=;Persist
> Security Info=True;User ID=;Initial....
>       MyDataSet.Commandtext := 'SELECT * FROM Test';
>       MyDataSet.Open;
>       OutStream := TMemoryStream.Create;
>     try
>       MyDataSet.SaveToADOStream(ADOStream, pfXML{pfADTG});
>       ADOStream.Position:=0;
>       CompressADOStream(ADOStream, OutStream);
>     finally
>       ADOStream := Nil;
>       OutStream.Free;
>     end;
>     DataSource3.DataSet := MyDataSet;
>     MyDataSet.Open;
>   end;
> end;

>   procedure CompressADOStream(ADOStream: _Stream; outStream:
TMemoryStream);
>   var InpBuf,OutBuf: Pointer;
>   var InpBytes,OutBytes: integer;
>     str: string;
>   begin
>     InpBuf := nil;
>     OutBuf := nil;
>     try
>       GetMem(InpBuf, ADOStream.size);
>       ADOStream.Position := 0;
>       InpBytes := ADOStream.Read(OleVariant(InpBuf^));
>       CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
>       outStream.Write(OutBuf^,OutBytes);
>     finally
>       if InpBuf <> nil then FreeMem(InpBuf);
>       if OutBuf <> nil then FreeMem(OutBuf);
>     end;
>   end;

> *********** This Works ***********
> procedure CompressStream(inpStream,outStream: TStream);
>   var InpBuf,OutBuf: Pointer;
>   var InpBytes,OutBytes: integer;
>   begin
>     InpBuf := nil;
>     OutBuf := nil;
>     try
>       GetMem(InpBuf,inpStream.size);
>       inpStream.Position := 0;
>       InpBytes := inpStream.Read(InpBuf^,inpStream.size);
>       CompressBuf(InpBuf,InpBytes,OutBuf,OutBytes);
>       outStream.Write(OutBuf^,OutBytes);
>     finally
>       if InpBuf <> nil then FreeMem(InpBuf);
>       if OutBuf <> nil then FreeMem(OutBuf);
>     end;
>   end;

> Robert Baker

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Anyone know how to get the ADOStream into a buffer
Thanks,
Robert Baker

  procedure CompressADOStream(ADOStream: _Stream; outStream: TMemoryStream);
  var InpBuf,OutBuf: Pointer;
  var InpBytes,OutBytes: integer;
    str: string;
  begin
    InpBuf := nil;
    OutBuf := nil;
    try
      GetMem(InpBuf, ADOStream.size);
      ADOStream.Position := 0;

   ********** Problem statement below *************
      InpBytes := ADOStream.Read(OleVariant(InpBuf^));
   *** ******* I get Invalid Variant Type here ***************

      CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
      outStream.Write(OutBuf^,OutBytes);
    finally
      if InpBuf <> nil then FreeMem(InpBuf);
      if OutBuf <> nil then FreeMem(OutBuf);
    end;
  end;

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Try the following:

procedure TForm1.Button1Click(Sender: TObject);

  function OleVariantToMemoryStream(AOleVariant: OleVariant): TMemoryStream;
  var
   vPByteArray : PByteArray;
   vSize       : Integer;
  begin
   Result := nil;
   if VarIsArray(AOleVariant) then
   begin
     vSize := VarArrayHighBound(AOleVariant, 1) -
VarArrayLowBound(AOleVariant, 1) +1;
     vPByteArray := VarArrayLock(AOleVariant);
     Result := TMemoryStream.Create;
     try
       Result.Size := vSize;
       Result.WriteBuffer(vPByteArray^, vSize);
       Result.Position := 0;
     finally
       VarArrayUnlock(AOleVariant);
     end;
   end;
  end;

var
  vConnectionString    : string;
  vVariantArrayOfBytes : OleVariant;
  vConnection          : _Connection;
  vRecordset           : _Recordset;
  vStream              : _Stream;
  vMemoryStream        : TMemoryStream;
  InpBuf, OutBuf       : Pointer;
  InpBytes, OutBytes   : Integer;
begin
  { ConnectionString }
  vConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\Program Files\Microsoft
Office\Office10\Samples\Northwind.mdb;Persist Security Info=False';
  { Create our _Connection object. }
  vConnection := CoConnection.Create;
  vConnection.ConnectionString := vConnectionString;
  { Open the _Connection. }
  vConnection.Open(vConnectionString, '', '', adConnectUnspecified);
  { Grab the data and stuff it into a _Recordset. }
  vRecordset := vConnection.Execute('SELECT * FROM EMPLOYEES', EmptyParam,
adCmdText);
  { Do we have any data? }
  if not vRecordset.EOF then
  begin
    { Create the _Stream. }
    vStream := CoStream.Create;
    { Save the recordset to a _Stream using the ADTG format. }
    vRecordset.Save(OleVariant(vStream), adPersistADTG);
    { Get the data into a variant array of bytes. }
    vVariantArrayOfBytes := vStream.Read(adReadAll);
    { Convert the variant array of bytes into a memory stream. }
    vMemoryStream := OleVariantToMemoryStream(vVariantArrayOfBytes);
    if vMemoryStream <> nil then
    begin
      try
        { Compress the memory. }
        CompressBuf(vMemoryStream.Memory, vMemoryStream.Size, OutBuf,
OutBytes);
        if (OutBuf <> nil) and (OutBytes > 0) then
        begin
          { Clear the memory stream. }
          vMemoryStream.Clear;
          { Write the new data. }
          vMemoryStream.Write(OutBuf, OutBytes);
          { Do something with the new data... }
          // DoSomething(vMemoryStream);
        end;
      finally
        vMemoryStream.Free;
      end;
    end;
  end;
end;

Regards,

Michael Cessna

Quote
"Robert Baker" <zxy...@hotmail.com> wrote in message

news:3e646581$1@newsgroups.borland.com...
Quote
> Anyone know how to get the ADOStream into a buffer
> Thanks,
> Robert Baker

>   procedure CompressADOStream(ADOStream: _Stream; outStream:
TMemoryStream);
>   var InpBuf,OutBuf: Pointer;
>   var InpBytes,OutBytes: integer;
>     str: string;
>   begin
>     InpBuf := nil;
>     OutBuf := nil;
>     try
>       GetMem(InpBuf, ADOStream.size);
>       ADOStream.Position := 0;

>    ********** Problem statement below *************
>       InpBytes := ADOStream.Read(OleVariant(InpBuf^));
>    *** ******* I get Invalid Variant Type here ***************

>       CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
>       outStream.Write(OutBuf^,OutBytes);
>     finally
>       if InpBuf <> nil then FreeMem(InpBuf);
>       if OutBuf <> nil then FreeMem(OutBuf);
>     end;
>   end;

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Ok, here's a much better way, using the TStreamAdapter:

procedure TForm1.Button1Click(Sender: TObject);
var
  vConnectionString : string;
  vConnection       : _Connection;
  vRecordset        : _Recordset;
  vMemoryStream     : TMemoryStream;
  vAdapter          : IStream;
  OutBuf            : Pointer;
  OutBytes          : Integer;
begin
  { ConnectionString }
  vConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\Program Files\Microsoft
Office\Office10\Samples\Northwind.mdb;Persist Security Info=False';
  { Create our _Connection object. }
  vConnection := CoConnection.Create;
  vConnection.ConnectionString := vConnectionString;
  { Open the _Connection. }
  vConnection.Open(vConnectionString, '', '', adConnectUnspecified);
  { Grab the data and stuff it into a _Recordset. }
  vRecordset := vConnection.Execute('SELECT * FROM EMPLOYEES', EmptyParam,
adCmdText);
  { Do we have any data? }
  if not vRecordset.EOF then
  begin
    { Create our memory stream. }
    vMemoryStream := TMemoryStream.Create;
    try
      { Connect the adapter and the memory stream. }
      vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
      { Save the recordset to the adapter using the ADTG format. }
      vRecordset.Save(OleVariant(vAdapter), adPersistADTG);
      { The memory stream should now contain the data, thanks to the
adapter. }
      if vMemoryStream.Size > 0 then
      begin
        { Reset the position. }
        vMemoryStream.Position := 0;
        vMemoryStream.SaveToFile('C:\StreamTest.txt');
        { Compress the memory. }
        OutBuf := nil;
        OutBytes := 0;
        CompressBuf(vMemoryStream.Memory, vMemoryStream.Size, OutBuf,
OutBytes);
        if (OutBuf <> nil) and (OutBytes > 0) then
        begin
          { Clear the memory stream. }
          vMemoryStream.Clear;
          { Write the new data. }
          vMemoryStream.Write(OutBuf, OutBytes);
          { Do something with the new data... }
          // DoSomething(vMemoryStream);
        end;
      end;
    finally
      vMemoryStream.Free;
    end;
  end;
end;

Quote
"Robert Baker" <zxy...@hotmail.com> wrote in message

news:3e646581$1@newsgroups.borland.com...
Quote
> Anyone know how to get the ADOStream into a buffer
> Thanks,
> Robert Baker

>   procedure CompressADOStream(ADOStream: _Stream; outStream:
TMemoryStream);
>   var InpBuf,OutBuf: Pointer;
>   var InpBytes,OutBytes: integer;
>     str: string;
>   begin
>     InpBuf := nil;
>     OutBuf := nil;
>     try
>       GetMem(InpBuf, ADOStream.size);
>       ADOStream.Position := 0;

>    ********** Problem statement below *************
>       InpBytes := ADOStream.Read(OleVariant(InpBuf^));
>    *** ******* I get Invalid Variant Type here ***************

>       CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
>       outStream.Write(OutBuf^,OutBytes);
>     finally
>       if InpBuf <> nil then FreeMem(InpBuf);
>       if OutBuf <> nil then FreeMem(OutBuf);
>     end;
>   end;

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Michael,

Thanks - this looks very good BUT on the line "vConnection :=
CoConnection.Create;",
I get the following compiler error:

[Error] uMSA.pas(617): Incompatible types: 'ADO26_TLB._Connection' and
'ADOInt._Connection'

What might I have wrong?  I have D7 and

Thanks again,

Robert Baker

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


I got the code below to compile, but on the following line:

      vRecordset._xSave(OleVariant(vAdapter), adPersistADTG);

I get the run time error: "Could not convert variant of type (Unknown) into
type (OleStr)"

Any suggestions?

Thanks - Robert

procedure TfrmMapping.Button4Click(Sender: TObject);
var
  vConnectionString : string;
  //vConnection       : _Connection;
  vConnection       : Connection15;        // ADO TLB 26
  //vRecordset        : _Recordset;
  vRecordset        : Recordset21;
  vMemoryStream     : TMemoryStream;
  vAdapter          : IStream;
  OutBuf            : Pointer;
  OutBytes          : Integer;
begin
  { ConnectionString }
  vConnectionString := 'Provider=SQLOLEDB.1;Password=;Persist Security
Info=True;User ID=sa;Initial Catalog=wfg;Data Source=zxytekserver';
  { Create our _Connection object. }
  vConnection := CoConnection.Create;
  //vConnection.ConnectionString := vConnectionString;
  { Open the _Connection. }
  vConnection.Open(vConnectionString, '', '', adConnectUnspecified);
  { Grab the data and stuff it into a _Recordset. }
  vRecordset := vConnection.Execute('SELECT  msa, name, activedlr,
potnewwfgd, potfabsal FROM [MappingData].[dbo].[MSAModel] order by MSA',
EmptyParam, adCmdText);
  { Do we have any data? }
  if not vRecordset.EOF then
  begin
    { Create our memory stream. }
    vMemoryStream := TMemoryStream.Create;
    try
      { Connect the adapter and the memory stream. }
      vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
      { Save the recordset to the adapter using the ADTG format. }
      vRecordset._xSave(OleVariant(vAdapter), adPersistADTG);

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Place ADO26_TLB in front of every ADO variable I've defined.

Example:

var
  vConnection       : ADO26_TLB._Connection;
  vRecordset        : ADO26_TLB._Recordset;
begin
  //...
end;

Quote
"Robert Baker" <zxy...@hotmail.com> wrote in message

news:3e6505b3@newsgroups.borland.com...
Quote
> Michael,

> Thanks - this looks very good BUT on the line "vConnection :=
> CoConnection.Create;",
> I get the following compiler error:

> [Error] uMSA.pas(617): Incompatible types: 'ADO26_TLB._Connection' and
> 'ADOInt._Connection'

> What might I have wrong?  I have D7 and

> Thanks again,

> Robert Baker

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


This won't work, because saving to a stream isn't supported in the version
you've defined.

Quote
"Robert Baker" <zxy...@hotmail.com> wrote in message

news:3e651311$1@newsgroups.borland.com...
Quote
> I got the code below to compile, but on the following line:

>       vRecordset._xSave(OleVariant(vAdapter), adPersistADTG);

> I get the run time error: "Could not convert variant of type (Unknown)
into
> type (OleStr)"

> Any suggestions?

> Thanks - Robert

> procedure TfrmMapping.Button4Click(Sender: TObject);
> var
>   vConnectionString : string;
>   //vConnection       : _Connection;
>   vConnection       : Connection15;        // ADO TLB 26
>   //vRecordset        : _Recordset;
>   vRecordset        : Recordset21;
>   vMemoryStream     : TMemoryStream;
>   vAdapter          : IStream;
>   OutBuf            : Pointer;
>   OutBytes          : Integer;
> begin
>   { ConnectionString }
>   vConnectionString := 'Provider=SQLOLEDB.1;Password=;Persist Security
> Info=True;User ID=sa;Initial Catalog=wfg;Data Source=zxytekserver';
>   { Create our _Connection object. }
>   vConnection := CoConnection.Create;
>   //vConnection.ConnectionString := vConnectionString;
>   { Open the _Connection. }
>   vConnection.Open(vConnectionString, '', '', adConnectUnspecified);
>   { Grab the data and stuff it into a _Recordset. }
>   vRecordset := vConnection.Execute('SELECT  msa, name, activedlr,
> potnewwfgd, potfabsal FROM [MappingData].[dbo].[MSAModel] order by MSA',
> EmptyParam, adCmdText);
>   { Do we have any data? }
>   if not vRecordset.EOF then
>   begin
>     { Create our memory stream. }
>     vMemoryStream := TMemoryStream.Create;
>     try
>       { Connect the adapter and the memory stream. }
>       vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
>       { Save the recordset to the adapter using the ADTG format. }
>       vRecordset._xSave(OleVariant(vAdapter), adPersistADTG);

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Michael,

You are a hero! Thank you, thank you, thank you.  The code below works
through "/////////////////// ".

I hate to impose, but you really seam to know this stuff and perhaps you
might advise me regarding the following two issues:

            // I GET A DECOMPRESSION ERROR ON THE NEXT STATEMENT
            DecompressBuf(InpBuf,sz,0,OutBuf,OutBytes);  // What could be
wrong [maybe not enough sleep here<g>]

            // THE FOLLOWING STATEMENT DOES NOT WORK
            ADODataSet1.Recordset := vRecordset;
            {I would like the data to be available to databound
controls.What is the best way to do this?}

Thanks again,

Robert Baker

procedure TfrmMapping.Button4Click(Sender: TObject);
var
  vConnectionString : string;
  vConnection       : ADO26_TLB._Connection;
  vRecordset        : ADO26_TLB._Recordset;
  vDataset          : ADO26_TLB._Recordset;
  vMemoryStream     : TMemoryStream;
  vAdapter          : IStream;
  OutBuf, InpBuf    : Pointer;
  OutBytes, sz      : Integer;
  MStream : TMemoryStream;
  ByteArray : TByteDynArray;
  pTemp : Pointer;
begin
  { ConnectionString }
  vConnectionString := 'Provider=SQLOLEDB.1;Password=;Persist Security
Info=True;User ID=....
  { Create our _Connection object. }
  vConnection := CoConnection.Create;
  { Open the _Connection. }
  vConnection.Open(vConnectionString, '', '', adConnectUnspecified);
  { Grab the data and stuff it into a _Recordset. }
  vRecordset := vConnection.Execute('SELECT  field1,field2,...FROM tbl1',
EmptyParam, adCmdText);
  { Do we have any data? }
  if not vRecordset.EOF then
  begin
    { Create our memory stream. }
    vMemoryStream := TMemoryStream.Create;
    try
      { Connect the adapter and the memory stream. }
      vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
      { Save the recordset to the adapter using the ADTG format. }
      vRecordset.Save(OleVariant(vAdapter), adPersistADTG);
      { The memory stream should now contain the data, thanks to the
adapter. }
      if vMemoryStream.Size > 0 then
      begin
        { Reset the position. }
        vMemoryStream.Position := 0;
        { Compress the memory. }
        OutBuf := nil;
        OutBytes := 0;
        CompressBuf(vMemoryStream.Memory, vMemoryStream.Size, OutBuf,
OutBytes);
        if (OutBuf <> nil) and (OutBytes > 0) then
        begin
          { Clear the memory stream. }
          vMemoryStream.Clear;
          { Write the new data into the Memory Stream}
          vMemoryStream.Write(OutBuf, OutBytes);
          { Point the Memory Stream to the beginning}
          vMemoryStream.Position := 0;
          {Put it into a Byte Array}
           ByteArray := ByteArrayFromStream(vMemoryStream);
      ///////////////////  - SENT IT ACROSS THE WIRE ////////////////
        =========== NOW WE ARE ON THE CLIENT SIDE =========
          { Clear the memory stream. }
          vMemoryStream.Clear;
          pTemp := @ByteArray[0];
          {Put it back into the Memory Stream from the Byte Array}
          vMemoryStream.Write( pTemp^, Length(ByteArray));
          vMemoryStream.Position := 0;

          sz := vMemoryStream.size;
          if sz > 0 then
          try
            { Decompress the Stream into the buffer }
            InpBuf := nil;
            OutBuf := nil;
            GetMem(InpBuf,sz);
            { Read the Stream into the Input Buffer}
            vMemoryStream.Read(InpBuf^,sz);

            OutBytes := 0;
            { Decompress the Input Buffer into the Output Buffer}
            // I GET A DECOMPRESSION ERROR ON THE NEXT STATEMENT
            DecompressBuf(InpBuf,sz,0,OutBuf,OutBytes);
            if (OutBuf <> nil) and (OutBytes > 0) then
            begin
              { Clear the memory stream}
              vMemoryStream.Clear;
              { Put it back into the Stream from the decompressed buffer}
              vMemoryStream.Write(OutBuf^,OutBytes);
             { Write the new data. }
              { Save the recordset to the adapter using the ADTG format. }
              vAdapter := nil;
              vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
              vRecordset.GetRows(22,OleVariant(vAdapter), adPersistADTG);

            // THE FOLLOWING STATEMENT DOES NOT WORK
            ADODataSet1.Recordset := vRecordset;

            end;
          finally
            vMemoryStream.Free;
            DecompressedStream.Free;
            if InpBuf <> nil then FreeMem(InpBuf);
            if OutBuf <> nil then FreeMem(OutBuf);
          end;
        end;
      end;

      finally
    end;
  end;
end;

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


I'm not familiar with ZLib, but here are some functions I found (untested):

From:
http://groups.google.com/groups?q=DecompressBuf(+group:*.delphi*&hl=e...
e=UTF-8&oe=UTF-8&newwindow=1&selm=987511022%40p24.f101.n469.z2.ftn&rnum=8

Procedure CompressStream(inpStream, outStream: TStream);
Var
  InpBuf,OutBuf: Pointer;
  InpBytes,OutBytes: integer;
begin
  InpBuf:= nil;  OutBuf:= nil;
  try
    GetMem(InpBuf,inpStream.size);
    inpStream.Position := 0;
    InpBytes:= inpStream.Read(InpBuf^, inpStream.size);
    CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
    outStream.Write(OutBuf^,OutBytes);
  finally
    if InpBuf <> nil then FreeMem(InpBuf);
    if OutBuf <> nil then FreeMem(OutBuf);
  end;
end;

Procedure ExpandStream(inpStream, outStream: TStream);
Var
 InpBuf,OutBuf: Pointer;
 OutBytes, sz: integer;
begin
  InpBuf := nil;
  OutBuf := nil;
  sz := inpStream.size-inpStream.Position;
  if sz > 0 then try
    GetMem(InpBuf, sz);
    inpStream.Read(InpBuf^, sz);
    DecompressBuf(InpBuf, sz, 0, OutBuf, OutBytes);
    outStream.Write(OutBuf^, OutBytes);
  finally
    if InpBuf <> nil then FreeMem(InpBuf);
    if OutBuf <> nil then FreeMem(OutBuf);
  end;
  outStream.Position := 0;
end;

I assume you're trying to transfer a recordset across the wire from a HTTP
server? The method I use to do this is to create a component that has a
Recordset property. This component is then compressed and transferred across
the wire to the client where it is decompressed. After it's been
decompressed into a stream, it's then read back into it's original
state...that of a component. It's pretty simple to do, and working with a
component is much easier at the application level. Once you have the
recordset, you should be able to assign it to the TADOQuery as you are
trying.

Regards,

Michael Cessna

Quote
"Robert Baker" <zxy...@hotmail.com> wrote in message

news:3e662db3@newsgroups.borland.com...
Quote
> Michael,

> You are a hero! Thank you, thank you, thank you.  The code below works
> through "/////////////////// ".

> I hate to impose, but you really seam to know this stuff and perhaps you
> might advise me regarding the following two issues:

>             // I GET A DECOMPRESSION ERROR ON THE NEXT STATEMENT
>             DecompressBuf(InpBuf,sz,0,OutBuf,OutBytes);  // What could be
> wrong [maybe not enough sleep here<g>]

>             // THE FOLLOWING STATEMENT DOES NOT WORK
>             ADODataSet1.Recordset := vRecordset;
>             {I would like the data to be available to databound
> controls.What is the best way to do this?}

> Thanks again,

> Robert Baker

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Michael,

The zlib routines worked and the code below works through:
        vNewDataset := CoRecordset.Create;
        ********************
            This is where I need some help to get the data into an ADO
Dataset that I can databind, etc.

Thanks so very much,

Robert

procedure TfrmMapping.Button4Click(Sender: TObject);
var
  vConnectionString : string;
  vConnection       : ADO26_TLB._Connection;
  vRecordset        : ADO26_TLB._Recordset;
  vDataset          : ADO26_TLB._Recordset;
  vMemoryStream     : TMemoryStream;
  vAdapter          : IStream;
  vNewDataset       : ADO26_TLB._Recordset;
  ByteArray      : TByteDynArray;
  pTemp      : Pointer;
  CompressedStream  : TMemoryStream;
  ADOStream     : ADO26_TLB._Stream; //coStream;
begin
  { ConnectionString }
  vConnectionString := 'Provider=SQLOLEDB.1;Password=;Persist Security
Info=True;User...
  { Create our _Connection object. }
  vConnection := CoConnection.Create;
  { Open the _Connection. }
  vConnection.Open(vConnectionString, '', '', adConnectUnspecified);
  { Grab the data and stuff it into a _Recordset. }
  vRecordset := vConnection.Execute('SELECT fld1, fld2 FROM myTable',
EmptyParam, adCmdText);
  { Do we have any data? }
  if not vRecordset.EOF then
  begin
    { Create our memory stream. }
    vMemoryStream := TMemoryStream.Create;
    CompressedStream := TMemoryStream.Create;
    try
      { Connect the adapter and the memory stream. }
      vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
      { Save the recordset to the adapter using the ADTG format. }
      vRecordset.Save(OleVariant(vAdapter), adPersistADTG);
      { The memory stream should now contain the data, thanks to the
adapter. }
      if vMemoryStream.Size > 0 then
      begin
        CompressStream(vMemoryStream, CompressedStream);
        { Reset the position. }
        vMemoryStream.Position := 0;
        vMemoryStream.SaveToFile('C:\StreamTest.txt');
        ///////////////////
        {Put it into a Byte Array}
        ByteArray := ByteArrayFromStream(vMemoryStream);
        { Clear the memory stream. }
        vMemoryStream.Clear;
        pTemp := @ByteArray[0];
        {Put it back into the Memory Stream from the Byte Array}
        vMemoryStream.Write( pTemp^, Length(ByteArray));
        ///////////////////
        { Un-compress the memory stream }
        ExpandStream(CompressedStream, vMemoryStream);
        vAdapter := nil;
        vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
        { Reset the position. }
        vMemoryStream.Position := 0;
        vNewDataset := CoRecordset.Create;
********************
    Need help here
********************
        vMemoryStream.Free;
        CompressedStream.Free;
      end;
    finally
    end;
  end;

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Just assign the recordset to a TADOQuery.Recordset, and then hook up a grid
or whatever to the query via a datasource.

MyQuery.Recordset := ThisNewRecordset;
MyDataSource.DataSet := MyQuery;
MyDBGrid.DataSource := MyDataSource;

Mike

Quote
"Robert Baker" <zxy...@hotmail.com> wrote in message

news:3e69423c$1@newsgroups.borland.com...
Quote
> Michael,

> The zlib routines worked and the code below works through:
>         vNewDataset := CoRecordset.Create;
>         ********************
>             This is where I need some help to get the data into an ADO
> Dataset that I can databind, etc.

> Thanks so very much,

> Robert

> procedure TfrmMapping.Button4Click(Sender: TObject);
> var
>   vConnectionString : string;
>   vConnection       : ADO26_TLB._Connection;
>   vRecordset        : ADO26_TLB._Recordset;
>   vDataset          : ADO26_TLB._Recordset;
>   vMemoryStream     : TMemoryStream;
>   vAdapter          : IStream;
>   vNewDataset       : ADO26_TLB._Recordset;
>   ByteArray      : TByteDynArray;
>   pTemp      : Pointer;
>   CompressedStream  : TMemoryStream;
>   ADOStream     : ADO26_TLB._Stream; //coStream;
> begin
>   { ConnectionString }
>   vConnectionString := 'Provider=SQLOLEDB.1;Password=;Persist Security
> Info=True;User...
>   { Create our _Connection object. }
>   vConnection := CoConnection.Create;
>   { Open the _Connection. }
>   vConnection.Open(vConnectionString, '', '', adConnectUnspecified);
>   { Grab the data and stuff it into a _Recordset. }
>   vRecordset := vConnection.Execute('SELECT fld1, fld2 FROM myTable',
> EmptyParam, adCmdText);
>   { Do we have any data? }
>   if not vRecordset.EOF then
>   begin
>     { Create our memory stream. }
>     vMemoryStream := TMemoryStream.Create;
>     CompressedStream := TMemoryStream.Create;
>     try
>       { Connect the adapter and the memory stream. }
>       vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
>       { Save the recordset to the adapter using the ADTG format. }
>       vRecordset.Save(OleVariant(vAdapter), adPersistADTG);
>       { The memory stream should now contain the data, thanks to the
> adapter. }
>       if vMemoryStream.Size > 0 then
>       begin
>         CompressStream(vMemoryStream, CompressedStream);
>         { Reset the position. }
>         vMemoryStream.Position := 0;
>         vMemoryStream.SaveToFile('C:\StreamTest.txt');
>         ///////////////////
>         {Put it into a Byte Array}
>         ByteArray := ByteArrayFromStream(vMemoryStream);
>         { Clear the memory stream. }
>         vMemoryStream.Clear;
>         pTemp := @ByteArray[0];
>         {Put it back into the Memory Stream from the Byte Array}
>         vMemoryStream.Write( pTemp^, Length(ByteArray));
>         ///////////////////
>         { Un-compress the memory stream }
>         ExpandStream(CompressedStream, vMemoryStream);
>         vAdapter := nil;
>         vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
>         { Reset the position. }
>         vMemoryStream.Position := 0;
>         vNewDataset := CoRecordset.Create;
> ********************
>     Need help here
> ********************
>         vMemoryStream.Free;
>         CompressedStream.Free;
>       end;
>     finally
>     end;
>   end;

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Michael,

Sorry I wasn't clear. What I don't know how to do is to get the Memory
Stream back into a recordset that is compatible with my ADO components.

       { Un-compress the memory stream }
        ExpandStream(CompressedStream, vMemoryStream);
        vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
        { Reset the position. }
        vMemoryStream.Position := 0;
        vRecordset.Read(OleVariant(vAdapter), adPersistADTG);
[Error] uMSA.pas(647): Undeclared identifier: 'Read'

The dataset got into the stream using the adapter, but there is no "read"
function so I, not understanding how this thing works cannot figure out how
to get the stream back into a proper ADO recordset.

  ADOQuery1.Recordset := vRecordset;
[Error] uMSA.pas(649): Incompatible types: 'ADO26_TLB._Recordset' and
'ADOInt._Recordset'

I dropped an ADO query off the pallet onto my form and attempted to hook
vRecordset to it, but I get the incompatiblity error.

Sorry to be so dumb - it you have any suggestions as to where I might read
up on this stuff, please advise.

Thanks again,

Robert

Re:invalid variant type copying streamed contents of TADOStream into a Buffer


Try to use the RecordsetToMemoryStream and MemoryStreamToRecordset methods I
posted at first, without using compression. If you can get this to work,
then you can work the compression routine in.

Quote
"Robert Baker" <zxy...@hotmail.com> wrote in message

news:3e6acfab$1@newsgroups.borland.com...
Quote
> Michael,

> Sorry I wasn't clear. What I don't know how to do is to get the Memory
> Stream back into a recordset that is compatible with my ADO components.

>        { Un-compress the memory stream }
>         ExpandStream(CompressedStream, vMemoryStream);
>         vAdapter := TStreamAdapter.Create(vMemoryStream, soReference);
>         { Reset the position. }
>         vMemoryStream.Position := 0;
>         vRecordset.Read(OleVariant(vAdapter), adPersistADTG);
> [Error] uMSA.pas(647): Undeclared identifier: 'Read'

> The dataset got into the stream using the adapter, but there is no "read"
> function so I, not understanding how this thing works cannot figure out
how
> to get the stream back into a proper ADO recordset.

>   ADOQuery1.Recordset := vRecordset;
> [Error] uMSA.pas(649): Incompatible types: 'ADO26_TLB._Recordset' and
> 'ADOInt._Recordset'

> I dropped an ADO query off the pallet onto my form and attempted to hook
> vRecordset to it, but I get the incompatiblity error.

> Sorry to be so dumb - it you have any suggestions as to where I might read
> up on this stuff, please advise.

> Thanks again,

> Robert

Other Threads