为支援Unicode准备-VCL和dbExpress

BDS 2006的功能文件中著明了dbExpressMS SQL Server驱动程式支援MS SQL 2005以及Unicode,这非常的有趣。为什么? 因为这牵涉到了许多的事情。首先许多Delphi/C++Builder的使用者早已要求Borland推出支援UnicodeVCL架框,这个支援UnicodeVCL架框早在Delphi 2时我便向Delphi R&D团队要求,因为当时我在台湾负责和新加坡同事为Delphi开发中文套件就我就觉得有这个需要。而当时Anders也认为这很重要,也准备为VCL架框加入Unicode的能力,可惜的是人去楼空,随著Anders的离开这个功能也就一直被悬而未决。

 

随著多语言环境不断的成长和成熟,UnicodeVCL架框似乎再也不能拖了,因此Borland2005DelphiRoadmap上宣示了在Delphi 64位元的版本中,VCL架框将支援Unicode。那么对于目前需要UnicodeDelphi/C++Builder开发人员要怎么办呢? 就我所知,许多人目前都是使用TNT控制项来解决这个需求:

 

http://www.tntware.com/delphicontrols/unicode/

 

即然VCL架框在未来才准备支援Unicode,而BDS 2006MS SQL Server dbExpress驱动程式已经支援了Unicode,那么这是怎么做到的? 其实Borland虽然在未来才准备让VCL架框支援Unicode,但是在BDS 2006VCL架框中却已经开始了这个工作,修改了许多VCL的方法,特性,事件和类别,介面等。也加入了一些新的类别,如此一来才能让dbExpress驱动程式和VCL架框配合。例如在BDS 2006VCL架框中,和dbExpress相关的TCustomSQLDataSet类别已经改成是从TWideDataSet继承下来,而不再是像Delphi 2005和以前的版本,是直接从TDataSet继承下来。

  TCustomSQLDataSet = class(TWideDataSet)

  Private

   

 

TWideDataset是一个新加入的类别,仔细看看TWideDataSet类别,主要是加入了WideString的支援宣告,为Unicode做准备,此外TWideDataset也复载了许多支援WideString的方法,为执行包含UnicodeSQL叙述和命令做准备。

{ TWideDataset }

 

  TWideDataSet = class(TDataSet, IProviderSupport2)

  protected

    function PSExecuteStatement(const ASQL: string; AParams: TParams;

      ResultSet: Pointer = nil): Integer; overload; override; deprecated;

    function PSExecuteStatement(const ASQL: WideString; AParams: TParams;

      ResultSet: Pointer = nil): Integer; overload; override;

    function PSGetCommandText: string; override; deprecated;

    function PSGetCommandTextW: WideString; override;

    function PSGetKeyFields: string; override; deprecated;

    function PSGetKeyFieldsW: WideString; override;

    function PSGetQuoteChar: string; override; deprecated;

    function PSGetQuoteCharW: WideString; override;

    function PSGetTableName: string; override; deprecated;

    function PSGetTableNameW: WideString; override;

    procedure PSSetCommandText(const CommandText: string); overload; override; deprecated;

    procedure PSSetCommandText(const CommandText: WideString); overload; override;

    function IProviderSupport2.PSGetCommandText = PSGetCommandTextW;

    function IProviderSupport2.PSGetKeyFields = PSGetKeyFieldsW;

    function IProviderSupport2.PSGetQuoteChar = PSGetQuoteCharW;

    function IProviderSupport2.PSGetTableName = PSGetTableNameW;

  end;

 

除此之外,对于dbExpress来说,BDS 2006也加入了一些新的wrapper类别来封装dbExpress的介面,例如对于dbExpressISQLMetaData介面,Delphi 2005加入了TISQLMetaData25封装类别,BDS 2006则加入了TISQLMetaData30封装类别。TISQLMetaData25封装类别复载了抽象虚拟类别 : TISQLMetaData抽象虚拟类别,并且使用做为实作的介面。

  TISQLMetaData25 = class(TISQLMetaData)

  protected

    I : ISQLMetaData25;

  public

    constructor Create(newMetaData: ISQLMetaData25);

    destructor Destroy; override;

    function SetOption(eDOption: TSQLMetaDataOption;

                     PropValue: LongInt): SQLResult; override;

    function SetStringOption(eDOption: TSQLMetaDataOption;

                     const str: WideString): SQLResult; override;

    function GetOption(eDOption: TSQLMetaDataOption; PropValue: Pointer;

                     MaxLength: SmallInt; out Length: SmallInt): SQLResult; override;

    function GetStringOption(eDOption: TSQLMetaDataOption;

                     var str: WideString): SQLResult; override;

    function getObjectList(eObjType: TSQLObjectType; var Cursor: TISQLCursor):

                     SQLResult; override;

    function getTables(TableName: PWideChar; TableType: LongWord;

                     var Cursor: TISQLCursor): SQLResult; override;

    function getProcedures(ProcedureName: PWideChar; ProcType: LongWord;

                     var Cursor: TISQLCursor): SQLResult; override;

    function getColumns(TableName: PWideChar; ColumnName: PWideChar;

                     ColType: LongWord; var Cursor: TISQLCursor): SQLResult; override;

    function getProcedureParams(ProcName: PWideChar; ParamName: PWideChar;

                     var Cursor: TISQLCursor): SQLResult; override;

    function getIndices(TableName: PWideChar; IndexType: LongWord;

                     var Cursor: TISQLCursor): SQLResult; override;

    function getErrorMessage(Error: PWideChar): SQLResult; overload; override;

    function getErrorMessageLen(out ErrorLen: SmallInt): SQLResult; override;

    function getErrorMessage(var Error: WideString): SQLResult; overload; override;

  end;

 

TISQLMetaData30也是复载了抽象虚拟类别 : TISQLMetaData抽象虚拟类别,但是使用了ISQLMetaData30介面做为实作的依据。

  TISQLMetaData30 = class(TISQLMetaData)

  protected

    I : ISQLMetaData30;

  public

    constructor Create(newMetaData: ISQLMetaData30);

    destructor Destroy; override;

    function SetOption(eDOption: TSQLMetaDataOption;

                     PropValue: LongInt): SQLResult; override;

    function SetStringOption(eDOption: TSQLMetaDataOption;

                     const str: WideString): SQLResult; override;

    function GetOption(eDOption: TSQLMetaDataOption; PropValue: Pointer;

                     MaxLength: SmallInt; out Length: SmallInt): SQLResult; override;

    function GetStringOption(eDOption: TSQLMetaDataOption;

                     var str: WideString): SQLResult; override;

    function getObjectList(eObjType: TSQLObjectType; var Cursor: TISQLCursor):

                     SQLResult; override;

    function getTables(TableName: PWideChar; TableType: LongWord;

                     var Cursor: TISQLCursor): SQLResult; override;

    function getProcedures(ProcedureName: PWideChar; ProcType: LongWord;

                     var Cursor: TISQLCursor): SQLResult; override;

    function getColumns(TableName: PWideChar; ColumnName: PWideChar;

                     ColType: LongWord; var Cursor: TISQLCursor): SQLResult; override;

    function getProcedureParams(ProcName: PWideChar; ParamName: PWideChar;

                     var Cursor: TISQLCursor): SQLResult; override;

    function getIndices(TableName: PWideChar; IndexType: LongWord;

                     var Cursor: TISQLCursor): SQLResult; override;

    function getErrorMessage(Error: PWideChar): SQLResult; overload; override;

    function getErrorMessageLen(out ErrorLen: SmallInt): SQLResult; override;

    function getErrorMessage(var Error: WideString): SQLResult; overload; override;

  end;

 

那么ISQLMetaData25ISQLMetaData30有什么不同? 细节看看下面这两个介面的差异:

ISQLMetaData25 = interface(ISQLMetaData)

   function SetOption(eDOption: TSQLMetaDataOption;

                     PropValue: LongInt): SQLResult; stdcall;

   function GetOption(eDOption: TSQLMetaDataOption; PropValue: Pointer;

                     MaxLength: SmallInt; out Length: SmallInt): SQLResult; stdcall;

   function getObjectList(eObjType: TSQLObjectType; out Cursor: ISQLCursor25):

                     SQLResult; stdcall;

   function getTables(TableName: PChar; TableType: LongWord;

                     out Cursor: ISQLCursor25): SQLResult; stdcall;

   function getProcedures(ProcedureName: PChar; ProcType: LongWord;

                     out Cursor: ISQLCursor25): SQLResult; stdcall;

   function getColumns(TableName: PChar; ColumnName: PChar;

                     ColType: LongWord; Out Cursor: ISQLCursor25): SQLResult; stdcall;

   function getProcedureParams(ProcName: PChar; ParamName: PChar;

                     out Cursor: ISQLCursor25): SQLResult; stdcall;

   function getIndices(TableName: PChar; IndexType: LongWord;

                     out Cursor: ISQLCursor25): SQLResult; stdcall;

   function getErrorMessage(Error: PChar): SQLResult; overload; stdcall;

   function getErrorMessageLen(out ErrorLen: SmallInt): SQLResult; stdcall;

end;

 

我们可以清楚的看到ISQLMetaData25ISQLMetaData30介面不同的地方是ISQLMetaData30完全使用WideString的格式来处理后理后端的资料来源,而ISQLMetaData25则是使用一般的字串格式,这代表ISQLMetaData30介面能够处理Unicode的资料。当然,BDS 2005其他封装dbExpress介面的wrapper类别也是类似的。

ISQLMetaData30 = interface(ISQLMetaData)

   function SetOption(eDOption: TSQLMetaDataOption;

                     PropValue: LongInt): SQLResult; stdcall;

   function GetOption(eDOption: TSQLMetaDataOption; PropValue: Pointer;

                     MaxLength: SmallInt; out Length: SmallInt): SQLResult; stdcall;

   function getObjectList(eObjType: TSQLObjectType; out Cursor: ISQLCursor30):

                     SQLResult; stdcall;

   function getTables(TableName: PWideChar; TableType: LongWord;

                     out Cursor: ISQLCursor30): SQLResult; stdcall;

   function getProcedures(ProcedureName: PWideChar; ProcType: LongWord;

                     out Cursor: ISQLCursor30): SQLResult; stdcall;

   function getColumns(TableName: PWideChar; ColumnName: PWideChar;

                     ColType: LongWord; Out Cursor: ISQLCursor30): SQLResult; stdcall;

   function getProcedureParams(ProcName: PWideChar; ParamName: PWideChar;

                     out Cursor: ISQLCursor30): SQLResult; stdcall;

   function getIndices(TableName: PWideChar; IndexType: LongWord;

                     out Cursor: ISQLCursor30): SQLResult; stdcall;

   function getErrorMessage(Error: PWideChar): SQLResult; overload; stdcall;

   function getErrorMessageLen(out ErrorLen: SmallInt): SQLResult; stdcall;

end;

 

现在封装dbExpressVCL类别都已经完成了对于Unicode的支援,就等Borland推出支援各种关连资料库的dbExpress驱动程式即可。而VCL架框也在稳定的朝向支援Unicode的方向前进,依照DelphiRoadmap,我们将可望在Borland推出代号为HighLanderBDS之后,看到全新架构的VCL架框。

 

在此时和dbExpress 3.0玩玩真的很有意思, dbExpress 3.0不但功能更多了, 效率也比以前的dbExpress快上了许多, 可以说是目前Win32下最好的资料存取技术了.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章