2
votes

Here's my architecture :

Datasnap Client <=> Datasnap Server <=> Oracle 11 XE

I'm using a remote provider with TDSProviderConnection from the client side to access my dataset.

Basically, I'm using a TIdHTTP component to query a website and store the result in an Oracle CLOB column.

When saving result to a file, text, accented and other exotic characters are displayed correctly. same text inserted into a clob using sqldeveloper is displayed correctly as well.

But when I'm doing this thru datasnap architecture, wrong characters shows up (like black diamonds or "upperscore" (underscore on top)

My DB Charset is AL32UTF8, which is the default charset on Oracle 11 XE.

To better understand where the problem is, I rewrote part of my client to access my database directly. And I can say the problem is not in the communication between datasnap client and server.

Now my architecture is :

Client <=> Database

And I access Oracle XE the following way :

TClientDataSet <=> TDataSetProvider <=> TSQLDataSet <=> TSQLConnection

Response from TIdHTTP, which is a TMemoryStream, is stored in the TClientDataset with :

    With ClientDataSet do
    begin
      Edit;
      (Fieldbyname('MYCLOBFIELD') as TBlobField).LoadFromStream(MS);
      ApplyUpdates(-1);
    end;

EDIT : 21st of may

I did test around TBlobField and this component seems to be part of my problem. Let me explain :

I took a random string containing characters from an extended charset like this : 'ÐÒÙÜßąĀûÆ'

And with my ClientDataSet, changed the assignment to this :

    FieldByname('MYCLOB').value := 'ÐÒÙÜßąĀûÆ'; // <-- Inserted correctly into Oracle.

Putting this string in a file 'test.txt' and trying to display a popup with the content does not work :

    var
      MyBlobField: TBlobField;
    begin
      MyBlobField.LoadFromFile('test.txt');
      ShowMessage(MyBlobField.AsString); // <-- does not display correctly

But Using a TMemo to display the content works like a charm :

    var
      MyMemo: TMemo;
    begin
      MyMemo.Lines.LoadFromFile('test.txt'); // <-- Works perfectly !!

I tried to set the TBlobField.BlobType property to ftOraClob or ftBlob with no luck.

Finally, using a TStringList (what TMemo.Lines is actually) to load my string into Oracle does the trick.

I guess either something is wrong with TBlobField.LoadFromFile/LoadFromStream or I'm not using it correctly.

TStringList inherits its LoadFromFile/LoadFromStream method from TStrings, which works.

Any help will be greatly appreciated. Regards.

1

1 Answers

1
votes

If you want to put some data to TBlobField you can try:

procedure SetParamBlob(Param : TParam; sData : String);
var  
 Str       : TStringStream;
begin
 Str := TStringStream.Create(sData);
 try
   Param.LoadFromStream(Str, ftBlob);
 finally
   Str.Free;
 end;
end;

or this:

procedure SetParamBlob(Param : TParam; sData : String);
var List   : TStringList;
   MemStream : TMemoryStream;
begin
  Param.Clear;
  Param.DataType := ftBlob;
  List   := TStringList.Create;
  MemStream := TMemoryStream.Create;
  try
    List.Text := sData;
    List.SaveToStream(MemStream);
    MemStream.Seek(0, soFromBeginning);
    Param.LoadFromStream(MemStream, ftBlob);
   finally
    FreeAndNil(List);
    FreeAndNil(MemStream);
   end;
end;

... ... SetParamBlob(q.ParamByName('FIELD'), MyMemo.Text); ...

You can load data from file by this:

   function LoadData(sFileSrc : String) : String;
   var F : TFileStream;
   begin
     F := TFileStream.Create(sFileSrc, fmOpenRead + fmShareDenyNone);
     try
       SetLength(Result, f.Size);
       f.Read(Result[1],f.Size);
      finally
       F.Free;
      end;
    end;