📄 ibcustomdataset.pas
字号:
{************************************************************************}
{ }
{ Borland Delphi Visual Component Library }
{ InterBase Express core components }
{ }
{ Copyright (c) 1998-2001 Borland Software Corporation }
{ }
{ InterBase Express is based in part on the product }
{ Free IB Components, written by Gregory H. Deatz for }
{ Hoagland, Longo, Moran, Dunst & Doukas Company. }
{ Free IB Components is used under license. }
{ }
{ The contents of this file are subject to the InterBase }
{ Public License Version 1.0 (the "License"); you may not }
{ use this file except in compliance with the License. You may obtain }
{ a copy of the License at http://www.borland.com/interbase/IPL.html }
{ Software distributed under the License is distributed on }
{ an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
{ express or implied. See the License for the specific language }
{ governing rights and limitations under the License. }
{ The Original Code was created by InterBase Software Corporation }
{ and its successors. }
{ Portions created by Borland Software Corporation are Copyright }
{ (C) Borland Software Corporation. All Rights Reserved. }
{ Contributor(s): Jeff Overcash }
{ }
{************************************************************************}
unit IBCustomDataSet;
interface
uses
SysUtils, Classes, Variants,
{$IFDEF MSWINDOWS}
Windows,
{$ENDIF}
{$IFDEF LINUX}
Libc, Types,
{$ENDIF}
IBExternals, IB, IBHeader, IBDatabase, IBSQL, Db, IBUtils, IBBlob;
const
BufferCacheSize = 1000; { Allocate cache in this many record chunks}
UniCache = 2; { Uni-directional cache is 2 records big }
type
TIBCustomDataSet = class;
TIBDataSet = class;
TIBDataSetUpdateObject = class(TComponent)
private
FRefreshSQL: TStrings;
procedure SetRefreshSQL(value: TStrings);
protected
function GetDataSet: TIBCustomDataSet; virtual; abstract;
procedure SetDataSet(ADataSet: TIBCustomDataSet); virtual; abstract;
procedure Apply(UpdateKind: TUpdateKind); virtual; abstract;
function GetSQL(UpdateKind: TUpdateKind): TStrings; virtual; abstract;
property DataSet: TIBCustomDataSet read GetDataSet write SetDataSet;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property RefreshSQL: TStrings read FRefreshSQL write SetRefreshSQL;
end;
PDateTime = ^TDateTime;
TBlobDataArray = array[0..0] of TIBBlobStream;
PBlobDataArray = ^TBlobDataArray;
{ TIBCustomDataSet }
TFieldData = record
fdDataType: Short;
fdDataScale: Short;
fdNullable: Boolean;
fdIsNull: Boolean;
fdDataSize: Short;
fdDataLength: Short;
fdDataOfs: Integer;
end;
PFieldData = ^TFieldData;
TCachedUpdateStatus = (
cusUnmodified, cusModified, cusInserted,
cusDeleted, cusUninserted
);
TIBDBKey = record
DBKey: array[0..7] of Byte;
end;
PIBDBKey = ^TIBDBKey;
TRecordData = record
rdBookmarkFlag: TBookmarkFlag;
rdFieldCount: Short;
rdRecordNumber: Long;
rdCachedUpdateStatus: TCachedUpdateStatus;
rdUpdateStatus: TUpdateStatus;
rdSavedOffset: DWORD;
rdDBKey: TIBDBKey;
rdFields: array[1..1] of TFieldData;
end;
PRecordData = ^TRecordData;
{ TIBStringField allows us to have strings longer than 8196 }
TIBStringField = class(TStringField)
public
constructor create(AOwner: TComponent); override;
class procedure CheckTypeSize(Value: Integer); override;
function GetAsString: string; override;
function GetAsVariant: Variant; override;
function GetValue(var Value: string): Boolean;
procedure SetAsString(const Value: string); override;
end;
{ TIBBCDField }
{ Actually, there is no BCD involved in this type,
instead it deals with currency types.
In IB, this is an encapsulation of Numeric (x, y)
where x < 18 and y <= 4.
Note: y > 4 will default to Floats
}
TIBBCDField = class(TBCDField)
protected
class procedure CheckTypeSize(Value: Integer); override;
function GetAsCurrency: Currency; override;
function GetAsString: string; override;
function GetAsVariant: Variant; override;
function GetDataSize: Integer; override;
public
constructor Create(AOwner: TComponent); override;
published
property Size default 8;
end;
TIBDataLink = class(TDetailDataLink)
private
FDataSet: TIBCustomDataSet;
protected
procedure ActiveChanged; override;
procedure RecordChanged(Field: TField); override;
function GetDetailDataSet: TDataSet; override;
procedure CheckBrowseMode; override;
public
constructor Create(ADataSet: TIBCustomDataSet);
destructor Destroy; override;
end;
TIBGeneratorApplyEvent = (gamOnNewRecord, gamOnPost, gamOnServer);
TIBGeneratorField = class(TPersistent)
private
FField: string;
FGenerator: string;
FIncrementBy: Integer;
DataSet: TIBCustomDataSet;
FApplyEvent: TIBGeneratorApplyEvent;
function IsComplete: Boolean;
public
constructor Create(ADataSet: TIBCustomDataSet);
function ValueName: string;
procedure Apply;
procedure Assign(Source: TPersistent); override;
published
property Field : string read FField write FField;
property Generator : string read FGenerator write FGenerator;
property IncrementBy : Integer read FIncrementBy write FIncrementBy default 1;
property ApplyEvent : TIBGeneratorApplyEvent read FApplyEvent write FApplyEvent default gamOnNewRecord;
end;
{ TIBCustomDataSet }
TIBUpdateAction = (uaFail, uaAbort, uaSkip, uaRetry, uaApply, uaApplied);
TIBUpdateErrorEvent = procedure(DataSet: TDataSet; E: EDatabaseError;
UpdateKind: TUpdateKind; var UpdateAction: TIBUpdateAction)
of object;
TIBUpdateRecordEvent = procedure(DataSet: TDataSet; UpdateKind: TUpdateKind;
var UpdateAction: TIBUpdateAction) of object;
TIBUpdateRecordTypes = set of TCachedUpdateStatus;
TLiveMode = (lmInsert, lmModify, lmDelete, lmRefresh);
TLiveModes = Set of TLiveMode;
TIBCustomDataSet = class(TDataset)
private
FNeedsRefresh: Boolean;
FForcedRefresh: Boolean;
FIBLoaded: Boolean;
FBase: TIBBase;
FBlobCacheOffset: Integer;
FBlobStreamList: TList;
FBufferChunks: Integer;
FBufferCache,
FOldBufferCache: PChar;
FBufferChunkSize,
FCacheSize,
FOldCacheSize: Integer;
FFilterBuffer: PChar;
FBPos,
FOBPos,
FBEnd,
FOBEnd: DWord;
FCachedUpdates: Boolean;
FCalcFieldsOffset: Integer;
FCurrentRecord: Long;
FDeletedRecords: Long;
FModelBuffer,
FOldBuffer: PChar;
FOpen: Boolean;
FInternalPrepared: Boolean;
FQDelete,
FQInsert,
FQRefresh,
FQSelect,
FQModify: TIBSQL;
FRecordBufferSize: Integer;
FRecordCount: Integer;
FRecordSize: Integer;
FUniDirectional: Boolean;
FUpdateMode: TUpdateMode;
FUpdateObject: TIBDataSetUpdateObject;
FParamCheck: Boolean;
FUpdatesPending: Boolean;
FUpdateRecordTypes: TIBUpdateRecordTypes;
FMappedFieldPosition: array of Integer;
FDataLink: TIBDataLink;
FStreamedActive : Boolean;
FLiveMode: TLiveModes;
FGeneratorField: TIBGeneratorField;
FRowsAffected: Integer;
FBeforeDatabaseDisconnect,
FAfterDatabaseDisconnect,
FDatabaseFree: TNotifyEvent;
FOnUpdateError: TIBUpdateErrorEvent;
FOnUpdateRecord: TIBUpdateRecordEvent;
FBeforeTransactionEnd,
FAfterTransactionEnd,
FTransactionFree: TNotifyEvent;
function GetSelectStmtHandle: TISC_STMT_HANDLE;
procedure SetUpdateMode(const Value: TUpdateMode);
procedure SetUpdateObject(Value: TIBDataSetUpdateObject);
function AdjustCurrentRecord(Buffer: Pointer; GetMode: TGetMode): TGetResult;
procedure AdjustRecordOnInsert(Buffer: Pointer);
function CanEdit: Boolean;
function CanInsert: Boolean;
function CanDelete: Boolean;
function CanRefresh: Boolean;
procedure CheckEditState;
procedure ClearBlobCache;
procedure CopyRecordBuffer(Source, Dest: Pointer);
procedure DoBeforeDatabaseDisconnect(Sender: TObject);
procedure DoAfterDatabaseDisconnect(Sender: TObject);
procedure DoDatabaseFree(Sender: TObject);
procedure DoBeforeTransactionEnd(Sender: TObject);
procedure DoAfterTransactionEnd(Sender: TObject);
procedure DoTransactionFree(Sender: TObject);
procedure FetchCurrentRecordToBuffer(Qry: TIBSQL; RecordNumber: Integer;
Buffer: PChar);
function GetDatabase: TIBDatabase;
function GetDBHandle: PISC_DB_HANDLE;
function GetDeleteSQL: TStrings;
function GetInsertSQL: TStrings;
function GetSQLParams: TIBXSQLDA;
function GetRefreshSQL: TStrings;
function GetSelectSQL: TStrings;
function GetStatementType: TIBSQLTypes;
function GetModifySQL: TStrings;
function GetTransaction: TIBTransaction;
function GetTRHandle: PISC_TR_HANDLE;
procedure InternalDeleteRecord(Qry: TIBSQL; Buff: Pointer);
function InternalLocate(const KeyFields: string; const KeyValues: Variant;
Options: TLocateOptions): Boolean;
procedure InternalPostRecord(Qry: TIBSQL; Buff: Pointer);
procedure InternalRevertRecord(RecordNumber: Integer);
function IsVisible(Buffer: PChar): Boolean;
procedure SaveOldBuffer(Buffer: PChar);
procedure SetBufferChunks(Value: Integer);
procedure SetDatabase(Value: TIBDatabase);
procedure SetDeleteSQL(Value: TStrings);
procedure SetInsertSQL(Value: TStrings);
procedure SetInternalSQLParams(Qry: TIBSQL; Buffer: Pointer);
procedure SetRefreshSQL(Value: TStrings);
procedure SetSelectSQL(Value: TStrings);
procedure SetModifySQL(Value: TStrings);
procedure SetTransaction(Value: TIBTransaction);
procedure SetUpdateRecordTypes(Value: TIBUpdateRecordTypes);
procedure SetUniDirectional(Value: Boolean);
procedure RefreshParams;
procedure SQLChanging(Sender: TObject);
function AdjustPosition(FCache: PChar; Offset: DWORD;
Origin: Integer): Integer;
procedure ReadCache(FCache: PChar; Offset: DWORD; Origin: Integer;
Buffer: PChar);
procedure ReadRecordCache(RecordNumber: Integer; Buffer: PChar;
ReadOldBuffer: Boolean);
procedure WriteCache(FCache: PChar; Offset: DWORD; Origin: Integer;
Buffer: PChar);
procedure WriteRecordCache(RecordNumber: Integer; Buffer: PChar);
function InternalGetRecord(Buffer: PChar; GetMode: TGetMode;
DoCheck: Boolean): TGetResult;
procedure SetGeneratorField(const Value: TIBGeneratorField);
function InternalGetFieldData(Field: TField; Buffer: Pointer): Boolean;
procedure InternalSetFieldData(Field: TField; Buffer: Pointer); virtual;
function GetPlan: String;
protected
procedure ActivateConnection;
function ActivateTransaction: Boolean;
procedure DeactivateTransaction;
procedure CheckDatasetClosed;
procedure CheckDatasetOpen;
function GetActiveBuf: PChar;
procedure InternalBatchInput(InputObject: TIBBatchInput); virtual;
procedure InternalBatchOutput(OutputObject: TIBBatchOutput); virtual;
procedure InternalPrepare; virtual;
procedure InternalUnPrepare; virtual;
procedure InternalExecQuery; virtual;
procedure InternalRefreshRow; virtual;
procedure InternalSetParamsFromCursor; virtual;
procedure CheckNotUniDirectional;
procedure SetActive(Value: Boolean); override;
{ IProviderSupport }
procedure PSEndTransaction(Commit: Boolean); override;
function PSExecuteStatement(const ASQL: string; AParams: TParams;
ResultSet: Pointer = nil): Integer; override;
function PsGetTableName: string; override;
function PSGetQuoteChar: string; override;
function PSGetUpdateException(E: Exception; Prev: EUpdateError): EUpdateError; override;
function PSInTransaction: Boolean; override;
function PSIsSQLBased: Boolean; override;
function PSIsSQLSupported: Boolean; override;
procedure PSStartTransaction; override;
procedure PSReset; override;
function PSUpdateRecord(UpdateKind: TUpdateKind; Delta: TDataSet): Boolean; override;
{ TDataSet support }
procedure InternalInsert; override;
procedure InitRecord(Buffer: PChar); override;
procedure Disconnect; virtual;
function ConstraintsStored: Boolean;
procedure ClearCalcFields(Buffer: PChar); override;
procedure CreateFields; override;
function AllocRecordBuffer: PChar; override;
procedure DoBeforeDelete; override;
procedure DoBeforeEdit; override;
procedure DoBeforeInsert; override;
procedure FreeRecordBuffer(var Buffer: PChar); override;
procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
function GetCanModify: Boolean; override;
function GetDataSource: TDataSource; override;
function GetFieldClass(FieldType: TFieldType): TFieldClass; override;
function GetRecNo: Integer; override;
function GetRecord(Buffer: PChar; GetMode: TGetMode;
DoCheck: Boolean): TGetResult; override;
function GetRecordCount: Integer; override;
function GetRecordSize: Word; override;
procedure InternalAddRecord(Buffer: Pointer; Append: Boolean); override;
procedure InternalCancel; override;
procedure InternalClose; override;
procedure InternalDelete; override;
procedure InternalFirst; override;
procedure InternalGotoBookmark(Bookmark: Pointer); override;
procedure InternalHandleException; override;
procedure InternalInitFieldDefs; override;
procedure InternalInitRecord(Buffer: PChar); override;
procedure InternalLast; override;
procedure InternalOpen; override;
procedure InternalPost; override;
procedure InternalRefresh; override;
procedure InternalSetToRecord(Buffer: PChar); override;
function IsCursorOpen: Boolean; override;
procedure ReQuery;
procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
procedure SetCachedUpdates(Value: Boolean);
procedure SetDataSource(Value: TDataSource);
procedure SetFieldData(Field : TField; Buffer : Pointer); override;
procedure SetFieldData(Field : TField; Buffer : Pointer;
NativeFormat : Boolean); overload; override;
procedure SetRecNo(Value: Integer); override;
procedure DoOnNewRecord; override;
procedure Loaded; override;
protected
{Likely to be made public by descendant classes}
property SQLParams: TIBXSQLDA read GetSQLParams;
property Params: TIBXSQLDA read GetSQLParams;
property InternalPrepared: Boolean read FInternalPrepared;
property QDelete: TIBSQL read FQDelete;
property QInsert: TIBSQL read FQInsert;
property QRefresh: TIBSQL read FQRefresh;
property QSelect: TIBSQL read FQSelect;
property QModify: TIBSQL read FQModify;
property StatementType: TIBSQLTypes read GetStatementType;
property SelectStmtHandle: TISC_STMT_HANDLE read GetSelectStmtHandle;
property LiveMode : TLiveModes read FLiveMode;
{Likely to be made published by descendant classes}
property BufferChunks: Integer read FBufferChunks write SetBufferChunks;
property CachedUpdates: Boolean read FCachedUpdates write SetCachedUpdates;
property UniDirectional: Boolean read FUniDirectional write SetUniDirectional default False;
property DeleteSQL: TStrings read GetDeleteSQL write SetDeleteSQL;
property InsertSQL: TStrings read GetInsertSQL write SetInsertSQL;
property RefreshSQL: TStrings read GetRefreshSQL write SetRefreshSQL;
property SelectSQL: TStrings read GetSelectSQL write SetSelectSQL;
property ModifySQL: TStrings read GetModifySQL write SetModifySQL;
property UpdateMode: TUpdateMode read FUpdateMode write SetUpdateMode default upWhereAll;
property ParamCheck: Boolean read FParamCheck write FParamCheck default True;
property GeneratorField : TIBGeneratorField read FGeneratorField write SetGeneratorField;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -