mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2026-03-13 09:24:25 +08:00
Add preliminary Unicode support.
(Requires a newer libmysql.dll, so you may want to get the strict_dll patch which is not in Zeos AFAIK.)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 <code>ResultSet</code> object as
|
||||
@@ -693,11 +699,15 @@ end;
|
||||
<code>NULL</code>, the value returned is <code>null</code>
|
||||
}
|
||||
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;
|
||||
|
||||
{**
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user