📄 provider.pas
字号:
{ ********************************************************************** }
{ }
{ Kylix and Delphi Cross-Platform Visual Component Library }
{ }
{ Copyright (C) 1997, 2001 Borland Software Corporation }
{ }
{ ********************************************************************** }
unit Provider;
{$T-,H+,X+}
interface
{$IFDEF MSWINDOWS}
uses Windows, SysUtils, VarUtils, Variants, Classes, DBClient, DB, DSIntf, ActiveX, Midas, SqlTimSt;
{$ENDIF}
{$IFDEF LINUX}
uses Libc, SysUtils, VarUtils, Variants, Classes, DBClient, DB, DSIntf, Midas, SqlTimSt;
{$ENDIF}
var
InformixLob: Boolean;
type
{ EDSWriter }
EDSWriter = class(Exception)
private
FErrorCode: Integer;
public
constructor Create(ErrMsg: string; Status: Integer);
property ErrorCode: Integer read FErrorCode;
end;
{$EXTERNALSYM EDSWriter}
(*$HPPEMIT 'namespace Provider' *)
(*$HPPEMIT '{' *)
(*$HPPEMIT 'class DELPHICLASS EDSWriter;' *)
(*$HPPEMIT '#pragma pack(push, 4)' *)
(*$HPPEMIT 'class PASCALIMPLEMENTATION EDSWriter : public Sysutils::Exception' *)
(*$HPPEMIT '{' *)
(*$HPPEMIT ' typedef Sysutils::Exception inherited;' *)
(*$HPPEMIT '' *)
(*$HPPEMIT 'private:' *)
(*$HPPEMIT ' int FErrorCode;' *)
(*$HPPEMIT '' *)
(*$HPPEMIT 'public:' *)
(*$HPPEMIT ' __fastcall EDSWriter(AnsiString ErrMsg, long Status);' *)
(*$HPPEMIT ' __property int ErrorCode = {read=FErrorCode, nodefault};' *)
(*$HPPEMIT 'public:' *)
(*$HPPEMIT ' /* Exception.CreateFmt */ inline __fastcall EDSWriter(const AnsiString Msg, const System::TVarRec * Args, const int Args_Size) : Sysutils::Exception(Msg, Args, Args_Size) { }' *)
(*$HPPEMIT ' /* Exception.CreateRes */ inline __fastcall EDSWriter(int Ident, Extended Dummy) : Sysutils::Exception(Ident, Dummy) { }' *)
(*$HPPEMIT ' /* Exception.CreateResFmt */ inline __fastcall EDSWriter(int Ident, const System::TVarRec * Args, const int Args_Size) : Sysutils::Exception(Ident, Args, Args_Size) { }' *)
(*$HPPEMIT ' /* Exception.CreateHelp */ inline __fastcall EDSWriter(const AnsiString Msg, int AHelpContext) : Sysutils::Exception(Msg, AHelpContext) { }' *)
(*$HPPEMIT ' /* Exception.CreateFmtHelp */ inline __fastcall EDSWriter(const AnsiString Msg, const System::TVarRec * Args, const int Args_Size, int AHelpContext) : Sysutils::Exception(Msg, Args, Args_Size, AHelpContext) { }' *)
(*$HPPEMIT ' /* Exception.CreateResHelp */ inline __fastcall EDSWriter(int Ident, int AHelpContext) : Sysutils::Exception(Ident, AHelpContext) { }' *)
(*$HPPEMIT ' /* Exception.CreateResFmtHelp */ inline __fastcall EDSWriter(int Ident, const System::TVarRec * Args, const int Args_Size, int AHelpContext) : Sysutils::Exception(Ident, Args, Args_Size, AHelpContext) { }' *)
(*$HPPEMIT '' *)
(*$HPPEMIT 'public:' *)
(*$HPPEMIT ' /* TObject.Destroy */ inline __fastcall virtual ~EDSWriter(void) { }' *)
(*$HPPEMIT '' *)
(*$HPPEMIT '};' *)
(*$HPPEMIT '' *)
(*$HPPEMIT '#pragma pack(pop)' *)
(*$HPPEMIT '}' *)
{ TCustomPacketWriter }
TCustomPacketWriter = class(TObject)
private
FIDSWriter: IDSWriter;
FBuffer: array of Byte;
protected
procedure AddAttribute(Area: TPcktAttrArea; const ParamName: string;
const Value: OleVariant; IncludeInDelta: Boolean);
procedure Check(Status: Integer);
property DSWriter: IDSWriter read FIDSWriter;
public
constructor Create; virtual;
destructor Destroy; override;
end;
{ TDataPacketWriter }
type
{ Forward declarations }
TGetRecordOption = (grMetaData, grReset, grXML, grXMLUTF8);
TGetRecordOptions = set of TGetRecordOption;
TDataRequestEvent = function(Sender: TObject; Input: OleVariant): OleVariant of object;
TProviderOption = (poFetchBlobsOnDemand, poFetchDetailsOnDemand,
poIncFieldProps, poCascadeDeletes, poCascadeUpdates, poReadOnly,
poAllowMultiRecordUpdates, poDisableInserts, poDisableEdits,
poDisableDeletes, poNoReset, poAutoRefresh, poPropogateChanges,
poAllowCommandText, poRetainServerOrder );
TProviderOptions = set of TProviderOption;
PPutFieldInfo = ^TPutFieldInfo;
TPutFieldProc = procedure(Info: PPutFieldInfo) of object;
TPutFieldInfo = record
FieldNo: Integer;
Field: TField;
DataSet: TDataSet;
Size: Integer;
IsDetail: Boolean;
Opened: Boolean;
PutProc: TPutFieldProc;
LocalFieldIndex: Integer;
FieldInfos: Pointer;
end;
TInfoArray = array of TPutFieldInfo;
TGetParamsEvent = procedure(DataSet: TDataSet; Params: TList) of object;
TDataPacketWriter = class(TCustomPacketWriter)
private
FConstraints: Boolean;
FPutFieldInfo: TInfoArray;
FOptions: TProviderOptions;
FPacketOptions: TGetRecordOptions;
FOnGetParams: TGetParamsEvent;
procedure FreeInfoRecords(var Info: TInfoArray);
function GetFieldIdx(const FieldName: string; const Info: TInfoArray): Integer;
procedure AddExtraFieldProps(Field: TField);
function InitPutProcs(ADataSet: TDataSet; var GlobalIdx: Integer): TInfoArray;
procedure RefreshPutProcs(ADataSet: TDataSet; var Info: TInfoArray);
protected
procedure AddColumn(const Info: TPutFieldInfo);
procedure AddConstraints(DataSet: TDataSet);
procedure AddDataSetAttributes(DataSet: TDataSet);
procedure AddFieldLinks(const Info: TInfoArray);
procedure AddIndexDefs(DataSet: TDataSet; const Info: TInfoArray);
procedure PutADTField(Info: PPutFieldInfo);
procedure PutArrayField(Info: PPutFieldInfo);
procedure PutBlobField(Info: PPutFieldInfo);
procedure PutCalcField(Info: PPutFieldInfo);
procedure PutDataSetField(Info: PPutFieldInfo);
procedure PutField(Info: PPutFieldInfo);
procedure PutStringField(Info: PPutFieldInfo);
procedure PutWideStringField(Info: PPutFieldInfo);
procedure PutVarBytesField(Info: PPutFieldInfo);
procedure Reset;
procedure WriteMetaData(DataSet: TDataSet; const Info: TInfoArray;
IsReference: Boolean = False);
function WriteDataSet(DataSet: TDataSet; var Info: TInfoArray;
RecsOut: Integer): Integer;
property OnGetParams: TGetParamsEvent read FOnGetParams write FOnGetParams;
public
destructor Destroy; override;
procedure GetDataPacket(DataSet: TDataSet; var RecsOut: Integer;
out Data: OleVariant);
property Constraints: Boolean read FConstraints write FConstraints;
property PacketOptions: TGetRecordOptions read FPacketOptions write FPacketOptions;
property Options: TProviderOptions read FOptions write FOptions;
end;
{ TPacketDataSet }
TPacketDataSet = class(TCustomClientDataSet)
private
FOldRecBuf: PChar;
FCurRecBuf: PChar;
FCurValues: PChar;
FUseCurValues: Boolean;
FWritingCurValues: Boolean;
FNewValuesModified: Boolean;
function GetStreamMetaData: Boolean;
procedure SetStreamMetaData(Value: Boolean);
procedure SetWritingCurValues(const Value: Boolean);
protected
procedure DataEvent(Event: TDataEvent; Info: Longint); override;
function GetStateFieldValue(State: TDataSetState; Field: TField): Variant; override;
procedure InternalClose; override;
procedure InternalOpen; override;
procedure InternalInitRecord(Buffer: PChar); override;
procedure SetFieldData(Field: TField; Buffer: Pointer); override;
property WritingCurValues: Boolean read FWritingCurValues write SetWritingCurValues;
public
constructor Create(AOwner: TComponent); override;
procedure AssignCurValues(Source: TDataSet); overload;
procedure AssignCurValues(const CurValues: Variant); overload;
procedure CreateFromDelta(Source: TPacketDataSet);
function HasCurValues: Boolean;
function HasMergeConflicts: Boolean;
procedure InitAltRecBuffers(CheckModified: Boolean = True);
function UpdateKind: TUpdateKind;
property NewValuesModified: Boolean read FNewValuesModified;
property StreamMetaData: Boolean read GetStreamMetaData write SetStreamMetaData;
property UseCurValues: Boolean read FUseCurValues write FUseCurValues;
end;
{ TCustomProvider }
TCustomProvider = class(TComponent)
private
FExported: Boolean;
FOnDataRequest: TDataRequestEvent;
FBeforeApplyUpdates: TRemoteEvent;
FAfterApplyUpdates: TRemoteEvent;
FBeforeGetRecords: TRemoteEvent;
FAfterGetRecords: TRemoteEvent;
FBeforeRowRequest: TRemoteEvent;
FAfterRowRequest: TRemoteEvent;
FBeforeExecute: TRemoteEvent;
FAfterExecute: TRemoteEvent;
FBeforeGetParams: TRemoteEvent;
FAfterGetParams: TRemoteEvent;
function GetData: OleVariant;
protected
function InternalApplyUpdates(const Delta: OleVariant; MaxErrors: Integer;
out ErrorCount: Integer): OleVariant; virtual; abstract;
function InternalGetRecords(Count: Integer; out RecsOut: Integer;
Options: TGetRecordOptions; const CommandText: WideString;
var Params: OleVariant): OleVariant; virtual;
function InternalRowRequest(const Row: OleVariant; RequestType: TFetchOptions): OleVariant; virtual;
procedure InternalExecute(const CommandText: WideString; var Params: OleVariant); virtual;
function InternalGetParams(Types: TParamTypes = AllParamTypes): OleVariant; virtual;
{ Event overrides }
procedure DoAfterApplyUpdates(var OwnerData: OleVariant); virtual;
procedure DoBeforeApplyUpdates(var OwnerData: OleVariant); virtual;
procedure DoAfterExecute(var OwnerData: OleVariant); virtual;
procedure DoBeforeExecute(const CommandText: WideString; var Params,
OwnerData: OleVariant); virtual;
procedure DoAfterGetParams(var OwnerData: OleVariant); virtual;
procedure DoBeforeGetParams(var OwnerData: OleVariant); virtual;
procedure DoAfterGetRecords(var OwnerData: OleVariant); virtual;
procedure DoBeforeGetRecords(Count: Integer; Options: Integer;
const CommandText: WideString; var Params, OwnerData: OleVariant); virtual;
procedure DoAfterRowRequest(var OwnerData: OleVariant); virtual;
procedure DoBeforeRowRequest(var OwnerData: OleVariant); virtual;
{ Events }
property OnDataRequest: TDataRequestEvent read FOnDataRequest write FOnDataRequest;
property BeforeApplyUpdates: TRemoteEvent read FBeforeApplyUpdates write FBeforeApplyUpdates;
property AfterApplyUpdates: TRemoteEvent read FAfterApplyUpdates write FAfterApplyUpdates;
property BeforeGetRecords: TRemoteEvent read FBeforeGetRecords write FBeforeGetRecords;
property AfterGetRecords: TRemoteEvent read FAfterGetRecords write FAfterGetRecords;
property BeforeRowRequest: TRemoteEvent read FBeforeRowRequest write FBeforeRowRequest;
property AfterRowRequest: TRemoteEvent read FAfterRowRequest write FAfterRowRequest;
property BeforeExecute: TRemoteEvent read FBeforeExecute write FBeforeExecute;
property AfterExecute: TRemoteEvent read FAfterExecute write FAfterExecute;
property BeforeGetParams: TRemoteEvent read FBeforeGetParams write FBeforeGetParams;
property AfterGetParams: TRemoteEvent read FAfterGetParams write FAfterGetParams;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function ApplyUpdates(const Delta: OleVariant; MaxErrors: Integer;
out ErrorCount: Integer): OleVariant; overload;
function ApplyUpdates(const Delta: OleVariant; MaxErrors: Integer;
out ErrorCount: Integer; var OwnerData: OleVariant): OleVariant; overload;
function GetRecords(Count: Integer; out RecsOut: Integer;
Options: Integer): OleVariant; overload;
function GetRecords(Count: Integer; out RecsOut: Integer; Options: Integer;
const CommandText: WideString; var Params,
OwnerData: OleVariant): OleVariant; overload;
function RowRequest(const Row: OleVariant; RequestType: Integer;
var OwnerData: OleVariant): OleVariant;
procedure Execute(const CommandText: WideString; var Params,
OwnerData: OleVariant);
function GetParams(var OwnerData: OleVariant): OleVariant;
function DataRequest(Input: OleVariant): OleVariant; virtual;
property Data: OleVariant read GetData;
property Exported: Boolean read FExported write FExported default True;
end;
const
ResetOption: Integer = 1 shl ord(grReset);
MetaDataOption: Integer = 1 shl ord(grMetaData);
XMLOption: Integer = 1 shl ord(grXML);
XMLUTF8Option: Integer = 1 shl ord(grXMLUTF8);
{ TBaseProvider }
type
TUpdateTree = class;
TCustomResolver = class;
TResolverResponse = (rrSkip, rrAbort, rrMerge, rrApply, rrIgnore);
TProviderDataEvent = procedure(Sender: TObject; DataSet: TCustomClientDataSet) of object;
TBeforeUpdateRecordEvent = procedure(Sender: TObject; SourceDS: TDataSet;
DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean) of object;
TAfterUpdateRecordEvent = procedure(Sender: TObject; SourceDS: TDataSet;
DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind) of object;
TResolverErrorEvent = procedure(Sender: TObject; DataSet: TCustomClientDataSet;
E: EUpdateError; UpdateKind: TUpdateKind; var Response: TResolverResponse) of object;
TBaseProvider = class(TCustomProvider)
private
FDataDS: TPacketDataSet;
FUpdateMode: TUpdateMode;
FResolver: TCustomResolver;
FOnGetData: TProviderDataEvent;
FOnUpdateData: TProviderDataEvent;
FOnUpdateError: TResolverErrorEvent;
FBeforeUpdateRecord: TBeforeUpdateRecordEvent;
FAfterUpdateRecord: TAfterUpdateRecordEvent;
FProviderOptions: TProviderOptions;
protected
procedure CheckResolver;
function CreateResolver: TCustomResolver; virtual;
procedure FreeResolver;
procedure CreateDataPacket(PacketOpts: TGetRecordOptions;
ProvOpts: TProviderOptions; var RecsOut: Integer; var Data: OleVariant); virtual;
procedure DoOnGetData(var Data: OleVariant);
procedure DoOnUpdateData(Delta: TPacketDataSet);
procedure LocateRecord(Source, Delta: TDataSet); virtual;
procedure UpdateRecord(Source, Delta: TDataSet; BlobsOnly, KeyOnly: Boolean); virtual;
procedure FetchDetails(Source, Delta: TDataSet); virtual;
function InternalRowRequest(const Row: OleVariant;
RequestType: TFetchOptions): OleVariant; override;
function InternalApplyUpdates(const Delta: OleVariant; MaxErrors: Integer;
out ErrorCount: Integer): OleVariant; override;
function InternalGetRecords(Count: Integer; out RecsOut: Integer;
Options: TGetRecordOptions; const CommandText: WideString;
var Params: OleVariant): OleVariant; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Resolver: TCustomResolver read FResolver;
property Options: TProviderOptions read FProviderOptions
write FProviderOptions default [];
property UpdateMode: TUpdateMode read FUpdateMode write FUpdateMode default upWhereAll;
property OnDataRequest;
property OnGetData: TProviderDataEvent read FOnGetData write FOnGetData;
property OnUpdateData: TProviderDataEvent read FOnUpdateData write FOnUpdateData;
property OnUpdateError: TResolverErrorEvent read FOnUpdateError write FOnUpdateError;
property BeforeUpdateRecord: TBeforeUpdateRecordEvent read FBeforeUpdateRecord
write FBeforeUpdateRecord;
property AfterUpdateRecord: TAfterUpdateRecordEvent read FAfterUpdateRecord
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -