diff --git a/components/zeosdbo/src/dbc/ZDbcMySql.pas b/components/zeosdbo/src/dbc/ZDbcMySql.pas
index 0c843f3a..72e25546 100644
--- a/components/zeosdbo/src/dbc/ZDbcMySql.pas
+++ b/components/zeosdbo/src/dbc/ZDbcMySql.pas
@@ -440,13 +440,9 @@ begin
DriverManager.LogMessage(lcConnect, FPlainDriver.GetProtocol, LogMessage);
{ Sets a client codepage. }
- if FClientCodePage <> '' then
- begin
- SQL := PChar(Format('SET CHARACTER SET %s', [FClientCodePage]));
- FPlainDriver.ExecQuery(FHandle, SQL);
- CheckMySQLError(FPlainDriver, FHandle, lcExecute, SQL);
- DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL);
- end;
+ FPlainDriver.SetCharacterSet(FHandle, 'utf8');
+ CheckMySQLError(FPlainDriver, FHandle, lcExecute, LogMessage);
+ DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, LogMessage);
{ Sets transaction isolation level. }
OldLevel := TransactIsolationLevel;
diff --git a/components/zeosdbo/src/dbc/ZDbcMySqlMetadata.pas b/components/zeosdbo/src/dbc/ZDbcMySqlMetadata.pas
index 07ce6b30..9016c25b 100644
--- a/components/zeosdbo/src/dbc/ZDbcMySqlMetadata.pas
+++ b/components/zeosdbo/src/dbc/ZDbcMySqlMetadata.pas
@@ -2130,9 +2130,9 @@ const
TypeCodes: array[1..MaxTypeCount] of TZSQLType = (
stBinaryStream, stBoolean, stShort, stLong, stBinaryStream, stBinaryStream,
stBinaryStream, stBinaryStream, stBinaryStream, stBytes, stBytes,
- stString, stAsciiStream, stAsciiStream, stAsciiStream, stAsciiStream,
- stString, stString, stBigDecimal, stBigDecimal, stInteger, stInteger,
- stInteger, stShort, stDouble, stFloat, stFloat, stString, stString,
+ stUnicodeString, stUnicodeStream, stUnicodeStream, stUnicodeStream, stUnicodeStream,
+ stUnicodeString, stUnicodeString, stBigDecimal, stBigDecimal, stInteger, stInteger,
+ stInteger, stShort, stDouble, stFloat, stFloat, stUnicodeString, stUnicodeString,
stDate, stTime, stTimestamp, stTimestamp);
TypePrecision: array[1..MaxTypeCount] of Integer = (
64, -1, 4, 16, 16777215, 16777215, MAXBUF, 65535, 255, 255, 255,
diff --git a/components/zeosdbo/src/dbc/ZDbcMySqlResultSet.pas b/components/zeosdbo/src/dbc/ZDbcMySqlResultSet.pas
index 770b361f..05d7d004 100644
--- a/components/zeosdbo/src/dbc/ZDbcMySqlResultSet.pas
+++ b/components/zeosdbo/src/dbc/ZDbcMySqlResultSet.pas
@@ -92,6 +92,7 @@ type
function IsNull(ColumnIndex: Integer): Boolean; override;
function GetPChar(ColumnIndex: Integer): PChar; override;
function GetString(ColumnIndex: Integer): string; override;
+ function GetUnicodeString(ColumnIndex: Integer): WideString; override;
function GetBoolean(ColumnIndex: Integer): Boolean; override;
function GetByte(ColumnIndex: Integer): ShortInt; override;
function GetShort(ColumnIndex: Integer): SmallInt; override;
@@ -388,6 +389,11 @@ begin
SetString(Result, Buffer, Length);
end;
+function TZMySQLResultSet.GetUnicodeString(ColumnIndex: Integer): WideString;
+begin
+ Result := UTF8Decode(GetString(ColumnIndex));
+end;
+
{**
Gets the value of the designated column in the current row
of this ResultSet object as
@@ -693,11 +699,15 @@ end;
NULL, the value returned is null
}
function TZMySQLResultSet.GetUnicodeStream(ColumnIndex: Integer): TStream;
+var
+ s: WideString;
begin
{$IFNDEF DISABLE_CHECKING}
CheckColumnConvertion(ColumnIndex, stUnicodeStream);
{$ENDIF}
- Result := nil;
+ s := GetUnicodeString(ColumnIndex);
+ Result := TMemoryStream.Create;
+ Result.WriteBuffer(s[1], Length(s) * SizeOf(s[1]));
end;
{**
diff --git a/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas b/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas
index 3a528fc8..f13b7f2e 100644
--- a/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas
+++ b/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas
@@ -97,7 +97,7 @@ type
FPlainDriver: IZMySQLPlainDriver;
protected
function CreateExecStatement: IZStatement; override;
- function GetEscapeString(const Value: string): string;
+ function GetEscapeString(const Value: WideString): WideString;
function PrepareSQLParam(ParamIndex: Integer): string; override;
public
constructor Create(PlainDriver: IZMySQLPlainDriver;
@@ -329,15 +329,15 @@ end;
@param Value a regular string.
@return a string in MySQL escape format.
}
-function TZMySQLPreparedStatement.GetEscapeString(const Value: string): string;
+function TZMySQLPreparedStatement.GetEscapeString(const Value: WideString): WideString;
var
BufferLen: Integer;
Buffer: PChar;
begin
BufferLen := Length(Value) * 2 + 1;
GetMem(Buffer, BufferLen);
- BufferLen := FPlainDriver.GetEscapeString(FHandle, Buffer, PChar(Value), Length(Value));
- Result := '''' + BufferToStr(Buffer, BufferLen) + '''';
+ BufferLen := FPlainDriver.GetEscapeString(FHandle, Buffer, PChar(UTF8Encode(Value)), Length(Value));
+ Result := '''' + UTF8Decode(BufferToStr(Buffer, BufferLen)) + '''';
FreeMem(Buffer);
end;
@@ -374,6 +374,8 @@ begin
Result := SoftVarManager.GetAsString(Value);
stString, stBytes:
Result := GetEscapeString(SoftVarManager.GetAsString(Value));
+ stUnicodeString:
+ Result := GetEscapeString(SoftVarManager.GetAsUnicodeString(Value));
stDate:
begin
{$IFNDEF VER130BELOW}
diff --git a/components/zeosdbo/src/dbc/ZDbcMySqlUtils.pas b/components/zeosdbo/src/dbc/ZDbcMySqlUtils.pas
index 93482f73..a823d145 100644
--- a/components/zeosdbo/src/dbc/ZDbcMySqlUtils.pas
+++ b/components/zeosdbo/src/dbc/ZDbcMySqlUtils.pas
@@ -192,7 +192,7 @@ begin
begin
if Signed then Result := stLong
//else Result := stBigDecimal;
- else Result := stString;
+ else Result := stUnicodeString;
end;
FIELD_TYPE_FLOAT:
// Result := stFloat;
@@ -211,34 +211,34 @@ begin
Result := stDouble;
FIELD_TYPE_DATE, FIELD_TYPE_NEWDATE:
//Result := stDate;
- Result := stString;
+ Result := stUnicodeString;
FIELD_TYPE_TIME:
//Result := stTime;
- Result := stString;
+ Result := stUnicodeString;
FIELD_TYPE_DATETIME, FIELD_TYPE_TIMESTAMP:
//Result := stTimestamp;
- Result := stString;
+ Result := stUnicodeString;
FIELD_TYPE_TINY_BLOB, FIELD_TYPE_MEDIUM_BLOB,
FIELD_TYPE_LONG_BLOB, FIELD_TYPE_BLOB:
if (FieldFlags and BINARY_FLAG) = 0 then
- Result := stAsciiStream
+ Result := stUnicodeStream
else Result := stBinaryStream;
FIELD_TYPE_BIT:
Result := stBinaryStream;
FIELD_TYPE_VARCHAR:
- Result := stString;
+ Result := stUnicodeString;
FIELD_TYPE_VAR_STRING:
- Result := stString;
+ Result := stUnicodeString;
FIELD_TYPE_STRING:
- Result := stString;
+ Result := stUnicodeString;
FIELD_TYPE_ENUM:
- Result := stString;
+ Result := stUnicodeString;
FIELD_TYPE_SET:
- Result := stString;
+ Result := stUnicodeString;
FIELD_TYPE_NULL:
// Example: SELECT NULL FROM DUAL
// Todo: Find out if it is possible to get real data in a TYPE_NULL field, perhaps adjust to binary or some such?
- Result := stString;
+ Result := stUnicodeString;
FIELD_TYPE_GEOMETRY:
// Todo: Would be nice to show as WKT.
Result := stBinaryStream;
@@ -246,7 +246,7 @@ begin
raise Exception.Create('Unknown MySQL data type!');
end;
{ SHOW FULL PROCESSLIST on 4.x servers can return veeery long FIELD_TYPE_VAR_STRINGs. The following helps avoid excessive row buffer allocation later on. }
- if (Result = stString) and (PlainDriver.GetFieldLength(FieldHandle) > 8192) then Result := stAsciiStream;
+ if (Result = stUnicodeString) and (PlainDriver.GetFieldLength(FieldHandle) > 8192) then Result := stUnicodeStream;
end;
{**
@@ -304,7 +304,7 @@ begin
begin
// Zeos uses a floating point type for unsigned int64..
//if IsUnsigned then Result := stBigDecimal
- if IsUnsigned then Result := stString
+ if IsUnsigned then Result := stUnicodeString
else Result := stLong;
end
else if TypeName = 'INT24' then
@@ -335,21 +335,21 @@ begin
else if TypeName = 'DOUBLE' then
Result := stDouble
else if TypeName = 'CHAR' then
- Result := stString
+ Result := stUnicodeString
else if TypeName = 'VARCHAR' then
- Result := stString
+ Result := stUnicodeString
else if TypeName = 'VARBINARY' then
Result := stBytes
else if TypeName = 'BINARY' then
Result := stBytes
else if TypeName = 'DATE' then
- Result := stString
+ Result := stUnicodeString
else if TypeName = 'TIME' then
- Result := stString
+ Result := stUnicodeString
else if TypeName = 'TIMESTAMP' then
- Result := stString
+ Result := stUnicodeString
else if TypeName = 'DATETIME' then
- Result := stString
+ Result := stUnicodeString
else if TypeName = 'TINYBLOB' then
Result := stBinaryStream
else if TypeName = 'BLOB' then
@@ -359,17 +359,17 @@ begin
else if TypeName = 'LONGBLOB' then
Result := stBinaryStream
else if TypeName = 'TINYTEXT' then
- Result := stAsciiStream
+ Result := stUnicodeStream
else if TypeName = 'TEXT' then
- Result := stAsciiStream
+ Result := stUnicodeStream
else if TypeName = 'MEDIUMTEXT' then
- Result := stAsciiStream
+ Result := stUnicodeStream
else if TypeName = 'LONGTEXT' then
- Result := stAsciiStream
+ Result := stUnicodeStream
else if TypeName = 'ENUM' then
- Result := stString
+ Result := stUnicodeString
else if TypeName = 'SET' then
- Result := stString
+ Result := stUnicodeString
else if TypeName = 'BIT' then
Result := stBinaryStream
else for i := 0 to Length(GeoTypes)-1 do if GeoTypes[i] = TypeName then Result := stBinaryStream;
diff --git a/components/zeosdbo/src/plain/ZPlainMySqlDriver.pas b/components/zeosdbo/src/plain/ZPlainMySqlDriver.pas
index d76b1bcc..3ba3573b 100644
--- a/components/zeosdbo/src/plain/ZPlainMySqlDriver.pas
+++ b/components/zeosdbo/src/plain/ZPlainMySqlDriver.pas
@@ -188,6 +188,7 @@ type
function GetAffectedRows(Handle: PZMySQLConnect): Int64;
// char_set_name
+ procedure SetCharacterSet(Handle: PZMySQLConnect; const CharSet: PChar);
procedure Close(Handle: PZMySQLConnect);
function Connect(Handle: PZMySQLConnect; const Host, User, Password: PChar): PZMySQLConnect;
function CreateDatabase(Handle: PZMySQLConnect; const Database: PChar): Integer;
@@ -786,6 +787,7 @@ type
function StoreResult(Handle: PZMySQLConnect): PZMySQLResult;
function UseResult(Handle: PZMySQLConnect): PZMySQLResult;
procedure FreeResult(Res: PZMySQLResult);
+ procedure SetCharacterSet(Handle: PZMySQLConnect; const CharSet: PChar);
function GetAffectedRows(Handle: PZMySQLConnect): Int64;
function FetchRow(Res: PZMySQLResult): PZMySQLRow;
@@ -869,6 +871,7 @@ type
function Rollback (Handle: PZMySQLConnect): Boolean;
function GetSQLState (Handle: PZMySQLConnect): AnsiString;
+ procedure SetCharacterSet(Handle: PZMySQLConnect; const CharSet: PChar);
function GetPreparedAffectedRows (Handle: PZMySqlPrepStmt): Int64;
function BindParameters (Handle: PZMySqlPrepStmt; bindArray: PZMysqlBindArray): Byte;
function BindResult (Handle: PZMySqlPrepStmt; bindArray: PZMysqlBindArray): Byte;
@@ -2583,6 +2586,11 @@ begin
MYSQL_API.mysql_free_result(Res);
end;
+procedure TZMySQL41PlainDriver.SetCharacterSet(Handle: PZMySQLConnect; const CharSet: PChar);
+begin
+ MYSQL_API.mysql_set_character_set(Handle, CharSet);
+end;
+
function TZMySQL41PlainDriver.GetAffectedRows(Handle: PZMySQLConnect): Int64;
begin
Result := MYSQL_API.mysql_affected_rows(Handle);
@@ -3108,6 +3116,11 @@ begin
MYSQL_API.mysql_free_result(Res);
end;
+procedure TZMySQL5PlainDriver.SetCharacterSet(Handle: PZMySQLConnect; const CharSet: PChar);
+begin
+ MYSQL_API.mysql_set_character_set(Handle, CharSet);
+end;
+
function TZMySQL5PlainDriver.GetAffectedRows(Handle: PZMySQLConnect): Int64;
begin
Result := MYSQL_API.mysql_affected_rows(Handle);