From ee1feb5521de9a8ad9a653e9fe4283ce664748a1 Mon Sep 17 00:00:00 2001 From: "rosenfield.albert" Date: Mon, 16 Jun 2008 21:20:15 +0000 Subject: [PATCH] Reimplement ANSI support to keep nutcases armed with v3.23 mysql servers happy. Fixes issue #497. --- components/zeosdbo/src/dbc/ZDbcMySql.pas | 22 +++++++++++++------ .../zeosdbo/src/dbc/ZDbcMySqlResultSet.pas | 10 +++++++-- .../zeosdbo/src/dbc/ZDbcMySqlStatement.pas | 6 ++++- .../zeosdbo/src/plain/ZPlainMySqlDriver.pas | 3 +++ 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/components/zeosdbo/src/dbc/ZDbcMySql.pas b/components/zeosdbo/src/dbc/ZDbcMySql.pas index 7dc9e983..7240f65f 100644 --- a/components/zeosdbo/src/dbc/ZDbcMySql.pas +++ b/components/zeosdbo/src/dbc/ZDbcMySql.pas @@ -99,6 +99,7 @@ type function GetPlainDriver: IZMySQLPlainDriver; function GetConnectionHandle: PZMySQLConnect; + function GetAnsiMode: Boolean; end; {** Implements MySQL Database Connection. } @@ -107,7 +108,7 @@ type FCatalog: string; FPlainDriver: IZMySQLPlainDriver; FHandle: PZMySQLConnect; - FClientCodePage: string; + FAnsiMode: Boolean; public constructor Create(Driver: IZDriver; const Url: string; PlainDriver: IZMySQLPlainDriver; const HostName: string; Port: Integer; @@ -141,6 +142,7 @@ type function GetPlainDriver: IZMySQLPlainDriver; function GetConnectionHandle: PZMySQLConnect; function GetDescription: AnsiString; + function GetAnsiMode: Boolean; end; @@ -358,9 +360,6 @@ begin AutoCommit := True; TransactIsolationLevel := tiNone; - { Processes connection properties. } - FClientCodePage := Trim(Info.Values['codepage']); - Open; end; @@ -438,10 +437,14 @@ begin end; DriverManager.LogMessage(lcConnect, FPlainDriver.GetProtocol, LogMessage); + FAnsiMode := FPlainDriver.GetServerVersion(FHandle) < 40100; + { Sets a client codepage. } - FPlainDriver.SetCharacterSet(FHandle, 'utf8'); - CheckMySQLError(FPlainDriver, FHandle, lcExecute, LogMessage); - DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, LogMessage); + if not FAnsiMode then begin + FPlainDriver.SetCharacterSet(FHandle, 'utf8'); + CheckMySQLError(FPlainDriver, FHandle, lcExecute, LogMessage); + DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, LogMessage); + end; { Sets transaction isolation level. } OldLevel := TransactIsolationLevel; @@ -781,6 +784,11 @@ begin Result := self.FPlainDriver.GetDescription; end; +function TZMySQLConnection.GetAnsiMode: Boolean; +begin + Result := FAnsiMode; +end; + initialization MySQLDriver := TZMySQLDriver.Create; DriverManager.RegisterDriver(MySQLDriver); diff --git a/components/zeosdbo/src/dbc/ZDbcMySqlResultSet.pas b/components/zeosdbo/src/dbc/ZDbcMySqlResultSet.pas index 55e0248a..d5796b80 100644 --- a/components/zeosdbo/src/dbc/ZDbcMySqlResultSet.pas +++ b/components/zeosdbo/src/dbc/ZDbcMySqlResultSet.pas @@ -269,7 +269,10 @@ begin // thus the value returned below will always be 0. Same goes for prepared // statements, unless STMT_ATTR_UPDATE_MAX_LENGTH is specified. FieldWidthMax := FPlainDriver.GetFieldMaxLength(FieldHandle); - if FPlainDriver.GetFieldCollationId(FieldHandle) <> COLLATION_BINARY then begin + if + (FPlainDriver.GetFieldCollationId(FieldHandle) <> COLLATION_BINARY) and + (FPlainDriver.GetFieldCollationId(FieldHandle) <> COLLATION_NONE) + then begin // Results are always utf-8. The MySQL utf-8 encoder can produce sequences that // consist of up to 3 bytes per character. That's the number which the MySQL // C API will return when queried, since the server (and the driver) returns @@ -419,7 +422,10 @@ end; function TZMySQLResultSet.GetUnicodeString(ColumnIndex: Integer): WideString; begin - Result := UTF8Decode(GetRawData(ColumnIndex)); + if not ((Statement.GetConnection) as IZMySQLConnection).GetAnsiMode then + Result := UTF8Decode(GetRawData(ColumnIndex)) + else + Result := WideString(GetRawData(ColumnIndex)); end; {** diff --git a/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas b/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas index 414d299a..2e8d027c 100644 --- a/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas +++ b/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas @@ -177,9 +177,13 @@ end; given query; never null } function TZMySQLStatement.ExecuteQuery(const SQL: WideString): IZResultSet; +var + nativeSql: string; begin Result := nil; - if FPlainDriver.ExecQuery(FHandle, PChar(UTF8Encode(SQL))) = 0 then + if not (Connection as IZMySQLConnection).GetAnsiMode then nativeSql := UTF8Encode(SQL) + else nativeSql := String(SQL); + if FPlainDriver.ExecQuery(FHandle, PChar(nativeSql)) = 0 then begin DriverManager.LogMessage(lcExecute, FPlainDriver.GetProtocol, SQL); {$IFDEF ENABLE_MYSQL_DEPRECATED} diff --git a/components/zeosdbo/src/plain/ZPlainMySqlDriver.pas b/components/zeosdbo/src/plain/ZPlainMySqlDriver.pas index 5cc27052..c381fd78 100644 --- a/components/zeosdbo/src/plain/ZPlainMySqlDriver.pas +++ b/components/zeosdbo/src/plain/ZPlainMySqlDriver.pas @@ -153,6 +153,9 @@ const _CLIENT_REMEMBER_OPTIONS = 2147483648; {Enable/disable multi-results } COLLATION_BINARY = 63; + // Equivalent to COLLATION_BINARY, this is what + // a new driver returns when connected to a pre-4.1 server. + COLLATION_NONE = 0; type PZMySQLConnect = Pointer;