Unicode Support

Discussion of open issues, suggestions and bugs regarding usage of dbExpress drivers for SQL Server in Delphi and C++Builder
Post Reply
Babnik42
Posts: 15
Joined: Tue 28 Nov 2006 11:46

Unicode Support

Post by Babnik42 » Wed 20 Dec 2006 09:48

I'm trying to read and write unicode to a SQL Server NText field. While the write seems to work well enough, reading in the text causes a TMemoField rather than a TWideMemoField to be created. I've also tried subclassing TSQLDataset, and overriding internalinitfielddefs, to create a TWideMemoField instead of a TMemoField, and I still don't get what I saved out to the database. Any ideas?

Jackson
Posts: 512
Joined: Thu 26 Jan 2006 10:06

Post by Jackson » Thu 21 Dec 2006 16:20

The dbExpress technology supports Unicode from Delphi 2006.
Use the Unicode extended driver option to enable or disable Unicode support.
If it is set to True, all character data from nchar and nvarchar columns is stored as WideStrings, and TStringField is replaced with TWideStringFiled.
Please see the ReadMe.html file in the DbxSda installation directory for more information.

Babnik42
Posts: 15
Joined: Tue 28 Nov 2006 11:46

Post by Babnik42 » Thu 21 Dec 2006 17:38

I have tried what you suggest and all works well, but ntext, and widememo fields are not supported. I have had to make a few changes to corelabs code to get this to work....but I do not like to play around with the source as it makes any new versions that come out difficult to maintain.

Babnik42
Posts: 15
Joined: Tue 28 Nov 2006 11:46

Post by Babnik42 » Thu 21 Dec 2006 18:27

These are the changes I have done :

1) Added a 'Wide' property to TFieldDesc in MemData.pas

property Wide : Boolean read fWide write fWide;

2) in TOLEDBRecordSet.InternalInitFields (OLEDBAccess.pas), I set this property when a wide string is found.

if OLEDBType = DBTYPE_WSTR then
begin
Field.SubDataType := Field.SubDataType or dtWide;
Field.Wide:= True;
end

Note the sub-type is already being set as wide, but this is ignored when setting the fielddefs.

3) In TMemSQLCursor.FromDataType(Field: TFieldDesc; var puSubType: Word): : word; (dbexp.pas) I add the line :

if (puSubType = fldstMEMO) and (Field.Wide) then
puSubType := fldstWIDEMEMO;

The above creates a widememo instead of a memo if an ntext is encountered. But this is still not enough, data was still being lost so I had to do the foloowing :

4) in TData.ReadBlob (memdata.pas), the following lines mean we convert from unicode to ansi string, losing data

s := Marshal.PtrToStringUni(Ws, Result);
Buf := Marshal.StringToHGlobalAnsi(s);
CopyBuffer(Buf, Dest, Result);


I changed this to

CopyBuffer(Ws, Dest, Result)

5) Almost there, but I was only getting half my data. I noticed that TWideMemoField.AsWideString was dividing the blob size by two to get the number of charcters. But TData.GetBlobSize, was also doing this

if Blob.FIsUnicode then
Result := Result shr 1;

So in effect returning the number of characters, and not the blob size. So I got rid of these two lines, and changed the readblob slightly as now I had the number of bytes and not the number of characters

Ws := Marshal.AllocHGlobal(LenBytes);
Buf := nil;
try
Result := Blob.Read(Position shl 1, LenBytes, Ws); // Result is bytes len
Result := Result shr 1; // Result is WideChar len
CopyBuffer(Ws, Dest, Result shl 1);


Now it all works....I'd like to do the same for Oracle, but that's not working at all.....I'll leave that for another day!!!

Jackson
Posts: 512
Joined: Thu 26 Jan 2006 10:06

Post by Jackson » Fri 22 Dec 2006 08:52

We couldn't reproduce the problem.
Please send us (evgeniym*crlab*com) a complete small test project to reproduce the problem;
it is desirable to use Northwind or Master schema objects, otherwise include definition of your own database objects; don't use third party components.

Also supply us the following information
- Exact version of Delphi or C++ Builder
- Exact version of DbxSda. You can see it in ReadMe.html
- Exact version of Microsoft SQL Server and OLE DB provider that you use. You can see it in version info of SQLOLEDB.DLL and SQLNCLI.DLL.

Post Reply