Delphi (XE) + MySQL + Latin1 Troubles and Solutions
Posted: 18.03.2011, 16:56
In the last two weeks i moved an old Turbo 2006 project do Delphi XE with Zeos 7.0 Alpha from SVN.
The project uses Zeos to connect to an MySQL Database with charset latin1. All worked fine, until i realized that sending data to the database will scramble any special chars from latin1 (here: ÄÖÜäöüß). But ready already correctly stored special chars is not a problem. After some reading, and doing some tests i found out was was going on:
Regardles of the current codepage in the connection, zeos encodes all strings as UTF8. Ok, lets just set the codepage of the connection to utf8 and let the database handle the conversation from utf8 to latin1. Now Saving works fine, but the data fetched from the server is now also utf8 encoded (trying to set Params like character-set_results didn't worked), but Zeos won't do the UTF8 decoding. Shit.
Ok lets do a quick try with an utf8 databse and charset=utf8. woot, all works like a breeze. Getting some information about converting the database to utf8 brings out that i either can do it with only one command per table, but then maybe having changed fieldtypes and sizes, but that was not what i want, or changing each field in every table one by one. Hell no.
Although i wasn't quite sure about the other applications (PHP, ...) accessing these database will work without any modifications.
After some searching here in the forums i found the following solution:
1.) from http://zeos.firmos.at/viewtopic.php?p=12092#12092
In File src/dbc/ZDbcCache.pas in TZRowAccessor.SetUnicodeString after Line 2127 (FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;) add the following
(You need to add the Unit WideStrUtils)
That solves all CHAR and VARCHAR-Fields, but not TEXT Fields
2.) from http://zeos.firmos.at/viewtopic.php?p=12834#12834
In File src/dbc/ZDbcMySqlResultSet.pas in TZMySQLResultSet.GetBlob(ColumnIndex: Integer) changing from:
to:
Thats all to get it working with a latin1 (maybe even other types) and connection.Property charset=utf8.
According to my little test programm it even won't break utf8 databases.
Hope this helps someone migrating to 7
EDIT: its codepage=UTF8 NOT charset=UTF8, sry
The project uses Zeos to connect to an MySQL Database with charset latin1. All worked fine, until i realized that sending data to the database will scramble any special chars from latin1 (here: ÄÖÜäöüß). But ready already correctly stored special chars is not a problem. After some reading, and doing some tests i found out was was going on:
Regardles of the current codepage in the connection, zeos encodes all strings as UTF8. Ok, lets just set the codepage of the connection to utf8 and let the database handle the conversation from utf8 to latin1. Now Saving works fine, but the data fetched from the server is now also utf8 encoded (trying to set Params like character-set_results didn't worked), but Zeos won't do the UTF8 decoding. Shit.
Ok lets do a quick try with an utf8 databse and charset=utf8. woot, all works like a breeze. Getting some information about converting the database to utf8 brings out that i either can do it with only one command per table, but then maybe having changed fieldtypes and sizes, but that was not what i want, or changing each field in every table one by one. Hell no.
Although i wasn't quite sure about the other applications (PHP, ...) accessing these database will work without any modifications.
After some searching here in the forums i found the following solution:
1.) from http://zeos.firmos.at/viewtopic.php?p=12092#12092
In File src/dbc/ZDbcCache.pas in TZRowAccessor.SetUnicodeString after Line 2127 (FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;) add the following
Code: Select all
if DetectUTF8Encoding(Value) = etUTF8 then
Value := UTF8Decode(Value);
That solves all CHAR and VARCHAR-Fields, but not TEXT Fields
2.) from http://zeos.firmos.at/viewtopic.php?p=12834#12834
In File src/dbc/ZDbcMySqlResultSet.pas in TZMySQLResultSet.GetBlob(ColumnIndex: Integer) changing from:
Code: Select all
function TZMySQLResultSet.GetBlob(ColumnIndex: Integer): IZBlob;
var
Stream: TStream;
begin
{$IFNDEF DISABLE_CHECKING}
CheckBlobColumn(ColumnIndex);
{$ENDIF}
Stream := nil;
try
if not IsNull(ColumnIndex) then
begin
Stream := TStringStream.Create(UTF8ToString(GetString(ColumnIndex)));
Result := TZAbstractBlob.CreateWithStream(Stream)
end
else
Result := TZAbstractBlob.CreateWithStream(nil);
finally
if Assigned(Stream) then
Stream.Free;
end;
end;
Code: Select all
function TZMySQLResultSet.GetBlob(ColumnIndex: Integer): IZBlob;
var
Stream: TStream;
Value: AnsiString;
begin
{$IFNDEF DISABLE_CHECKING}
CheckBlobColumn(ColumnIndex);
{$ENDIF}
Stream := nil;
try
if not IsNull(ColumnIndex) then
begin
Value := GetString(ColumnIndex);
if DetectUTF8Encoding(Value) = etUTF8 then
Value := UTF8Decode(Value);
Stream := TStringStream.Create(Value);
Result := TZAbstractBlob.CreateWithStream(Stream)
end
else
Result := TZAbstractBlob.CreateWithStream(nil);
finally
if Assigned(Stream) then
Stream.Free;
end;
end;
According to my little test programm it even won't break utf8 databases.
Hope this helps someone migrating to 7
EDIT: its codepage=UTF8 NOT charset=UTF8, sry