home *** CD-ROM | disk | FTP | other *** search
-
- {*******************************************************}
- { }
- { Delphi Visual Component Library }
- { }
- { Copyright (c) 1995,96 Borland International }
- { }
- {*******************************************************}
-
- unit DB;
-
- {$N+,P+,S-,R-}
-
- interface
-
- uses SysUtils, Windows, Bde, Classes;
-
- const
-
- { TDataSet maximum number of record buffers }
-
- dsMaxBufferCount = 1024;
-
- { Maximum string field size }
-
- dsMaxStringSize = 8192;
-
- { SQL Trace buffer size }
-
- smTraceBufSize = 8192 + SizeOf(TraceDesc);
-
- { TDBDataSet flags }
-
- dbfOpened = 0;
- dbfPrepared = 1;
- dbfExecSQL = 2;
- dbfTable = 3;
- dbfFieldList = 4;
- dbfIndexList = 5;
- dbfStoredProc = 6;
- dbfExecProc = 7;
- dbfProcDesc = 8;
-
- type
-
- { Forward declarations }
-
- TDBError = class;
- TSession = class;
- TDatabase = class;
- TFieldDefs = class;
- TDataSet = class;
- TDBDataSet = class;
- TField = class;
- TDataSource = class;
- TDataLink = class;
-
- { Generic types }
-
- PFieldDescList = ^TFieldDescList;
- TFieldDescList = array[0..1023] of FLDDesc;
-
- PIndexDescList = ^TIndexDescList;
- TIndexDescList = array[0..63] of IDXDesc;
-
- { Exception classes }
-
- EDatabaseError = class(Exception);
-
- EDBEngineError = class(EDatabaseError)
- private
- FErrors: TList;
- function GetError(Index: Integer): TDBError;
- function GetErrorCount: Integer;
- public
- constructor Create(ErrorCode: DBIResult);
- destructor Destroy; override;
- property ErrorCount: Integer read GetErrorCount;
- property Errors[Index: Integer]: TDBError read GetError;
- end;
-
- { BDE error information type }
-
- TDBError = class
- private
- FErrorCode: DBIResult;
- FNativeError: Longint;
- FMessage: string;
- function GetCategory: Byte;
- function GetSubCode: Byte;
- public
- constructor Create(Owner: EDBEngineError; ErrorCode: DBIResult;
- NativeError: Longint; Message: PChar);
- property Category: Byte read GetCategory;
- property ErrorCode: DBIResult read FErrorCode;
- property SubCode: Byte read GetSubCode;
- property Message: string read FMessage;
- property NativeError: Longint read FNativeError;
- end;
-
- { TLocale }
-
- TLocale = Pointer;
-
- { TBDECallback }
-
- TBDECallbackEvent = function(CBInfo: Pointer): CBRType of Object;
-
- TBDECallback = class
- private
- FHandle: hDBICur;
- FOwner: TObject;
- FCBType: CBType;
- FOldCBData: Longint;
- FOldCBBuf: Pointer;
- FOldCBBufLen: Word;
- FOldCBFunc: pfDBICallBack;
- FInstalled: Boolean;
- FCallbackEvent: TBDECallbackEvent;
- protected
- function Invoke(CallType: CBType; CBInfo: Pointer): CBRType;
- public
- constructor Create(AOwner: TObject; Handle: hDBICur; CBType: CBType;
- CBBuf: Pointer; CBBufSize: Integer; CallbackEvent: TBDECallbackEvent;
- Chain: Boolean);
- destructor Destroy; override;
- end;
-
- { TSessionList }
-
- TSessionList = class(TObject)
- private
- FSessions: TList;
- procedure AddSession(ASession: TSession);
- procedure CloseAll;
- function GetCount: Integer;
- function GetSession(Index: Integer): TSession;
- function GetCurrentSession: TSession;
- function GetSessionByName(const SessionName: string): TSession;
- procedure SetCurrentSession(Value: TSession);
- public
- constructor Create;
- destructor Destroy; override;
- property CurrentSession: TSession read GetCurrentSession write SetCurrentSession;
- function FindSession(const SessionName: string): TSession;
- procedure GetSessionNames(List: TStrings);
- function OpenSession(const SessionName: string): TSession;
- property Count: Integer read GetCount;
- property Sessions[Index: Integer]: TSession read GetSession; default;
- property List[const SessionName: string]: TSession read GetSessionByName;
- end;
-
- { TSession }
-
- TConfigMode = (cmPersistent, cmSession, cmAll);
-
- TPasswordEvent = procedure(Sender: TObject; var Continue: Boolean) of Object;
-
- TDatabaseEvent = (dbOpen, dbClose, dbAdd, dbRemove, dbAddAlias, dbDeleteAlias);
-
- TDatabaseNotifyEvent = procedure(DBEvent: TDatabaseEvent; const Param) of object;
-
- TBDEInitProc = procedure(Session: TSession);
-
- TTraceFlag = (tfQPrepare, tfQExecute, tfError, tfStmt, tfConnect,
- tfTransact, tfBlob, tfMisc, tfVendor);
-
- TTraceFlags = set of TTraceFlag;
-
- TWriteProc = function (Client: TObject; Data: PChar; Len: Integer): LongBool; StdCall;
- TSMRegProc = function (Handle: Integer; ClientName: PChar;
- var WriteProc: TWriteProc; Instance: TObject;
- const SignalProc: Pointer): TObject; StdCall;
-
- TSession = class(TComponent)
- private
- FHandle: HDBISes;
- FDefault: Boolean;
- FDatabases: TList;
- FCallbacks: TList;
- FLocale: TLocale;
- FClientLib: THandle;
- FSMRegProc: TSMRegProc;
- FSMWriteProc: TWriteProc;
- FSMBuffer: PTraceDesc;
- FSMClient: TObject;
- FTraceFlags: TTraceFlags;
- FStreamedActive: Boolean;
- FKeepConnections: Boolean;
- FSessionName: string;
- FNetFileDir: string;
- FPrivateDir: string;
- FCBSCType: CBSCType;
- FDLLDetach: Boolean;
- FBDEOwnsLoginCbDb: Boolean;
- FLockCount: Integer;
- FCBDBLogin: TCBDBLogin;
- FOnPassword: TPasswordEvent;
- FOnStartup: TNotifyEvent;
- FOnDBNotify: TDatabaseNotifyEvent;
- procedure AddDatabase(Value: TDatabase);
- procedure AddConfigRecord(const Path, Node: string; List: TStrings);
- procedure CallBDEInitProcs;
- procedure CheckInactive;
- procedure CheckConfigMode(CfgMode: TConfigMode);
- function DBLoginCallback(CBInfo: Pointer): CBRType;
- procedure DBNotification(DBEvent: TDatabaseEvent; const Param);
- procedure DeleteConfigPath(const Path, Node: string);
- function GetActive: Boolean;
- function GetConfigMode: TConfigMode;
- function GetDatabase(Index: Integer): TDatabase;
- function GetDatabaseCount: Integer;
- function GetHandle: HDBISes;
- function GetNetFileDir: string;
- function GetPrivateDir: string;
- procedure InitializeBDE;
- procedure InternalAddAlias(const Name, Driver: string; List: TStrings;
- CfgMode: TConfigMode; RestoreMode: Boolean);
- procedure InternalDeleteAlias(const Name: string; CfgMode: TConfigMode;
- RestoreMode: Boolean);
- procedure LockSession;
- procedure MakeCurrent;
- procedure ModifyConfigParams(const Path, Node: string; List: TStrings);
- procedure RegisterCallbacks(Value: Boolean);
- procedure RemoveDatabase(Value: TDatabase);
- function ServerCallback(CBInfo: Pointer): CBRType;
- procedure SetActive(Value: Boolean);
- procedure SetConfigMode(Value: TConfigMode);
- procedure SetConfigParams(const Path, Node: string; List: TStrings);
- procedure SetNetFileDir(const Value: string);
- procedure SetPrivateDir(const Value: string);
- procedure SetSessionName(const Value: string);
- procedure SetTraceFlags(Value: TTraceFlags);
- procedure SMClientSignal(Sender: TObject; Data: Integer);
- function SqlTraceCallback(CBInfo: Pointer): CBRType;
- procedure StartSession(Value: Boolean);
- procedure UnlockSession;
- protected
- procedure Loaded; override;
- property OnDBNotify: TDatabaseNotifyEvent read FOnDBNotify write FOnDBNotify;
- property BDEOwnsLoginCbDb: Boolean read FBDEOwnsLoginCbDb write FBDEOwnsLoginCbDb;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure AddAlias(const Name, Driver: string; List: TStrings);
- procedure AddStandardAlias(const Name, Path, DefaultDriver: string);
- property ConfigMode: TConfigMode read GetConfigMode write SetConfigMode;
- procedure AddPassword(const Password: string);
- procedure Close;
- procedure CloseDatabase(Database: TDatabase);
- procedure DeleteAlias(const Name: string);
- procedure DropConnections;
- function FindDatabase(const DatabaseName: string): TDatabase;
- procedure GetAliasNames(List: TStrings);
- procedure GetAliasParams(const AliasName: string; List: TStrings);
- function GetAliasDriverName(const AliasName: string): string;
- procedure GetConfigParams(const Path, Section: string; List: TStrings);
- procedure GetDatabaseNames(List: TStrings);
- procedure GetDriverNames(List: TStrings);
- procedure GetDriverParams(const DriverName: string; List: TStrings);
- function GetPassword: Boolean;
- procedure GetTableNames(const DatabaseName, Pattern: string;
- Extensions, SystemTables: Boolean; List: TStrings);
- procedure GetStoredProcNames(const DatabaseName: string; List: TStrings);
- function IsAlias(const Name: string): Boolean;
- procedure ModifyAlias(Name: string; List: TStrings);
- procedure Open;
- function OpenDatabase(const DatabaseName: string): TDatabase;
- procedure RemoveAllPasswords;
- procedure RemovePassword(const Password: string);
- procedure SaveConfigFile;
- property DatabaseCount: Integer read GetDatabaseCount;
- property Databases[Index: Integer]: TDatabase read GetDatabase;
- property Handle: HDBISES read GetHandle;
- property Locale: TLocale read FLocale;
- property TraceFlags: TTraceFlags read FTraceFlags write SetTraceFlags;
- published
- property Active: Boolean read GetActive write SetActive default False;
- property KeepConnections: Boolean read FKeepConnections write FKeepConnections default True;
- property NetFileDir: string read GetNetFileDir write SetNetFileDir;
- property PrivateDir: string read GetPrivateDir write SetPrivateDir;
- property SessionName: string read FSessionName write SetSessionName;
- property OnPassword: TPasswordEvent read FOnPassword write FOnPassword;
- property OnStartup: TNotifyEvent read FOnStartup write FOnStartup;
- end;
-
- { TParamList }
-
- TParamList = class(TObject)
- private
- FFieldCount: Integer;
- FBufSize: Word;
- FFieldDescs: PFieldDescList;
- FBuffer: PChar;
- public
- constructor Create(Params: TStrings);
- destructor Destroy; override;
- property Buffer: PChar read FBuffer;
- property FieldCount: Integer read FFieldCount;
- property FieldDescs: PFieldDescList read FFieldDescs;
- end;
-
- { TDatabase }
-
- TTransIsolation = (tiDirtyRead, tiReadCommitted, tiRepeatableRead);
-
- TLoginEvent = procedure(Database: TDatabase;
- LoginParams: TStrings) of object;
-
- TDatabase = class(TComponent)
- private
- FDataSets: TList;
- FTransIsolation: TTransIsolation;
- FLoginPrompt: Boolean;
- FKeepConnection: Boolean;
- FTemporary: Boolean;
- FSessionAlias: Boolean;
- FStreamedConnected: Boolean;
- FLocaleLoaded: Boolean;
- FAliased: Boolean;
- FReserved: Byte;
- FRefCount: Integer;
- FHandle: HDBIDB;
- FSQLBased: Boolean;
- FTransHandle: HDBIXAct;
- FLocale: TLocale;
- FSession: TSession;
- FSessionName: string;
- FParams: TStrings;
- FDatabaseName: string;
- FDatabaseType: string;
- FAcquiredHandle: Boolean;
- FOnLogin: TLoginEvent;
- procedure CheckActive;
- procedure CheckInactive;
- procedure CheckDatabaseName;
- procedure CheckDatabaseAlias(var Password: string);
- procedure CheckSessionName(Required: Boolean);
- procedure EndTransaction(TransEnd: EXEnd);
- function GetAliasName: string;
- function GetConnected: Boolean;
- function GetDataSet(Index: Integer): TDBDataSet;
- function GetDataSetCount: Integer;
- function GetDirectory: string;
- function GetDriverName: string;
- function GetIsSQLBased: Boolean;
- function GetInTransaction: Boolean;
- function GetTraceFlags: TTraceFlags;
- procedure LoadLocale;
- procedure Login(LoginParams: TStrings);
- procedure ParamsChanging(Sender: TObject);
- procedure SetAliasName(const Value: string);
- procedure SetConnected(Value: Boolean);
- procedure SetDatabaseName(const Value: string);
- procedure SetDatabaseType(const Value: string; Aliased: Boolean);
- procedure SetDirectory(const Value: string);
- procedure SetDriverName(const Value: string);
- procedure SetHandle(Value: HDBIDB);
- procedure SetKeepConnection(Value: Boolean);
- procedure SetParams(Value: TStrings);
- procedure SetTraceFlags(Value: TTraceFlags);
- procedure SetSessionName(const Value: string);
- protected
- procedure Loaded; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure ApplyUpdates(const DataSets: array of TDBDataSet);
- procedure Close;
- procedure CloseDataSets;
- procedure Commit;
- procedure FlushSchemaCache(const TableName: string);
- procedure Open;
- procedure Rollback;
- procedure StartTransaction;
- procedure ValidateName(const Name: string);
- property DataSetCount: Integer read GetDataSetCount;
- property DataSets[Index: Integer]: TDBDataSet read GetDataSet;
- property Directory: string read GetDirectory write SetDirectory;
- property Handle: HDBIDB read FHandle write SetHandle;
- property IsSQLBased: Boolean read FSQLBased;
- property InTransaction: Boolean read GetInTransaction;
- property Locale: TLocale read FLocale;
- property Session: TSession read FSession;
- property Temporary: Boolean read FTemporary write FTemporary;
- property SessionAlias: Boolean read FSessionAlias;
- property TraceFlags: TTraceFlags read GetTraceFlags write SetTraceFlags;
- published
- property AliasName: string read GetAliasName write SetAliasName;
- property Connected: Boolean read GetConnected write SetConnected default False;
- property DatabaseName: string read FDatabaseName write SetDatabaseName;
- property DriverName: string read GetDriverName write SetDriverName;
- property KeepConnection: Boolean read FKeepConnection write SetKeepConnection default True;
- property LoginPrompt: Boolean read FLoginPrompt write FLoginPrompt default True;
- property Params: TStrings read FParams write SetParams;
- property SessionName: string read FSessionName write SetSessionName;
- property TransIsolation: TTransIsolation read FTransIsolation write FTransIsolation default tiReadCommitted;
- property OnLogin: TLoginEvent read FOnLogin write FOnLogin;
- end;
-
- { TDataSetDesigner }
-
- TDataEvent = (deFieldChange, deRecordChange, deDataSetChange,
- deDataSetScroll, deLayoutChange, deUpdateRecord, deUpdateState,
- deCheckBrowseMode, dePropertyChange, deFieldListChange,
- deFocusControl);
-
- TDataSetDesigner = class(TObject)
- private
- FDataSet: TDataSet;
- FSaveActive: Boolean;
- FReserved: Byte;
- public
- constructor Create(DataSet: TDataSet);
- destructor Destroy; override;
- procedure BeginDesign;
- procedure DataEvent(Event: TDataEvent; Info: Longint); virtual;
- procedure EndDesign;
- property DataSet: TDataSet read FDataSet;
- end;
-
- { TFieldDef }
-
- TFieldClass = class of TField;
-
- TFieldType = (ftUnknown, ftString, ftSmallint, ftInteger, ftWord,
- ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime,
- ftBytes, ftVarBytes, ftAutoInc, ftBlob, ftMemo, ftGraphic,
- ftFmtMemo, ftParadoxOle, ftDBaseOle, ftTypedBinary);
-
- TFieldDef = class
- private
- FOwner: TFieldDefs;
- FName: string;
- FDataType: TFieldType;
- FRequired: Boolean;
- FBDECalcField: Boolean;
- FSize: Word;
- FFieldNo: Integer;
- function GetFieldClass: TFieldClass;
- public
- constructor Create(Owner: TFieldDefs; const Name: string;
- DataType: TFieldType; Size: Word; Required: Boolean; FieldNo: Integer);
- destructor Destroy; override;
- function CreateField(Owner: TComponent): TField;
- property BDECalcField: Boolean read FBDECalcField;
- property DataType: TFieldType read FDataType;
- property FieldClass: TFieldClass read GetFieldClass;
- property FieldNo: Integer read FFieldNo;
- property Name: string read FName;
- property Required: Boolean read FRequired;
- property Size: Word read FSize;
- end;
-
- { TFieldDefs }
-
- TFieldDefs = class
- private
- FDataSet: TDataSet;
- FItems: TList;
- FUpdated: Boolean;
- FReserved: Byte;
- function GetCount: Integer;
- function GetItem(Index: Integer): TFieldDef;
- public
- constructor Create(DataSet: TDataSet);
- destructor Destroy; override;
- procedure Add(const Name: string; DataType: TFieldType; Size: Word;
- Required: Boolean);
- procedure AddFieldDesc(FieldDesc: FLDDesc; Required: Boolean;
- FieldNo: Word);
- procedure Assign(FieldDefs: TFieldDefs);
- procedure Clear;
- function Find(const Name: string): TFieldDef;
- function IndexOf(const Name: string): Integer;
- procedure Update;
- property Count: Integer read GetCount;
- property Items[Index: Integer]: TFieldDef read GetItem; default;
- end;
-
- { TDataSet }
-
- TBookmark = Pointer;
- TBookmarkStr = String;
-
- PBufferList = ^TBufferList;
- TBufferList = array[0..dsMaxBufferCount - 1] of PChar;
-
- TDataSetState = (dsInactive, dsBrowse, dsEdit, dsInsert,
- dsSetKey, dsCalcFields, dsUpdateNew, dsUpdateOld, dsFilter);
-
- TGetMode = (gmCurrent, gmNext, gmPrior);
-
- TFilterOption = (foCaseInsensitive, foNoPartialCompare);
- TFilterOptions = set of TFilterOption;
-
- TLocateOption = (loCaseInsensitive, loPartialKey);
- TLocateOptions = set of TLocateOption;
-
- TResyncMode = set of (rmExact, rmCenter);
-
- TKeyIndex = (kiLookup, kiRangeStart, kiRangeEnd, kiCurRangeStart,
- kiCurRangeEnd, kiSave);
-
- PKeyBuffer = ^TKeyBuffer;
- TKeyBuffer = record
- Modified: Boolean;
- Exclusive: Boolean;
- FieldCount: Integer;
- Data: record end;
- end;
-
- TDataAction = (daFail, daAbort, daRetry);
-
- TDataSetNotifyEvent = procedure(DataSet: TDataSet) of object;
- TDataSetErrorEvent = procedure(DataSet: TDataSet; E: EDatabaseError;
- var Action: TDataAction) of object;
-
-
- TUpdateStatus = (usUnmodified, usModified, usInserted, usDeleted);
- TUpdateKind = (ukModify, ukInsert, ukDelete);
- TUpdateAction = (uaFail, uaAbort, uaSkip, uaRetry, uaApplied);
- TUpdateRecordTypes = set of (rtModified, rtInserted, rtDeleted, rtUnmodified);
- TUpdateErrorEvent = procedure(DataSet: TDataSet; E: EDatabaseError;
- UpdateKind: TUpdateKind; var UpdateAction: TUpdateAction) of object;
- TUpdateRecordEvent = procedure(DataSet: TDataSet; UpdateKind: TUpdateKind;
- var UpdateAction: TUpdateAction) of object;
- TOnServerYieldEvent = procedure(DataSet: TDataSet; var AbortQuery: Boolean) of object;
- TDataSetUpdateObject = class(TComponent)
- protected
- function GetDataSet: TDataSet; virtual; abstract;
- procedure SetDataSet(ADataSet: TDataSet); virtual; abstract;
- procedure Apply(UpdateKind: TUpdateKind); virtual; abstract;
- property DataSet: TDataSet read GetDataSet write SetDataSet;
- end;
-
- TFilterRecordEvent = procedure(DataSet: TDataSet;
- var Accept: Boolean) of object;
-
- TRecNoStatus = (rnDbase, rnParadox, rnNotSupported);
-
- PRecInfo = ^TRecInfo;
- TRecInfo = record
- UpdateStatus: TUpdateStatus;
- RecordNumber: Longint;
- end;
-
- TDataOperation = function: DBIResult of object;
-
- TDataSet = class(TComponent)
- private
- FFields: TList;
- FDataSources: TList;
- FFieldDefs: TFieldDefs;
- FBuffers: PBufferList;
- FBufListSize: Integer;
- FBufferCount: Integer;
- FRecordCount: Integer;
- FActiveRecord: Integer;
- FCurrentRecord: Integer;
- FHandle: HDBICur;
- FBOF: Boolean;
- FEOF: Boolean;
- FState: TDataSetState;
- FAutoCalcFields: Boolean;
- FDefaultFields: Boolean;
- FCanModify: Boolean;
- FModified: Boolean;
- FStreamedActive: Boolean;
- FInfoQueryMode: Boolean;
- FDisableState: TDataSetState;
- FEnableEvent: TDataEvent;
- FFiltered: Boolean;
- FFound: Boolean;
- FRecProps: RecProps;
- FRawFieldCount: Integer;
- FRecordSize: Word;
- FBookmarkSize: Word;
- FRecInfoOfs: Word;
- FBookmarkOfs: Word;
- FRecNoStatus: TRecNoStatus;
- FKeySize: Word;
- FExpIndex: Boolean;
- FCaseInsIndex: Boolean;
- FCalcFieldsSize: Word;
- FRecBufSize: Word;
- FDisableCount: Integer;
- FFirstDataLink: TDataLink;
- FLocale: TLocale;
- FDesigner: TDataSetDesigner;
- FKeyBuffers: array[TKeyIndex] of PKeyBuffer;
- FKeyBuffer: PKeyBuffer;
- FCalcBuffer: PChar;
- FFilterText: string;
- FFilterOptions: TFilterOptions;
- FExprFilter: HDBIFilter;
- FFuncFilter: HDBIFilter;
- FFilterBuffer: PChar;
- FIndexFieldCount: Integer;
- FIndexFieldMap: DBIKey;
- FBDECalcFields: Boolean;
- FCachedUpdates: Boolean;
- FUpdateCBBuf: PDELAYUPDCbDesc;
- FUpdateCallback: TBDECallback;
- FInUpdateCallback: Boolean;
- FUpdateErrCode: DBIResult;
- FAsyncCallback: TBDECallback;
- FCBYieldStep: CBYieldStep;
- FOnServerYield: TOnServerYieldEvent;
- FUpdateObject: TDataSetUpdateObject;
- FBeforeOpen: TDataSetNotifyEvent;
- FAfterOpen: TDataSetNotifyEvent;
- FBeforeClose: TDataSetNotifyEvent;
- FAfterClose: TDataSetNotifyEvent;
- FBeforeInsert: TDataSetNotifyEvent;
- FAfterInsert: TDataSetNotifyEvent;
- FBeforeEdit: TDataSetNotifyEvent;
- FAfterEdit: TDataSetNotifyEvent;
- FBeforePost: TDataSetNotifyEvent;
- FAfterPost: TDataSetNotifyEvent;
- FBeforeCancel: TDataSetNotifyEvent;
- FAfterCancel: TDataSetNotifyEvent;
- FBeforeDelete: TDataSetNotifyEvent;
- FAfterDelete: TDataSetNotifyEvent;
- FOnNewRecord: TDataSetNotifyEvent;
- FOnCalcFields: TDataSetNotifyEvent;
- FOnUpdateError: TUpdateErrorEvent;
- FOnUpdateRecord: TUpdateRecordEvent;
- FOnFilterRecord: TFilterRecordEvent;
- FOnEditError: TDataSetErrorEvent;
- FOnPostError: TDataSetErrorEvent;
- FOnDeleteError: TDataSetErrorEvent;
- procedure ActivateBuffers;
- procedure ActivateFilters;
- procedure AddDataSource(DataSource: TDataSource);
- procedure AddField(Field: TField);
- procedure AddRecord(const Values: array of const; Append: Boolean);
- procedure AllocKeyBuffers;
- procedure AllocDelUpdCBBuf(Allocate: Boolean);
- procedure BeginInsertAppend;
- procedure BindFields(Binding: Boolean);
- function CachedUpdateCallBack(CBInfo: Pointer): CBRType;
- procedure CalculateBDEFields;
- procedure CalculateFields;
- procedure CheckCanModify;
- procedure CheckCachedUpdateMode;
- procedure CheckFieldName(const FieldName: string);
- procedure CheckFieldNames(const FieldNames: string);
- procedure CheckOperation(Operation: TDataOperation;
- ErrorEvent: TDataSetErrorEvent);
- procedure CheckRequiredFields;
- procedure CheckSetKeyMode;
- procedure CopyBuffer(SourceIndex, DestIndex: Integer);
- function CreateExprFilter(const Expr: string;
- Options: TFilterOptions; Priority: Integer): HDBIFilter;
- procedure CreateFields;
- function CreateFuncFilter(FilterFunc: Pointer;
- Priority: Integer): HDBIFilter;
- function CreateLookupFilter(Fields: TList; const Values: Variant;
- Options: TLocateOptions; Priority: Integer): HDBIFilter;
- procedure DeactivateFilters;
- function DeleteRecord: DBIResult;
- procedure DestroyFields;
- function EditRecord: DBIResult;
- procedure EndInsertAppend;
- function FieldByNumber(FieldNo: Integer): TField;
- function FindRecord(Restart, GoForward: Boolean): Boolean;
- procedure FreeFieldBuffers;
- procedure FreeKeyBuffers;
- function GetActive: Boolean;
- function GetBookmarkStr: TBookmarkStr;
- procedure GetCalcFields(Index: Integer);
- function GetField(Index: Integer): TField;
- function GetFieldCount: Integer;
- function GetFieldValue(const FieldName: string): Variant;
- procedure GetIndexInfo;
- function GetNextRecord: Boolean;
- function GetNextRecords: Integer;
- function GetPriorRecord: Boolean;
- function GetPriorRecords: Integer;
- function GetRecord(Index: Integer; GetMode: TGetMode): DBIResult;
- function GetRecordCount: Longint;
- function GetUpdatesPending: Boolean;
- function InitKeyBuffer(Buffer: PKeyBuffer): PKeyBuffer;
- procedure InitRecord(Buffer: PChar);
- procedure InternalClose;
- procedure InternalOpen;
- function LocateRecord(const KeyFields: string; const KeyValues: Variant;
- Options: TLocateOptions; SyncCursor: Boolean): Boolean;
- function MapsToIndex(Fields: TList; CaseInsensitive: Boolean): Boolean;
- procedure MoveBuffer(CurIndex, NewIndex: Integer);
- procedure PostKeyBuffer(Commit: Boolean);
- function PostRecord: DBIResult;
- function RecordFilter(RecBuf: Pointer; RecNo: Integer): Smallint; stdcall;
- procedure RemoveDataSource(DataSource: TDataSource);
- procedure RemoveField(Field: TField);
- procedure SetActive(Value: Boolean);
- procedure SetBookmarkStr(const Value: TBookmarkStr);
- procedure SetBufferCount(Value: Integer);
- procedure SetBufListSize(Value: Integer);
- procedure SetCurrentRecord(Index: Integer);
- procedure SetField(Index: Integer; Value: TField);
- procedure SetFieldDefs(Value: TFieldDefs);
- procedure SetFieldValue(const FieldName: string; const Value: Variant);
- procedure SetFilterData(const Text: string; Options: TFilterOptions);
- procedure SetFiltered(Value: Boolean);
- procedure SetFilterHandle(var Filter: HDBIFilter; Value: HDBIFilter);
- procedure SetFilterOptions(Value: TFilterOptions);
- procedure SetFilterText(const Value: string);
- procedure SetOnFilterRecord(const Value: TFilterRecordEvent);
- procedure SetOnUpdateError(UpdateEvent: TUpdateErrorEvent);
- procedure SetState(Value: TDataSetState);
- procedure UpdateBufferCount;
- function UpdateCallbackRequired: Boolean;
- procedure UpdateFieldDefs;
- function YieldCallBack(CBInfo: Pointer): CBRType;
- protected
- procedure CheckInactive;
- procedure ClearBuffers;
- procedure CloseCursor; virtual;
- function CreateHandle: HDBICur; virtual;
- procedure DataEvent(Event: TDataEvent; Info: Longint); virtual;
- procedure DestroyHandle; virtual;
- procedure DestroyLookupCursor; virtual;
- procedure DoAfterCancel; virtual;
- procedure DoAfterClose; virtual;
- procedure DoAfterDelete; virtual;
- procedure DoAfterEdit; virtual;
- procedure DoAfterInsert; virtual;
- procedure DoAfterOpen; virtual;
- procedure DoAfterPost; virtual;
- procedure DoBeforeCancel; virtual;
- procedure DoBeforeClose; virtual;
- procedure DoBeforeDelete; virtual;
- procedure DoBeforeEdit; virtual;
- procedure DoBeforeInsert; virtual;
- procedure DoBeforeOpen; virtual;
- procedure DoBeforePost; virtual;
- procedure DoOnCalcFields; virtual;
- procedure DoOnNewRecord; virtual;
- function GetCanModify: Boolean; virtual;
- function GetDataSource: TDataSource; virtual;
- function GetIndexField(Index: Integer): TField;
- function GetIndexFieldCount: Integer;
- function GetKeyBuffer(KeyIndex: TKeyIndex): PKeyBuffer;
- function GetKeyExclusive: Boolean;
- function GetKeyFieldCount: Integer;
- function GetLookupCursor(const KeyFields: string;
- CaseInsensitive: Boolean): HDBICur; virtual;
- function GetRecordNumber: Longint; virtual;
- procedure InitFieldDefs; virtual;
- procedure Loaded; override;
- procedure OpenCursor; virtual;
- procedure PrepareCursor; virtual;
- function ResetCursorRange: Boolean;
- function SetCursorRange: Boolean;
- procedure SetIndexField(Index: Integer; Value: TField);
- procedure SetKeyBuffer(KeyIndex: TKeyIndex; Clear: Boolean);
- procedure SetKeyExclusive(Value: Boolean);
- procedure SetKeyFieldCount(Value: Integer);
- procedure SetKeyFields(KeyIndex: TKeyIndex; const Values: array of const);
- procedure SetLinkRanges(MasterFields: TList);
- procedure SetLocale(Value: TLocale);
- procedure SetName(const Value: TComponentName); override;
- procedure SwitchToIndex(const IndexName, TagName: string);
- procedure GetChildren(Proc: TGetChildProc); override;
- procedure SetChildOrder(Component: TComponent; Order: Integer); override;
- property InfoQueryMode: Boolean read FInfoQueryMode;
- procedure SetCachedUpdates(Value: Boolean);
- procedure SetupCallBack(Value: Boolean);
- function ProcessUpdates(UpdCmd: DBIDelayedUpdCmd): DBIResult;
- function GetUpdateRecordSet: TUpdateRecordTypes;
- procedure SetUpdateRecordSet(RecordTypes: TUpdateRecordTypes);
- procedure SetUpdateObject(Value: TDataSetUpdateObject);
- function ForceUpdateCallback: Boolean;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- function ActiveBuffer: PChar;
- procedure Append;
- procedure AppendRecord(const Values: array of const);
- procedure Cancel;
- procedure CheckBrowseMode;
- procedure ClearFields;
- procedure Close;
- function ControlsDisabled: Boolean;
- procedure CursorPosChanged;
- procedure Delete;
- procedure DisableControls;
- procedure Edit;
- procedure EnableControls;
- procedure FetchAll;
- function FieldByName(const FieldName: string): TField;
- function FindField(const FieldName: string): TField;
- function FindFirst: Boolean;
- function FindLast: Boolean;
- function FindNext: Boolean;
- function FindPrior: Boolean;
- procedure First;
- procedure FreeBookmark(Bookmark: TBookmark);
- function GetBookmark: TBookmark;
- function GetCurrentRecord(Buffer: PChar): Boolean;
- procedure GetFieldList(List: TList; const FieldNames: string);
- procedure GetFieldNames(List: TStrings);
- procedure GotoBookmark(Bookmark: TBookmark);
- procedure Insert;
- procedure InsertRecord(const Values: array of const);
- function IsLinkedTo(DataSource: TDataSource): Boolean;
- procedure Last;
- function Locate(const KeyFields: string; const KeyValues: Variant;
- Options: TLocateOptions): Boolean;
- function Lookup(const KeyFields: string; const KeyValues: Variant;
- const ResultFields: string): Variant;
- function MoveBy(Distance: Integer): Integer;
- procedure Next;
- procedure Open;
- procedure Post;
- procedure Prior;
- procedure Refresh;
- procedure Resync(Mode: TResyncMode);
- procedure SetFields(const Values: array of const);
- procedure SetDetailFields(MasterFields: TList);
- procedure UpdateCursorPos;
- procedure UpdateRecord;
- procedure ApplyUpdates;
- procedure CommitUpdates;
- procedure CancelUpdates;
- procedure RevertRecord;
- function UpdateStatus: TUpdateStatus;
- property BOF: Boolean read FBOF;
- property Bookmark: TBookmarkStr read GetBookmarkStr write SetBookmarkStr;
- property CanModify: Boolean read GetCanModify;
- property DataSource: TDataSource read GetDataSource;
- property DefaultFields: Boolean read FDefaultFields;
- property Designer: TDataSetDesigner read FDesigner;
- property EOF: Boolean read FEOF;
- property ExpIndex: Boolean read FExpIndex;
- property FieldCount: Integer read GetFieldCount;
- property FieldDefs: TFieldDefs read FFieldDefs write SetFieldDefs;
- property Fields[Index: Integer]: TField read GetField write SetField;
- property FieldValues[const FieldName: string]: Variant read GetFieldValue write SetFieldValue; default;
- property Found: Boolean read FFound;
- property Handle: HDBICur read FHandle;
- property KeySize: Word read FKeySize;
- property Locale: TLocale read FLocale;
- property Modified: Boolean read FModified;
- property RecordCount: Longint read GetRecordCount;
- property RecNo: Longint read GetRecordNumber;
- property RecordSize: Word read FRecordSize;
- property State: TDataSetState read FState;
- property UpdateObject: TDataSetUpdateObject read FUpdateObject write SetUpdateObject;
- property UpdateRecordTypes: TUpdateRecordTypes read GetUpdateRecordSet write SetUpdateRecordSet;
- property UpdatesPending: Boolean read GetUpdatesPending;
- published
- property Active: Boolean read GetActive write SetActive default False;
- property AutoCalcFields: Boolean read FAutoCalcFields write FAutoCalcFields default True;
- property CachedUpdates: Boolean read FCachedUpdates write SetCachedUpdates default False;
- property Filter: string read FFilterText write SetFilterText;
- property Filtered: Boolean read FFiltered write SetFiltered default False;
- property FilterOptions: TFilterOptions read FFilterOptions write SetFilterOptions default [];
- property BeforeOpen: TDataSetNotifyEvent read FBeforeOpen write FBeforeOpen;
- property AfterOpen: TDataSetNotifyEvent read FAfterOpen write FAfterOpen;
- property BeforeClose: TDataSetNotifyEvent read FBeforeClose write FBeforeClose;
- property AfterClose: TDataSetNotifyEvent read FAfterClose write FAfterClose;
- property BeforeInsert: TDataSetNotifyEvent read FBeforeInsert write FBeforeInsert;
- property AfterInsert: TDataSetNotifyEvent read FAfterInsert write FAfterInsert;
- property BeforeEdit: TDataSetNotifyEvent read FBeforeEdit write FBeforeEdit;
- property AfterEdit: TDataSetNotifyEvent read FAfterEdit write FAfterEdit;
- property BeforePost: TDataSetNotifyEvent read FBeforePost write FBeforePost;
- property AfterPost: TDataSetNotifyEvent read FAfterPost write FAfterPost;
- property BeforeCancel: TDataSetNotifyEvent read FBeforeCancel write FBeforeCancel;
- property AfterCancel: TDataSetNotifyEvent read FAfterCancel write FAfterCancel;
- property BeforeDelete: TDataSetNotifyEvent read FBeforeDelete write FBeforeDelete;
- property AfterDelete: TDataSetNotifyEvent read FAfterDelete write FAfterDelete;
- property OnNewRecord: TDataSetNotifyEvent read FOnNewRecord write FOnNewRecord;
- property OnCalcFields: TDataSetNotifyEvent read FOnCalcFields write FOnCalcFields;
- property OnFilterRecord: TFilterRecordEvent read FOnFilterRecord write SetOnFilterRecord;
- property OnServerYield: TOnServerYieldEvent read FOnServerYield write FOnServerYield;
- property OnUpdateError: TUpdateErrorEvent read FOnUpdateError write SetOnUpdateError;
- property OnUpdateRecord: TUpdateRecordEvent read FOnUpdateRecord write FOnUpdateRecord;
- property OnEditError: TDataSetErrorEvent read FOnEditError write FOnEditError;
- property OnPostError: TDataSetErrorEvent read FOnPostError write FOnPostError;
- property OnDeleteError: TDataSetErrorEvent read FOnDeleteError write FOnDeleteError;
- end;
-
- { TDBDataSet }
-
- TUpdateMode = (upWhereAll, upWhereChanged, upWhereKeyOnly);
- TDBFlags = set of 0..15;
-
- TDBDataSet = class(TDataSet)
- private
- FDBFlags: TDBFlags;
- FUpdateMode: TUpdateMode;
- FReserved: Byte;
- FDatabase: TDatabase;
- FDatabaseName: string;
- FSessionName: string;
- procedure CheckDBSessionName;
- function GetDBFlag(Flag: Integer): Boolean;
- function GetDBHandle: HDBIDB;
- function GetDBLocale: TLocale;
- function GetDBSession: TSession;
- procedure SetDatabaseName(const Value: string);
- procedure SetSessionName(const Value: string);
- procedure SetUpdateMode(const Value: TUpdateMode);
- protected
- procedure CloseCursor; override;
- procedure Disconnect; virtual;
- procedure OpenCursor; override;
- procedure SetDBFlag(Flag: Integer; Value: Boolean); virtual;
- property DBFlags: TDBFlags read FDBFlags;
- property UpdateMode: TUpdateMode read FUpdateMode write SetUpdateMode default upWhereAll;
- public
- function CheckOpen(Status: DBIResult): Boolean;
- property Database: TDatabase read FDatabase;
- property DBHandle: HDBIDB read GetDBHandle;
- property DBLocale: TLocale read GetDBLocale;
- property DBSession: TSession read GetDBSession;
- published
- property DatabaseName: string read FDatabaseName write SetDatabaseName;
- property SessionName: string read FSessionName write SetSessionName;
- end;
-
- { TDataSource }
-
- TDataChangeEvent = procedure(Sender: TObject; Field: TField) of object;
-
- TDataSource = class(TComponent)
- private
- FDataSet: TDataSet;
- FDataLinks: TList;
- FEnabled: Boolean;
- FAutoEdit: Boolean;
- FState: TDataSetState;
- FReserved: Byte;
- FOnStateChange: TNotifyEvent;
- FOnDataChange: TDataChangeEvent;
- FOnUpdateData: TNotifyEvent;
- procedure AddDataLink(DataLink: TDataLink);
- procedure DataEvent(Event: TDataEvent; Info: Longint);
- procedure NotifyDataLinks(Event: TDataEvent; Info: Longint);
- procedure RemoveDataLink(DataLink: TDataLink);
- procedure SetDataSet(ADataSet: TDataSet);
- procedure SetEnabled(Value: Boolean);
- procedure SetState(Value: TDataSetState);
- procedure UpdateState;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Edit;
- function IsLinkedTo(DataSet: TDataSet): Boolean;
- property State: TDataSetState read FState;
- published
- property AutoEdit: Boolean read FAutoEdit write FAutoEdit default True;
- property DataSet: TDataSet read FDataSet write SetDataSet;
- property Enabled: Boolean read FEnabled write SetEnabled default True;
- property OnStateChange: TNotifyEvent read FOnStateChange write FOnStateChange;
- property OnDataChange: TDataChangeEvent read FOnDataChange write FOnDataChange;
- property OnUpdateData: TNotifyEvent read FOnUpdateData write FOnUpdateData;
- end;
-
- { TField }
-
- TFieldKind = (fkData, fkCalculated, fkLookup);
-
- TFieldNotifyEvent = procedure(Sender: TField) of object;
- TFieldGetTextEvent = procedure(Sender: TField; var Text: string;
- DisplayText: Boolean) of object;
- TFieldSetTextEvent = procedure(Sender: TField; const Text: string) of object;
- TFieldRef = ^TField;
-
- TField = class(TComponent)
- private
- FDataSet: TDataSet;
- FFieldName: string;
- FDataType: TFieldType;
- FReadOnly: Boolean;
- FFieldKind: TFieldKind;
- FAlignment: TAlignment;
- FVisible: Boolean;
- FRequired: Boolean;
- FValidating: Boolean;
- FSize: Word;
- FDataSize: Word;
- FFieldNo: Integer;
- FOffset: Word;
- FDisplayWidth: Integer;
- FDisplayLabel: string;
- FEditMask: string;
- FValueBuffer: Pointer;
- FLookupDataSet: TDataSet;
- FKeyFields: string;
- FLookupKeyFields: string;
- FLookupResultField: string;
- FAttributeSet: string;
- FOnChange: TFieldNotifyEvent;
- FOnValidate: TFieldNotifyEvent;
- FOnGetText: TFieldGetTextEvent;
- FOnSetText: TFieldSetTextEvent;
- procedure Bind(Binding: Boolean);
- procedure CalcLookupValue;
- function GetBDECalcField: Boolean;
- function GetCalculated: Boolean;
- function GetDisplayLabel: string;
- function GetDisplayName: string;
- function GetDisplayText: string;
- function GetDisplayWidth: Integer;
- function GetEditText: string;
- function GetIndex: Integer;
- function GetIsIndexField: Boolean;
- function GetIsNull: Boolean;
- function GetLookup: Boolean;
- function GetNewValue: Variant;
- function GetOldValue: Variant;
- function GetUpdateValue(ValueState: TDataSetState): Variant;
- function IsDisplayLabelStored: Boolean;
- function IsDisplayWidthStored: Boolean;
- procedure ReadAttributeSet(Reader: TReader);
- procedure SetAlignment(Value: TAlignment);
- procedure SetCalculated(Value: Boolean);
- procedure SetDataSet(ADataSet: TDataSet);
- procedure SetDisplayLabel(Value: string);
- procedure SetDisplayWidth(Value: Integer);
- procedure SetEditMask(const Value: string);
- procedure SetEditText(const Value: string);
- procedure SetFieldKind(Value: TFieldKind);
- procedure SetFieldName(const Value: string);
- procedure SetIndex(Value: Integer);
- procedure SetLookup(Value: Boolean);
- procedure SetLookupDataSet(Value: TDataSet);
- procedure SetLookupKeyFields(const Value: string);
- procedure SetLookupResultField(const Value: string);
- procedure SetKeyFields(const Value: string);
- procedure SetNewValue(const Value: Variant);
- procedure SetVisible(Value: Boolean);
- procedure UpdateDataSize;
- procedure WriteAttributeSet(Writer: TWriter);
- protected
- procedure AccessError(const TypeName: string);
- procedure CheckInactive;
- procedure Change; virtual;
- procedure DataChanged;
- procedure DefineProperties(Filer: TFiler); override;
- procedure FreeBuffers; virtual;
- function GetAsBoolean: Boolean; virtual;
- function GetAsCurrency: Currency; virtual;
- function GetAsDateTime: TDateTime; virtual;
- function GetAsFloat: Double; virtual;
- function GetAsInteger: Longint; virtual;
- function GetAsString: string; virtual;
- function GetAsVariant: Variant; virtual;
- function GetCanModify: Boolean;
- function GetDefaultWidth: Integer; virtual;
- function GetParentComponent: TComponent; override;
- procedure GetText(var Text: string; DisplayText: Boolean); virtual;
- function HasParent: Boolean; override;
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); override;
- procedure PropertyChanged(LayoutAffected: Boolean);
- procedure ReadState(Reader: TReader); override;
- procedure SetAsBoolean(Value: Boolean); virtual;
- procedure SetAsCurrency(Value: Currency); virtual;
- procedure SetAsDateTime(Value: TDateTime); virtual;
- procedure SetAsFloat(Value: Double); virtual;
- procedure SetAsInteger(Value: Longint); virtual;
- procedure SetAsString(const Value: string); virtual;
- procedure SetAsVariant(const Value: Variant); virtual;
- procedure SetDataType(Value: TFieldType);
- procedure SetSize(Value: Word);
- procedure SetParentComponent(AParent: TComponent); override;
- procedure SetText(const Value: string); virtual;
- procedure SetVarValue(const Value: Variant); virtual;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- procedure AssignValue(const Value: TVarRec);
- procedure Clear; virtual;
- procedure FocusControl;
- function GetData(Buffer: Pointer): Boolean;
- function IsValidChar(InputChar: Char): Boolean; virtual;
- procedure SetData(Buffer: Pointer);
- procedure SetFieldType(Value: TFieldType); virtual;
- property AsBoolean: Boolean read GetAsBoolean write SetAsBoolean;
- property AsCurrency: Currency read GetAsCurrency write SetAsCurrency;
- property AsDateTime: TDateTime read GetAsDateTime write SetAsDateTime;
- property AsFloat: Double read GetAsFloat write SetAsFloat;
- property AsInteger: Longint read GetAsInteger write SetAsInteger;
- property AsString: string read GetAsString write SetAsString;
- property AsVariant: Variant read GetAsVariant write SetAsVariant;
- property AttributeSet: string read FAttributeSet write FAttributeSet;
- property BDECalcField: Boolean read GetBDECalcField;
- property CanModify: Boolean read GetCanModify;
- property DataSet: TDataSet read FDataSet write SetDataSet stored False;
- property DataSize: Word read FDataSize;
- property DataType: TFieldType read FDataType;
- property DisplayName: string read GetDisplayName;
- property DisplayText: string read GetDisplayText;
- property EditMask: string read FEditMask write SetEditMask;
- property EditMaskPtr: string read FEditMask;
- property FieldKind: TFieldKind read FFieldKind write SetFieldKind;
- property FieldNo: Integer read FFieldNo;
- property IsIndexField: Boolean read GetIsIndexField;
- property IsNull: Boolean read GetIsNull;
- property Size: Word read FSize write SetSize;
- property Text: string read GetEditText write SetEditText;
- property Value: Variant read GetAsVariant write SetAsVariant;
- property NewValue: Variant read GetNewValue write SetNewValue;
- property OldValue: Variant read GetOldValue;
- published
- property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
- property Calculated: Boolean read GetCalculated write SetCalculated default False;
- property DisplayLabel: string read GetDisplayLabel write SetDisplayLabel
- stored IsDisplayLabelStored;
- property DisplayWidth: Integer read GetDisplayWidth write SetDisplayWidth
- stored IsDisplayWidthStored;
- property FieldName: string read FFieldName write SetFieldName;
- property Index: Integer read GetIndex write SetIndex stored False;
- property Lookup: Boolean read GetLookup write SetLookup default False;
- property LookupDataSet: TDataSet read FLookupDataSet write SetLookupDataSet;
- property LookupKeyFields: string read FLookupKeyFields write SetLookupKeyFields;
- property LookupResultField: string read FLookupResultField write SetLookupResultField;
- property KeyFields: string read FKeyFields write SetKeyFields;
- property ReadOnly: Boolean read FReadOnly write FReadOnly default False;
- property Required: Boolean read FRequired write FRequired default False;
- property Visible: Boolean read FVisible write SetVisible default True;
- property OnChange: TFieldNotifyEvent read FOnChange write FOnChange;
- property OnGetText: TFieldGetTextEvent read FOnGetText write FOnGetText;
- property OnSetText: TFieldSetTextEvent read FOnSetText write FOnSetText;
- property OnValidate: TFieldNotifyEvent read FOnValidate write FOnValidate;
- end;
-
- { TDataLink }
-
- TDataLink = class(TPersistent)
- private
- FDataSource: TDataSource;
- FNext: TDataLink;
- FBufferCount: Integer;
- FFirstRecord: Integer;
- FReadOnly: Boolean;
- FActive: Boolean;
- FEditing: Boolean;
- FUpdating: Boolean;
- FDataSourceFixed: Boolean;
- procedure DataEvent(Event: TDataEvent; Info: Longint);
- function GetActiveRecord: Integer;
- function GetDataSet: TDataSet;
- function GetRecordCount: Integer;
- procedure SetActive(Value: Boolean);
- procedure SetActiveRecord(Value: Integer);
- procedure SetBufferCount(Value: Integer);
- procedure SetDataSource(ADataSource: TDataSource);
- procedure SetEditing(Value: Boolean);
- procedure SetReadOnly(Value: Boolean);
- procedure UpdateRange;
- procedure UpdateState;
- protected
- procedure ActiveChanged; virtual;
- procedure CheckBrowseMode; virtual;
- procedure DataSetChanged; virtual;
- procedure DataSetScrolled(Distance: Integer); virtual;
- procedure FocusControl(Field: TFieldRef); virtual;
- procedure EditingChanged; virtual;
- procedure LayoutChanged; virtual;
- procedure RecordChanged(Field: TField); virtual;
- procedure UpdateData; virtual;
- public
- constructor Create;
- destructor Destroy; override;
- function Edit: Boolean;
- procedure UpdateRecord;
- property Active: Boolean read FActive;
- property ActiveRecord: Integer read GetActiveRecord write SetActiveRecord;
- property BufferCount: Integer read FBufferCount write SetBufferCount;
- property DataSet: TDataSet read GetDataSet;
- property DataSource: TDataSource read FDataSource write SetDataSource;
- property DataSourceFixed: Boolean read FDataSourceFixed write FDataSourceFixed;
- property Editing: Boolean read FEditing;
- property ReadOnly: Boolean read FReadOnly write SetReadOnly;
- property RecordCount: Integer read GetRecordCount;
- end;
-
- const
- dsEditModes = [dsEdit, dsInsert, dsSetKey];
-
- function AnsiToNative(Locale: TLocale; const AnsiStr: string;
- NativeStr: PChar; MaxLen: Integer): PChar;
- procedure NativeToAnsi(Locale: TLocale; NativeStr: PChar;
- var AnsiStr: string);
- procedure AnsiToNativeBuf(Locale: TLocale; Source, Dest: PChar; Len: Integer);
- procedure NativeToAnsiBuf(Locale: TLocale; Source, Dest: PChar; Len: Integer);
-
- function NativeCompareStr(Locale: TLocale; const S1, S2: string; Len: Integer): Integer;
- function NativeCompareStrBuf(Locale: TLocale; const S1, S2: PChar; Len: Integer): Integer;
- function NativeCompareText(Locale: TLocale; const S1, S2: string; Len: Integer): Integer;
- function NativeCompareTextBuf(Locale: TLocale; const S1, S2: PChar; Len: Integer): Integer;
-
- function ExtractFieldName(const Fields: string; var Pos: Integer): string;
-
- procedure RegisterFields(const FieldClasses: array of TFieldClass);
-
- procedure DatabaseError(const Message: string);
- procedure DBError(Ident: Word);
- procedure DBErrorFmt(Ident: Word; const Args: array of const);
- procedure DbiError(ErrorCode: DBIResult);
- procedure Check(Status: DBIResult);
- procedure RegisterBDEInitProc(const InitProc: TBDEInitProc);
-
- var
- Session: TSession;
- Sessions: TSessionList;
-
- const
- RegisterFieldsProc: procedure(const FieldClassess: array of TFieldClass) = nil;
-
- implementation
-
- uses Controls, Forms, DBConsts, DBPWDlg, DBLogDlg, DBTables;
-
- var
- FCSect: TRTLCriticalSection;
- StartTime: LongInt = 0;
- TimerID: Word;
- AcquiredTimer: Boolean = False;
- BDEInitProcs: TList;
-
- procedure RegisterBDEInitProc(const InitProc: TBDEInitProc);
- begin
- if not Assigned(BDEInitProcs) then
- BDEInitProcs := TList.Create;
- BDEInitProcs.Add(@InitProc);
- end;
-
- procedure FreeTimer;
- begin
- if AcquiredTimer then
- begin
- KillTimer(0, TimerID);
- AcquiredTimer := False;
- StartTime := 0;
- Screen.Cursor := crDefault;
- end;
- end;
-
- { Timer callback function }
-
- procedure TimerCallBack(hWnd: HWND; Message: Word; TimerID: Word;
- SysTime: LongInt); stdcall;
- begin
- FreeTimer;
- end;
-
- { BdeCallbacks }
-
- function BdeCallBack(CallType: CBType; Data: Longint;
- CBInfo: Pointer): CBRType; stdcall;
- begin
- if (Data <> 0) then
- Result := TBDECallback(Data).Invoke(CallType, CBInfo) else
- Result := cbrUSEDEF;
- end;
-
- function DLLDetachCallBack(CallType: CBType; Data: Longint;
- CBInfo: Pointer): CBRType; stdcall;
- begin
- DB.Session.FDLLDetach := True;
- Sessions.CloseAll;
- end;
-
- constructor TBDECallback.Create(AOwner: TObject; Handle: hDBICur; CBType: CBType;
- CBBuf: Pointer; CBBufSize: Integer; CallbackEvent: TBDECallbackEvent;
- Chain: Boolean);
- begin
- FOwner := AOwner;
- FHandle := Handle;
- FCBType := CBType;
- FCallbackEvent := CallbackEvent;
- DbiGetCallBack(Handle, FCBType, @FOldCBData, @FOldCBBufLen, @FOldCBBuf, FOldCBFunc);
- if not Assigned(FOldCBFunc) or Chain then
- begin
- Check(DbiRegisterCallback(FHandle, FCBType, Longint(Self), CBBufSize,
- CBBuf, BdeCallBack));
- FInstalled := True;
- end;
- end;
-
- destructor TBDECallback.Destroy;
- begin
- if FInstalled then
- begin
- if Assigned(FOldCBFunc) then
- try
- DbiRegisterCallback(FHandle, FCBType, FOldCBData, FOldCBBufLen,
- FOldCBBuf, FOldCBFunc);
- except
- end
- else
- DbiRegisterCallback(FHandle, FCBType, 0, 0, nil, nil);
- end;
- end;
-
- function TBDECallback.Invoke(CallType: CBType; CBInfo: Pointer): CBRType;
- begin
- if CallType = FCBType then
- Result := FCallbackEvent(CBInfo) else
- Result := cbrUSEDEF;
- if Assigned(FOldCBFunc)
- then Result := FOldCBFunc(CallType, FOldCBData, CBInfo);
- end;
-
- { Utility routines }
-
- procedure DisposeMem(var Buffer; Size: Word);
- begin
- if Pointer(Buffer) <> nil then
- begin
- FreeMem(Pointer(Buffer), Size);
- Pointer(Buffer) := nil;
- end;
- end;
-
- function BuffersEqual(Buf1, Buf2: Pointer; Size: Cardinal): Boolean; assembler;
- asm
- PUSH EDI
- PUSH ESI
- MOV ESI,Buf1
- MOV EDI,Buf2
- XOR EAX,EAX
- JECXZ @@1
- CLD
- REPE CMPSB
- JNE @@1
- INC EAX
- @@1: POP ESI
- POP EDI
- end;
-
- function StrToOem(const AnsiStr: string): string;
- begin
- SetLength(Result, Length(AnsiStr));
- if Length(Result) > 0 then
- CharToOem(PChar(AnsiStr), PChar(Result));
- end;
-
- function AnsiToNative(Locale: TLocale; const AnsiStr: string;
- NativeStr: PChar; MaxLen: Integer): PChar;
- var
- Len: Integer;
- begin
- Len := Length(AnsiStr);
- if Len > MaxLen then Len := MaxLen;
- if Len > 0 then AnsiToNativeBuf(Locale, Pointer(AnsiStr), NativeStr, Len);
- NativeStr[Len] := #0;
- Result := NativeStr;
- end;
-
- procedure NativeToAnsi(Locale: TLocale; NativeStr: PChar;
- var AnsiStr: string);
- var
- Len: Integer;
- begin
- Len := StrLen(NativeStr);
- SetString(AnsiStr, nil, Len);
- if Len > 0 then NativeToAnsiBuf(Locale, NativeStr, Pointer(AnsiStr), Len);
- end;
-
- procedure AnsiToNativeBuf(Locale: TLocale; Source, Dest: PChar; Len: Integer);
- var
- DataLoss: LongBool;
- begin
- if Len > 0 then
- if Locale <> nil then
- DbiAnsiToNative(Locale, Dest, Source, Len, DataLoss) else
- CharToOemBuff(Source, Dest, Len);
- end;
-
- procedure NativeToAnsiBuf(Locale: TLocale; Source, Dest: PChar; Len: Integer);
- var
- DataLoss: LongBool;
- begin
- if Len > 0 then
- if Locale <> nil then
- DbiNativeToAnsi(Locale, Dest, Source, Len, DataLoss) else
- OemToCharBuff(Source, Dest, Len)
- end;
-
- function NativeCompareStr(Locale: TLocale; const S1, S2: string; Len: Integer): Integer;
- begin
- Result := NativeCompareStrBuf(Locale, PChar(S1), PChar(S2), Len);
- end;
-
- function NativeCompareStrBuf(Locale: TLocale; const S1, S2: PChar; Len: Integer): Integer;
- begin
- if Len > 0 then
- Result := OsLdStrnCmp(Locale, S1, S2, Len) else
- Result := OsLdStrCmp(Locale, S1, S2);
- end;
-
- function NativeCompareText(Locale: TLocale; const S1, S2: string; Len: Integer): Integer;
- begin
- Result := NativeCompareTextBuf(Locale, PChar(S1), PChar(S2), Len);
- end;
-
- function NativeCompareTextBuf(Locale: TLocale; const S1, S2: PChar; Len: Integer): Integer;
- begin
- if Len > 0 then
- Result := OsLdStrnCmpi(Locale, S1, S2, Len) else
- Result := OsLdStrCmpi(Locale, S1, S2);
- end;
-
- function ExtractFieldName(const Fields: string; var Pos: Integer): string;
- var
- I: Integer;
- begin
- I := Pos;
- while (I <= Length(Fields)) and (Fields[I] <> ';') do Inc(I);
- Result := Copy(Fields, Pos, I - Pos);
- if (I <= Length(Fields)) and (Fields[I] = ';') then Inc(I);
- Pos := I;
- end;
-
- function IsDirectory(const DatabaseName: string): Boolean;
- begin
- Result := (DatabaseName = '') or (Pos(':', DatabaseName) <> 0) or
- (Pos('\', DatabaseName) <> 0);
- end;
-
- procedure MergeStrings(Dest, Source: TStrings);
- var
- DI, I, P: Integer;
- S: string;
- begin
- for I := 0 to Source.Count - 1 do
- begin
- S := Source[I];
- P := Pos('=', S);
- if P > 1 then
- begin
- DI := Dest.IndexOfName(Copy(S, 1, P - 1));
- if DI > -1 then Dest[DI] := S;
- end;
- end;
- end;
-
- procedure CheckTypeSize(DataType: TFieldType; Size: Word);
- begin
- case DataType of
- ftString: if (Size >= 1) and (Size <= dsMaxStringSize) then Exit;
- ftBCD: if Size <= 32 then Exit;
- ftBytes, ftVarBytes: if Size > 0 then Exit;
- ftBlob, ftMemo, ftGraphic, ftFmtMemo, ftParadoxOle, ftDBaseOle,
- ftTypedBinary: Exit;
- else
- if Size = 0 then Exit;
- end;
- DBError(SInvalidFieldSize);
- end;
-
- function FieldTypeToVarType(DataType: TFieldType): Integer;
- const
- TypeMap: array[TFieldType] of Word = (
- varEmpty, varString, varInteger, varInteger, varInteger, varBoolean,
- varDouble, varCurrency, varCurrency, varDate, varDate, varDate,
- varEmpty, varEmpty, varInteger, varEmpty, varEmpty, varEmpty,
- varEmpty, varEmpty, varEmpty, varEmpty);
- begin
- Result := TypeMap[DataType];
- end;
-
- procedure RegisterFields(const FieldClasses: array of TFieldClass);
- begin
- if Assigned(RegisterFieldsProc) then
- RegisterFieldsProc(FieldClasses) else
- DBError(SInvalidFieldRegistration);
- end;
-
- function GetIntProp(const Handle: Pointer; PropName: Integer): Integer;
- var
- Length: Word;
- Value: Integer;
- begin
- Value := 0;
- Check(DbiGetProp(HDBIObj(Handle), propName, @Value, SizeOf(Value), Length));
- Result := Value;
- end;
-
- { Error and exception handling routines }
-
- procedure DatabaseError(const Message: string);
- begin
- raise EDatabaseError.Create(Message);
- end;
-
- procedure DBError(Ident: Word);
- begin
- DatabaseError(LoadStr(Ident));
- end;
-
- procedure DBErrorFmt(Ident: Word; const Args: array of const);
- begin
- DatabaseError(FmtLoadStr(Ident, Args));
- end;
-
- procedure DbiError(ErrorCode: DBIResult);
- begin
- if AcquiredTimer then FreeTimer;
- raise EDBEngineError.Create(ErrorCode);
- end;
-
- procedure Check(Status: DBIResult);
- begin
- if Status <> 0 then DbiError(Status);
- end;
-
- { TDBError }
-
- constructor TDBError.Create(Owner: EDBEngineError; ErrorCode: DBIResult;
- NativeError: Longint; Message: PChar);
- begin
- Owner.FErrors.Add(Self);
- FErrorCode := ErrorCode;
- FNativeError := NativeError;
- FMessage := Message;
- end;
-
- function TDBError.GetCategory: Byte;
- begin
- Result := Hi(FErrorCode);
- end;
-
- function TDBError.GetSubCode: Byte;
- begin
- Result := Lo(FErrorCode);
- end;
-
- { EDBEngineError }
-
- function TrimMessage(Msg: PChar): PChar;
- var
- Blank: Boolean;
- Source, Dest: PChar;
- begin
- Source := Msg;
- Dest := Msg;
- Blank := False;
- while Source^ <> #0 do
- begin
- if Source^ <= ' ' then Blank := True else
- begin
- if Blank then
- begin
- Dest^ := ' ';
- Inc(Dest);
- Blank := False;
- end;
- Dest^ := Source^;
- Inc(Dest);
- end;
- Inc(Source);
- end;
- if (Dest > Msg) and ((Dest - 1)^ = '.') then Dec(Dest);
- Dest^ := #0;
- Result := Msg;
- end;
-
- constructor EDBEngineError.Create(ErrorCode: DBIResult);
- var
- ErrorIndex: Integer;
- NativeError: Longint;
- Msg, LastMsg: DBIMSG;
- begin
- inherited Create('');
- FErrors := TList.Create;
- ErrorIndex := 1;
- if not Session.Active then
- begin
- Message := FmtLoadStr(SInitError, [ErrorCode]);
- TDBError.Create(Self, ErrorCode, 0, PChar(Message));
- end
- else begin
- DbiGetErrorString(ErrorCode, Msg);
- TDBError.Create(Self, ErrorCode, 0, Msg);
- TrimMessage(Msg);
- if Msg[0] = #0 then Message := FmtLoadStr(SBDEError, [ErrorCode])
- else Message := Msg;
- while True do
- begin
- StrCopy(LastMsg, Msg);
- ErrorCode := DbiGetErrorEntry(ErrorIndex, NativeError, Msg);
- if (ErrorCode = DBIERR_NONE) or
- (ErrorCode = DBIERR_NOTINITIALIZED) then Break;
- TDBError.Create(Self, ErrorCode, NativeError, Msg);
- TrimMessage(Msg);
- if (Msg[0] <> #0) and (StrComp(Msg, LastMsg) <> 0) then
- Message := Format('%s. %s', [Message, Msg]);
- Inc(ErrorIndex);
- end;
- end;
- end;
-
- destructor EDBEngineError.Destroy;
- var
- I: Integer;
- begin
- if FErrors <> nil then
- begin
- for I := FErrors.Count - 1 downto 0 do TDBError(FErrors[I]).Free;
- FErrors.Free;
- end;
- inherited Destroy;
- end;
-
- function EDBEngineError.GetError(Index: Integer): TDBError;
- begin
- Result := FErrors[Index];
- end;
-
- function EDBEngineError.GetErrorCount: Integer;
- begin
- Result := FErrors.Count;
- end;
-
- { TSessionList }
-
- constructor TSessionList.Create;
- begin
- inherited Create;
- FSessions := TList.Create;
- InitializeCriticalSection(FCSect);
- end;
-
- destructor TSessionList.Destroy;
- begin
- CloseAll;
- DeleteCriticalSection(FCSect);
- inherited Destroy;
- end;
-
- procedure TSessionList.AddSession(ASession: TSession);
- begin
- if FSessions.Count = 0 then ASession.FDefault := True;
- FSessions.Add(ASession);
- end;
-
- procedure TSessionList.CloseAll;
- var
- I: Integer;
- begin
- for I := FSessions.Count-1 downto 0 do
- TSession(FSessions[I]).Free;
- end;
-
- function TSessionList.GetCount: Integer;
- begin
- Result := FSessions.Count;
- end;
-
- function TSessionList.GetCurrentSession: TSession;
- var
- Handle: HDBISes;
- I: Integer;
- begin
- Check(DbiGetCurrSession(Handle));
- for I := 0 to FSessions.Count - 1 do
- if TSession(FSessions[I]).Handle = Handle then
- begin
- Result := TSession(FSessions[I]);
- Exit;
- end;
- Result := nil;
- end;
-
- function TSessionList.GetSession(Index: Integer): TSession;
- begin
- Result := TSession(FSessions[Index]);
- end;
-
- function TSessionList.GetSessionByName(const SessionName: string): TSession;
- begin
- if SessionName = '' then
- Result := DB.Session
- else
- Result := FindSession(SessionName);
- if Result = nil then
- DBErrorFmt(SInvalidSessionName, [SessionName]);
- end;
-
- function TSessionList.FindSession(const SessionName: string): TSession;
- var
- I: Integer;
- begin
- if SessionName = '' then
- Result := DB.Session
- else
- begin
- for I := 0 to FSessions.Count - 1 do
- begin
- Result := FSessions[I];
- if AnsiCompareText(Result.SessionName, SessionName) = 0 then Exit;
- end;
- Result := nil;
- end;
- end;
-
- procedure TSessionList.GetSessionNames(List: TStrings);
- var
- I: Integer;
- begin
- List.BeginUpdate;
- try
- List.Clear;
- for I := 0 to FSessions.Count - 1 do
- with TSession(FSessions[I]) do
- List.Add(SessionName);
- finally
- List.EndUpdate;
- end;
- end;
-
- function TSessionList.OpenSession(const SessionName: string): TSession;
- begin
- Result := FindSession(SessionName);
- if Result = nil then
- begin
- Result := TSession.Create(nil);
- Result.SessionName := SessionName;
- end;
- Result.SetActive(True);
- end;
-
- procedure TSessionList.SetCurrentSession(Value: TSession);
- begin
- Check(DbiSetCurrSession(Value.FHandle))
- end;
-
- { TSession }
-
- constructor TSession.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- Exclude(FComponentStyle, csInheritable);
- FDatabases := TList.Create;
- FCallbacks := TList.Create;
- FKeepConnections := True;
- Sessions.AddSession(Self);
- FHandle := nil;
- end;
-
- destructor TSession.Destroy;
-
- procedure ResetDBSessionRefs;
- var
- I: Integer;
- begin
- for I := 0 to FDatabases.Count - 1 do
- with TDatabase(FDatabases[I]) do
- if FSession = Self then
- begin
- FSession := DB.Session;
- FSession.AddDatabase(FDatabases[I]);
- end;
- end;
-
- begin
- SetActive(False);
- Sessions.FSessions.Remove(Self);
- if not FDefault and Assigned(FDatabases) then ResetDBSessionRefs;
- FDatabases.Free;
- FCallbacks.Free;
- inherited Destroy;
- end;
-
- procedure TSession.AddAlias(const Name, Driver: string; List: TStrings);
- begin
- InternalAddAlias(Name, Driver, List, ConfigMode, True);
- end;
-
- procedure TSession.AddDatabase(Value: TDatabase);
- begin
- FDatabases.Add(Value);
- DBNotification(dbAdd, Value);
- end;
-
- procedure TSession.AddConfigRecord(const Path, Node: string; List: TStrings);
- var
- ParamList: TParamList;
- begin
- ParamList := TParamList.Create(List);
- try
- with ParamList do
- Check(DbiCfgAddRecord(nil, PChar(Format(Path, [Node])), FieldCount,
- PFLDDesc(FieldDescs), Buffer));
- finally
- ParamList.Free;
- end;
- end;
-
- procedure TSession.AddStandardAlias(const Name, Path, DefaultDriver: string);
- var
- AliasParams: TStringList;
- begin
- AliasParams := TStringList.Create;
- try
- AliasParams.Add(Format('%s=%s', [szCFGDBPATH, Path]));
- AliasParams.Add(Format('%s=%s', [szCFGDBDEFAULTDRIVER, DefaultDriver]));
- AddAlias(Name, szCFGDBSTANDARD, AliasParams);
- finally
- AliasParams.Free;
- end;
- end;
-
- procedure TSession.AddPassword(const Password: string);
- var
- Buffer: array[0..255] of Char;
- begin
- LockSession;
- try
- if Password <> '' then
- Check(DbiAddPassword(AnsiToNative(Locale, Password, Buffer,
- SizeOf(Buffer) - 1)));
- finally
- UnlockSession;
- end;
- end;
-
- procedure TSession.CallBDEInitProcs;
- var
- I: Integer;
- begin
- if Assigned(BDEInitProcs) then
- for I := 0 to BDEInitProcs.Count - 1 do
- TBDEInitProc(BDEInitProcs[I])(Self);
- end;
-
- procedure TSession.CheckInactive;
- begin
- if Active then
- DBError(SSessionActive);
- end;
-
- procedure TSession.CheckConfigMode(CfgMode: TConfigMode);
- begin
- if CfgMode = cmAll then CfgMode := cmPersistent;
- ConfigMode := CfgMode;
- end;
-
- procedure TSession.Close;
- begin
- SetActive(False);
- end;
-
- procedure TSession.CloseDatabase(Database: TDatabase);
- begin
- if Database.FRefCount <> 0 then Dec(Database.FRefCount);
- if (Database.FRefCount = 0) and not Database.KeepConnection then
- if Database.Temporary then Database.Free else Database.Close;
- end;
-
- function TSession.DBLoginCallback(CBInfo: Pointer): CBRType;
- var
- Database: TDatabase;
- UserName, Password: string;
- AliasParams: TStringList;
- begin
- Result := cbrYES;
- with PCBDBLogin(CBInfo)^ do
- try
- if hDB = nil then
- begin
- if not FBDEOwnsLoginCbDb then
- begin
- hDb := OpenDatabase(szDbName).Handle;
- if not Assigned(hDb) then
- Result := cbrAbort
- else
- bCallbackToClose := True;
- end else
- begin
- AliasParams := TStringList.Create;
- try
- GetAliasParams(szDbName, AliasParams);
- UserName := AliasParams.Values[szUSERNAME];
- finally
- AliasParams.Free;
- end;
- Password := '';
- if LoginDialogEx(szDbName, UserName, Password, True) then
- begin
- AnsiToNative(Locale, Password, szPassword, SizeOf(szPassword) - 1);
- bCallbackToClose := False;
- end
- else
- Result :=cbrAbort;
- end
- end else
- begin
- Database := FindDatabase(szDbName);
- if Assigned(Database) and (hDB = Database.Handle) then
- CloseDatabase(Database);
- end;
- except
- Result := cbrAbort;
- end;
- end;
-
- procedure TSession.DBNotification(DBEvent: TDatabaseEvent; const Param);
- begin
- if Assigned(FOnDBNotify) then FOnDBNotify(DBEvent, Param);
- end;
-
- procedure TSession.DeleteAlias(const Name: string);
- begin
- InternalDeleteAlias(Name, ConfigMode, True);
- end;
-
- procedure TSession.DeleteConfigPath(const Path, Node: string);
- var
- CfgPath: string;
- begin
- CfgPath := Format(Path, [Node]);
- if DbiCfgPosition(nil, PChar(CfgPath)) = 0 then
- Check(DbiCfgDropRecord(nil, PChar(CfgPath)));
- end;
-
- procedure TSession.DropConnections;
- var
- I: Integer;
- begin
- for I := FDatabases.Count - 1 downto 0 do
- with TDatabase(FDatabases[I]) do
- if Temporary and (FRefCount = 0) then Free;
- end;
-
- function TSession.FindDatabase(const DatabaseName: string): TDatabase;
- var
- I: Integer;
- begin
- for I := 0 to FDatabases.Count - 1 do
- begin
- Result := FDatabases[I];
- if ((Result.DatabaseName <> '') or Result.Temporary) and
- (AnsiCompareText(Result.DatabaseName, DatabaseName) = 0) then Exit;
- end;
- Result := nil;
- end;
-
- function TSession.GetActive: Boolean;
- begin
- Result := FHandle <> nil;
- end;
-
- function TSession.GetAliasDriverName(const AliasName: string): string;
- var
- Desc: DBDesc;
- begin
- LockSession;
- try
- if DbiGetDatabaseDesc(PChar(StrToOem(AliasName)), @Desc) <> 0 then
- DBErrorFmt(SInvalidAliasName, [AliasName]);
- finally
- UnlockSession;
- end;
- if Desc.szDBType[sizeOf(Desc.szDBType) - 1] <> #0 then
- Desc.szDBType[sizeOf(Desc.szDBType) - 1] := #0;
- OemToChar(Desc.szDBType, Desc.szDBType);
- Result := Desc.szDBType;
- end;
-
- procedure TSession.GetAliasNames(List: TStrings);
- var
- Cursor: HDBICur;
- Desc: DBDesc;
- begin
- List.BeginUpdate;
- try
- List.Clear;
- LockSession;
- try
- Check(DbiOpenDatabaseList(Cursor));
- finally
- UnlockSession;
- end;
- try
- while DbiGetNextRecord(Cursor, dbiNOLOCK, @Desc, nil) = 0 do
- begin
- OemToChar(Desc.szName, Desc.szName);
- List.Add(Desc.szName);
- end;
- finally
- DbiCloseCursor(Cursor);
- end;
- finally
- List.EndUpdate;
- end;
- end;
-
- procedure TSession.GetAliasParams(const AliasName: string; List: TStrings);
- var
- SAlias: DBIName;
- Desc: DBDesc;
- begin
- List.BeginUpdate;
- try
- List.Clear;
- StrPLCopy(SAlias, AliasName, SizeOf(SAlias) - 1);
- CharToOEM(SAlias, SAlias);
- LockSession;
- try
- Check(DbiGetDatabaseDesc(SAlias, @Desc));
- finally
- UnlockSession;
- end;
- if Desc.szDBType[sizeOf(Desc.szDBType) - 1] <> #0 then
- Desc.szDBType[sizeOf(Desc.szDBType) - 1] := #0;
- if StrIComp(Desc.szDbType, szCFGDBSTANDARD) = 0 then
- begin
- GetConfigParams('\DATABASES\%s\DB INFO', SAlias, List);
- List.Values[szCFGDBTYPE] := '';
- end
- else
- GetConfigParams('\DATABASES\%s\DB OPEN', SAlias, List);
- finally
- List.EndUpdate;
- end;
- end;
-
- procedure TSession.GetConfigParams(const Path, Section: string; List: TStrings);
- var
- Cursor: HDBICur;
- ConfigDesc: CFGDesc;
- begin
- LockSession;
- try
- Check(DbiOpenCfgInfoList(nil, dbiREADONLY, cfgPERSISTENT, PChar(Format(Path,
- [Section])), Cursor));
- finally
- UnlockSession;
- end;
- try
- while DbiGetNextRecord(Cursor, dbiNOLOCK, @ConfigDesc, nil) = 0 do
- with ConfigDesc do
- begin
- OemToChar(szValue, szValue);
- List.Add(Format('%s=%s', [szNodeName, szValue]));
- end;
- finally
- DbiCloseCursor(Cursor);
- end;
- end;
-
- function TSession.GetDatabase(Index: Integer): TDatabase;
- begin
- Result := FDatabases[Index];
- end;
-
- function TSession.GetDatabaseCount: Integer;
- begin
- Result := FDatabases.Count;
- end;
-
- procedure TSession.GetDatabaseNames(List: TStrings);
- var
- I: Integer;
- Names: TStringList;
- begin
- Names := TStringList.Create;
- try
- Names.Sorted := True;
- GetAliasNames(Names);
- for I := 0 to FDatabases.Count - 1 do
- with TDatabase(FDatabases[I]) do
- if not IsDirectory(DatabaseName) then Names.Add(DatabaseName);
- List.Assign(Names);
- finally
- Names.Free;
- end;
- end;
-
- procedure TSession.GetDriverNames(List: TStrings);
- var
- Cursor: HDBICur;
- Name: array[0..255] of Char;
- begin
- List.BeginUpdate;
- try
- List.Clear;
- List.Add(szCFGDBSTANDARD);
- LockSession;
- try
- Check(DbiOpenDriverList(Cursor));
- finally
- UnlockSession;
- end;
- try
- while DbiGetNextRecord(Cursor, dbiNOLOCK, @Name, nil) = 0 do
- if (StrIComp(Name, szPARADOX) <> 0) and
- (StrIComp(Name, szDBASE) <> 0) then
- begin
- OemToChar(Name, Name);
- List.Add(Name);
- end;
- finally
- DbiCloseCursor(Cursor);
- end;
- finally
- List.EndUpdate;
- end;
- end;
-
- procedure TSession.GetDriverParams(const DriverName: string;
- List: TStrings);
- begin
- List.BeginUpdate;
- try
- List.Clear;
- if CompareText(DriverName, szCFGDBSTANDARD) = 0 then
- begin
- List.Add(Format('%s=', [szCFGDBPATH]));
- List.Add(Format('%s=%s', [szCFGDBDEFAULTDRIVER, szPARADOX]));
- List.Add(Format('%s=%s', [szCFGDBENABLEBCD, szCFGFALSE]));
- end
- else
- GetConfigParams('\DRIVERS\%s\DB OPEN', StrToOem(DriverName), List);
- finally
- List.EndUpdate;
- end;
- end;
-
- function TSession.GetHandle: HDBISes;
- begin
- if FHandle <> nil then
- Check(DbiSetCurrSession(FHandle))
- else
- SetActive(True);
- Result := FHandle;
- end;
-
- function TSession.GetNetFileDir: string;
- var
- Length: Word;
- Buffer: array[0..255] of Char;
- begin
- if Active and not (csWriting in ComponentState) then
- begin
- LockSession;
- try
- Check(DbiGetProp(HDBIOBJ(FHandle), sesNETFILE, @Buffer, SizeOf(Buffer),
- Length));
- finally
- UnLockSession;
- end;
- NativeToAnsi(nil, Buffer, Result);
- end else
- Result := FNetFileDir;
- Result := AnsiUpperCase(Result);
- end;
-
- function TSession.GetPrivateDir: string;
- var
- SessionInfo: SESInfo;
- begin
- if Active and not (csWriting in ComponentState) then
- begin
- LockSession;
- try
- Check(DbiGetSesInfo(SessionInfo));
- finally
- UnlockSession;
- end;
- NativeToAnsi(nil, SessionInfo.szPrivDir, Result);
- end else
- Result := FPrivateDir;
- Result := AnsiUpperCase(Result);
- end;
-
- function TSession.GetPassword: Boolean;
- begin
- if Assigned(FOnPassword) then
- begin
- Result := False;
- FOnPassword(Self, Result)
- end else
- Result := PasswordDialog(Self);
- end;
-
- procedure TSession.GetTableNames(const DatabaseName, Pattern: string;
- Extensions, SystemTables: Boolean; List: TStrings);
- var
- Database: TDatabase;
- Cursor: HDBICur;
- WildCard: PChar;
- Name: string;
- SPattern: array[0..127] of Char;
- Desc: TBLBaseDesc;
- begin
- List.BeginUpdate;
- try
- List.Clear;
- Database := OpenDatabase(DatabaseName);
- try
- WildCard := nil;
- if Pattern <> '' then
- WildCard := AnsiToNative(Database.Locale, Pattern, SPattern,
- SizeOf(SPattern) - 1);
- Check(DbiOpenTableList(Database.Handle, False, SystemTables,
- WildCard, Cursor));
- try
- while DbiGetNextRecord(Cursor, dbiNOLOCK, @Desc, nil) = 0 do
- with Desc do
- begin
- if Extensions and (szExt[0] <> #0) then
- StrCat(StrCat(szName, '.'), szExt);
- NativeToAnsi(Database.Locale, szName, Name);
- List.Add(Name);
- end;
- finally
- DbiCloseCursor(Cursor);
- end;
- finally
- CloseDatabase(Database);
- end;
- finally
- List.EndUpdate;
- end;
- end;
-
- procedure TSession.GetStoredProcNames(const DatabaseName: string; List: TStrings);
- var
- Database: TDatabase;
- Cursor: HDBICur;
- Name: string;
- Desc: SPDesc;
- begin
- List.BeginUpdate;
- try
- List.Clear;
- Database := OpenDatabase(DatabaseName);
- try
- Check(DbiOpenSPList(Database.Handle, False, True, nil, Cursor));
- try
- while DbiGetNextRecord(Cursor, dbiNOLOCK, @Desc, nil) = 0 do
- with Desc do
- begin
- NativeToAnsi(Database.Locale, szName, Name);
- List.Add(Name);
- end;
- finally
- DbiCloseCursor(Cursor);
- end;
- finally
- CloseDatabase(Database);
- end;
- finally
- List.EndUpdate;
- end;
- end;
-
- procedure TSession.InitializeBDE;
- const
- StartFlags: LongInt = $FFFFEBF0;
- var
- Status: DBIResult;
- Env: DbiEnv;
- ClientHandle: hDBIObj;
- SetCursor: Boolean;
- begin
- SetCursor := GetCurrentThreadID = MainThreadID;
- if SetCursor then
- Screen.Cursor := crHourGlass;
- try
- FillChar(Env, SizeOf(Env), 0);
- StrPLCopy(Env.szLang, LoadStr(SIDAPILangID), SizeOf(Env.szLang) - 1);
- Status := DbiInit(@Env);
- if (Status <> DBIERR_NONE) and (Status <> DBIERR_MULTIPLEINIT) then
- DBErrorFmt(SInitError, [Status]);
- Check(DbiGetCurrSession(FHandle));
- if DbiGetObjFromName(objCLIENT, nil, ClientHandle) = 0 then
- DbiSetProp(ClientHandle, clSQLRESTRICT, StartFlags);
- if IsLibrary then
- DbiRegisterCallback(nil, cbDETACHNOTIFY, 0, 0, nil, DLLDetachCallBack);
- finally
- if SetCursor then
- Screen.Cursor := crDefault;
- end;
- end;
-
- procedure TSession.InternalAddAlias(const Name, Driver: string; List: TStrings;
- CfgMode: TConfigMode; RestoreMode: Boolean);
- var
- Standard: Boolean;
- DefaultDriver: string;
- OemName: string;
- CfgModeSave: TConfigMode;
-
- procedure ValidateAliasName;
- const
- ValidChars = ['0'..'9','A'..'Z','a'..'z','_',#127..#255];
- var
- I, Len: Integer;
- ValidName: Boolean;
- begin
- Len := Length(Name);
- ValidName := Len > 0;
- if ValidName then
- begin
- OemName := StrToOem(Name);
- for I := 1 to Len do
- begin
- ValidName := OemName[I] in ValidChars;
- if not ValidName then break;
- end;
- end;
- if not ValidName then
- DBErrorFmt(SInvalidAliasName, [Name]);
- end;
-
- procedure AddDBInfo;
- var
- DBInfo: TStringList;
- EnableBCD: string;
- begin
- DBInfo := TStringList.Create;
- try
- if Standard then
- DBInfo.Add(Format('%s=%s', [szCFGDBTYPE, szCFGDBSTANDARD])) else
- DBInfo.Add(Format('%s=%s', [szCFGDBTYPE, Driver]));
- DBInfo.Add(Format('%s=%s', [szCFGDBPATH, List.Values[szCFGDBPATH]]));
- if Standard then
- begin
- if DefaultDriver = '' then
- DefaultDriver := List.Values[szCFGDBDEFAULTDRIVER];
- DBInfo.Add(Format('%s=%s', [szCFGDBDEFAULTDRIVER, DefaultDriver]));
- EnableBCD := List.Values[szCFGDBENABLEBCD];
- if EnableBCD = '' then EnableBCD := szCFGFALSE;
- DBInfo.Add(Format('%s=%s', [szCFGDBENABLEBCD, EnableBCD]));
- end;
- AddConfigRecord('\DATABASES\%s\DB INFO', OemName, DBInfo);
- finally
- DBInfo.Free;
- end;
- end;
-
- procedure AddDBOpen;
- var
- DBOpen: TStringList;
- begin
- try
- DBOpen := TStringList.Create;
- try
- GetDriverParams(Driver, DBOpen);
- MergeStrings(DBOpen, List);
- AddConfigRecord('\DATABASES\%s\DB OPEN', OemName, DBOpen);
- finally
- DBOpen.Free;
- end;
- except
- DbiCfgDropRecord(nil, PChar(Format('\DATABASES\%s\DB INFO', [Name])));
- raise;
- end;
- end;
-
- begin
- LockSession;
- try
- DefaultDriver := '';
- Standard := (Driver = '') or (CompareText(Driver, szCFGDBSTANDARD) = 0);
- if not Standard and ((CompareText(Driver, szPARADOX) = 0) or
- (CompareText(Driver, szDBASE) = 0) or
- (CompareText(Driver, szASCII) = 0)) then
- begin
- Standard := True;
- DefaultDriver := Driver;
- end;
- ValidateAliasName;
- CfgModeSave := ConfigMode;
- try
- CheckConfigMode(CfgMode);
- AddDBInfo;
- if not Standard then AddDBOpen;
- finally
- if RestoreMode then ConfigMode := CfgModeSave;
- end;
- finally
- UnlockSession;
- end;
- DBNotification(dbAddAlias, Pointer(Name));
- end;
-
- procedure TSession.InternalDeleteAlias(const Name: string;
- CfgMode: TConfigMode; RestoreMode: Boolean);
- var
- CfgModeSave: TConfigMode;
- begin
- DBNotification(dbDeleteAlias, Pointer(Name));
- LockSession;
- try
- CfgModeSave := ConfigMode;
- try
- CheckConfigMode(CfgMode);
- DeleteConfigPath('\DATABASES\%s', StrToOem(Name));
- finally
- if RestoreMode then ConfigMode := cfgModeSave;
- end;
- finally
- UnlockSession;
- end;
- end;
-
- function TSession.IsAlias(const Name: string): Boolean;
- begin
- MakeCurrent;
- Result := DbiCfgPosition(nil, PChar(Format('\DATABASES\%s', [Name]))) = 0;
- end;
-
- procedure TSession.Loaded;
- begin
- inherited Loaded;
- try
- if FStreamedActive then SetActive(True);
- except
- if csDesigning in ComponentState then
- Application.HandleException(Self)
- else
- raise;
- end;
- end;
-
- procedure TSession.LockSession;
- begin
- if FLockCount = 0 then
- begin
- EnterCriticalSection(FCSect);
- Inc(FLockCount);
- MakeCurrent;
- end
- else
- Inc(FLockCount);
- end;
-
- procedure TSession.UnLockSession;
- begin
- Dec(FLockCount);
- if FLockCount = 0 then
- LeaveCriticalSection(FCSect);
- end;
-
- procedure TSession.MakeCurrent;
- begin
- if FHandle <> nil then
- Check(DbiSetCurrSession(FHandle))
- else
- SetActive(True);
- end;
-
- procedure TSession.ModifyAlias(Name: string; List: TStrings);
- var
- DriverName: string;
- OemName: string;
- CfgModeSave: TConfigMode;
- begin
- LockSession;
- try
- CfgModeSave := ConfigMode;
- try
- CheckConfigMode(ConfigMode);
- DriverName := GetAliasDriverName(Name);
- OemName := StrToOem(Name);
- ModifyConfigParams('\DATABASES\%s\DB INFO', OemName, List);
- if DriverName <> szCFGDBSTANDARD then
- ModifyConfigParams('\DATABASES\%s\DB OPEN', OemName, List);
- finally
- ConfigMode := CfgModeSave;
- end;
- finally
- UnLockSession;
- end;
- end;
-
- procedure TSession.ModifyConfigParams(const Path, Node: string; List: TStrings);
- var
- I, J, C: Integer;
- Params: TStrings;
- begin
- Params := TStringList.Create;
- try
- GetConfigParams(Path, Node, Params);
- C := 0;
- for I := 0 to Params.Count - 1 do
- begin
- J := List.IndexOfName(Params.Names[I]);
- if J >= 0 then
- begin
- Params[I] := List[J];
- Inc(C);
- end;
- end;
- if C > 0 then SetConfigParams(Path, Node, Params);
- finally
- Params.Free;
- end;
- end;
-
- procedure TSession.Open;
- begin
- SetActive(True);
- end;
-
- function TSession.OpenDatabase(const DatabaseName: string): TDatabase;
- var
- TempDatabase: TDatabase;
- begin
- MakeCurrent;
- TempDatabase := nil;
- try
- Result := FindDatabase(DatabaseName);
- if Result = nil then
- begin
- TempDatabase := TDatabase.Create(Self);
- TempDatabase.DatabaseName := DatabaseName;
- TempDatabase.KeepConnection := FKeepConnections;
- TempDatabase.Temporary := True;
- Result := TempDatabase;
- end;
- Result.Open;
- Inc(Result.FRefCount);
- except
- TempDatabase.Free;
- raise;
- end;
- end;
-
- procedure TSession.RegisterCallbacks(Value: Boolean);
-
- procedure UnloadSMClient;
- begin
- try
- FreeMem(FSMBuffer, smTraceBufSize);
- FSMClient.Free;
- FreeLibrary(FClientLib);
- except
- end;
- end;
-
- function LoadSMClient: Boolean;
- var
- FM: THandle;
- ClientLibPath: PChar;
- ClientName: string;
- FOldCBFunc: pfDBICallBack;
- begin
- Result := False;
- try
- if DbiGetCallBack(nil, cbTrace, nil, nil, nil,
- FOldCBFunc) = DBIERR_NONE then Exit;
- FM := OpenFileMapping(FILE_MAP_READ, False, 'SMClientLib');
- if FM <> 0 then
- try
- ClientLibPath := MapViewOfFile(FM, FILE_MAP_READ, 0, 0, MAX_PATH);
- FClientLib := LoadLibrary(ClientLibPath);
- if FClientLib > 32 then
- try
- FSMRegProc := GetProcAddress(FClientLib, 'RegisterClient');
- if not Assigned(FSMRegProc) then SysUtils.Abort;
- ClientName := Application.Title;
- if ClientName = '' then ClientName := LoadStr(SUntitled);
- if not FDefault then
- ClientName := Format('%s.%s', [ClientName, SessionName]);
- FSMClient := FSMRegProc(Integer(FHandle), PChar(ClientName),
- FSMWriteProc, Self, @TSession.SMClientSignal);
- if not Assigned(FSMClient) then SysUtils.Abort;
- GetMem(FSMBuffer, smTraceBufSize);
- Result := True;
- except
- UnloadSMClient;
- FClientLib := 0;
- end;
- finally
- CloseHandle(FM);
- end;
- except
- end;
- end;
-
- var
- I: Integer;
- begin
- if Value then
- begin
- FCallbacks.Add(TBDECallback.Create(Self, nil, cbSERVERCALL,
- @FCBSCType, SizeOf(CBSCType), ServerCallBack, False));
-
- FCallbacks.Add(TBDECallback.Create(Self, nil, cbDBLOGIN,
- @FCBDBLogin, SizeOf(TCBDBLogin), DBLoginCallBack, False));
-
- if LoadSMClient then
- FCallbacks.Add(TBDECallback.Create(Self, nil, cbTRACE,
- FSMBuffer, smTraceBufSize, SqlTraceCallBack, False));
- end else
- begin
- for I := FCallbacks.Count - 1 downto 0 do
- TBDECallback(FCallbacks[I]).Free;
- FCallbacks.Clear;
- if (FClientLib <> 0) then UnloadSMClient;
- end;
- end;
-
- procedure TSession.RemoveDatabase(Value: TDatabase);
- begin
- FDatabases.Remove(Value);
- DBNotification(dbRemove, Value);
- end;
-
- procedure TSession.RemoveAllPasswords;
- begin
- LockSession;
- try
- DbiDropPassword(nil);
- finally
- UnlockSession;
- end;
- end;
-
- procedure TSession.RemovePassword(const Password: string);
- var
- Buffer: array[0..255] of Char;
- begin
- LockSession;
- try
- if Password <> '' then
- DbiDropPassword(AnsiToNative(Locale, Password, Buffer,
- SizeOf(Buffer) - 1));
- finally
- UnlockSession;
- end;
- end;
-
- procedure TSession.SaveConfigFile;
- var
- CfgModeSave: TConfigMode;
- begin
- CfgModeSave := ConfigMode;
- try
- ConfigMode := cmPersistent;
- Check(DbiCfgSave(nil, nil, False));
- finally
- ConfigMode := CfgModeSave;
- end;
- end;
-
- function TSession.ServerCallBack(CBInfo: Pointer): CBRType;
- const
- MinWait = 500;
- begin
- Result := cbrUSEDEF;
- if (FCBSCType = cbscSQL) and (GetCurrentThreadID = MainThreadID) then
- begin
- if StartTime = 0 then
- begin
- TimerID := SetTimer(0, 0, 1000, @TimerCallBack);
- AcquiredTimer := TimerID <> 0;
- StartTime := GetTickCount;
- end
- else if AcquiredTimer and (GetTickCount - StartTime > MinWait) then
- Screen.Cursor := crSQLWait;
- end;
- end;
-
- procedure TSession.SetActive(Value: Boolean);
- begin
- if csReading in ComponentState then
- FStreamedActive := Value
- else
- if Active <> Value then
- StartSession(Value);
- end;
-
- function TSession.GetConfigMode: TConfigMode;
- begin
- LockSession;
- try
- Result := TConfigMode(GetIntProp(FHandle, sesCfgMode));
- finally
- UnlockSession;
- end;
- end;
-
- procedure TSession.SetConfigMode(Value: TConfigMode);
- begin
- LockSession;
- try
- Check(DbiSetProp(hDBIObj(FHandle), sesCFGMODE, Longint(Value)));
- finally
- UnlockSession;
- end;
- end;
-
- procedure TSession.SetConfigParams(const Path, Node: string; List: TStrings);
- var
- ParamList: TParamList;
- begin
- ParamList := TParamList.Create(List);
- try
- with ParamList do
- Check(DbiCfgModifyRecord(nil, PChar(Format(Path, [Node])), FieldCount,
- PFLDDesc(FieldDescs), Buffer));
- finally
- ParamList.Free;
- end;
- end;
-
- procedure TSession.SetNetFileDir(const Value: string);
- var
- Buffer: array[0..255] of Char;
- begin
- if Active then
- begin
- LockSession;
- try
- Check(DbiSetProp(HDBIOBJ(Handle), sesNETFILE, Longint(AnsiToNative(nil,
- Value, Buffer, SizeOf(Buffer) - 1))));
- finally
- UnLockSession;
- end;
- end;
- FNetFileDir := Value;
- end;
-
- procedure TSession.SetPrivateDir(const Value: string);
- var
- Buffer: array[0..255] of Char;
- begin
- if Active then
- begin
- LockSession;
- try
- Check(DbiSetPrivateDir(AnsiToNative(nil, Value, Buffer,
- SizeOf(Buffer) - 1)));
- finally
- UnlockSession;
- end;
- end;
- FPrivateDir := Value;
- end;
-
- procedure TSession.SetSessionName(const Value: string);
- var
- Ses: TSession;
- begin
- CheckInActive;
- if Value <> '' then
- begin
- Ses := Sessions.FindSession(Value);
- if not ((Ses = nil) or (Ses = Self)) then
- DBErrorFmt(SDuplicateSessionName, [Value]);
- end;
- FSessionName := Value
- end;
-
- procedure TSession.SetTraceFlags(Value: TTraceFlags);
- var
- I: Integer;
- begin
- FTraceFlags := Value;
- for I := FDatabases.Count - 1 downto 0 do
- with TDatabase(FDatabases[I]) do
- TraceFlags := FTraceFlags;
- end;
-
- procedure TSession.SMClientSignal(Sender: TObject; Data: Integer);
- begin
- SetTraceFlags(TTraceFlags(Word(Data)));
- end;
-
- function TSession.SqlTraceCallBack(CBInfo: Pointer): CBRType;
- var
- Len: Integer;
- Data: PChar;
- begin
- Result := cbrUSEDEF;
- try
- Data := @PTraceDesc(CBInfo).pszTrace;
- Len := StrLen(Data);
- if not FSMWriteProc(FSMClient, Data, Len) then SysUtils.abort;
- except
- SetTraceFlags([]);
- end;
- end;
-
- procedure TSession.StartSession(Value: Boolean);
- var
- I: Integer;
- begin
- EnterCriticalSection(FCSect);
- try
- if Value then
- begin
- if Assigned(FOnStartup) then FOnStartup(Self);
- if FSessionName = '' then DBError(SSessionNameMissing);
- if (DB.Session <> Self) then DB.Session.Active := True;
- if FDefault then
- InitializeBDE
- else
- Check(DbiStartSession(nil, FHandle, nil));
- try
- RegisterCallbacks(True);
- if FNetFileDir <> '' then SetNetFileDir(FNetFileDir);
- if FPrivateDir <> '' then SetPrivateDir(FPrivateDir);
- ConfigMode := cmAll;
- CallBDEInitProcs;
- except
- StartSession(False);
- raise;
- end;
- end else
- begin
- DbiSetCurrSession(FHandle);
- for I := FDatabases.Count - 1 downto 0 do
- with TDatabase(FDatabases[I]) do
- if Temporary then Free else Close;
- RegisterCallbacks(False);
- if FDefault then
- begin
- if not FDLLDetach then
- begin
- if IsLibrary then
- begin
- DbiRegisterCallback(nil, cbDETACHNOTIFY, 0, 0, @DLLDetachCallBack, nil);
- DbiDLLExit;
- end;
- DbiExit;
- end;
- end
- else
- begin
- Check(DbiCloseSession(FHandle));
- DbiSetCurrSession(Session.FHandle);
- end;
- FHandle := nil;
- end;
- finally
- LeaveCriticalSection(FCSect);
- end;
- end;
-
- { TParamList }
-
- constructor TParamList.Create(Params: TStrings);
- var
- I, P, FieldNo: Integer;
- BufPtr: PChar;
- S: string;
- begin
- for I := 0 to Params.Count - 1 do
- begin
- S := Params[I];
- P := Pos('=', S);
- if P <> 0 then
- begin
- Inc(FFieldCount);
- Inc(FBufSize, Length(S) - P + 1);
- end;
- end;
- if FFieldCount > 0 then
- begin
- FFieldDescs := AllocMem(FFieldCount * SizeOf(FLDDesc));
- FBuffer := AllocMem(FBufSize);
- FieldNo := 0;
- BufPtr := FBuffer;
- for I := 0 to Params.Count - 1 do
- begin
- S := Params[I];
- P := Pos('=', S);
- if P <> 0 then
- with FFieldDescs^[FieldNo] do
- begin
- Inc(FieldNo);
- iFldNum := FieldNo;
- StrPLCopy(szName, Copy(S, 1, P - 1), SizeOf(szName) - 1);
- iFldType := fldZSTRING;
- iOffset := BufPtr - FBuffer;
- iLen := Length(S) - P + 1;
- StrCopy(BufPtr, PChar(Copy(S, P + 1, 255)));
- CharToOem(BufPtr, BufPtr);
- Inc(BufPtr, iLen);
- end;
- end;
- end;
- end;
-
- destructor TParamList.Destroy;
- begin
- DisposeMem(FFieldDescs, FFieldCount * SizeOf(FLDDesc));
- DisposeMem(FBuffer, FBufSize);
- end;
-
- { TDatabase }
-
- constructor TDatabase.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- Exclude(FComponentStyle, csInheritable);
- if AOwner is TSession then
- FSession := TSession(AOwner) else
- FSession := DB.Session;
- SessionName := FSession.SessionName;
- FSession.AddDatabase(Self);
- FDataSets := TList.Create;
- FParams := TStringList.Create;
- TStringList(FParams).OnChanging := ParamsChanging;
- FLoginPrompt := True;
- FKeepConnection := True;
- FLocale := FSession.Locale;
- FTransIsolation := tiReadCommitted;
- end;
-
- destructor TDatabase.Destroy;
- begin
- Close;
- FParams.Free;
- FDataSets.Free;
- if FSession <> nil then
- FSession.RemoveDatabase(Self);
- inherited Destroy;
- end;
-
- procedure TDatabase.ApplyUpdates(const DataSets: array of TDBDataSet);
- var
- I: Integer;
- DS: TDBDataSet;
- begin
- StartTransaction;
- try
- for I := 0 to High(DataSets) do
- begin
- DS := DataSets[I];
- if DS.Database <> Self then
- DatabaseError(FmtLoadStr(SUpdateWrongDB, [DS.Name, Name]));
- DataSets[I].ApplyUpdates;
- end;
- Commit;
- except
- Rollback;
- raise;
- end;
- for I := 0 to High(DataSets) do
- DataSets[I].CommitUpdates;
- end;
-
- procedure TDatabase.CheckActive;
- begin
- if FHandle = nil then DBError(SDatabaseClosed);
- end;
-
- procedure TDatabase.CheckInactive;
- begin
- if FHandle <> nil then DBError(SDatabaseOpen);
- end;
-
- procedure TDatabase.CheckDatabaseName;
- begin
- if (FDatabaseName = '') and not Temporary then
- DBError(SDatabaseNameMissing);
- end;
-
- procedure TDatabase.CheckSessionName(Required: Boolean);
- var
- NewSession: TSession;
- begin
- if Required then
- NewSession := Sessions.List[FSessionName]
- else
- NewSession := Sessions.FindSession(FSessionName);
- if (NewSession <> nil) and (NewSession <> FSession) then
- begin
- FSession.RemoveDatabase(Self);
- FSession := NewSession;
- FSession.AddDatabase(Self);
- end;
- if Required then FSession.Active := True;
- end;
-
- procedure TDatabase.Close;
- begin
- if FHandle <> nil then
- begin
- Session.DBNotification(dbClose, Self);
- CloseDataSets;
- if FLocaleLoaded then OsLdUnloadObj(FLocale);
- FLocaleLoaded := False;
- FLocale := DB.Session.Locale;
- if not FAcquiredHandle then
- DbiCloseDatabase(FHandle)
- else
- FAcquiredHandle := False;
- FSQLBased := False;
- FHandle := nil;
- FRefCount := 0;
- if FSessionAlias then
- begin
- FSession.InternalDeleteAlias(FDatabaseName, cmSession, True);
- FSessionAlias := False;
- end;
- end;
- end;
-
- procedure TDatabase.CloseDataSets;
- begin
- while FDataSets.Count <> 0 do TDBDataSet(FDataSets.Last).Disconnect;
- end;
-
- procedure TDatabase.Commit;
- begin
- CheckActive;
- EndTransaction(xendCOMMIT);
- end;
-
- procedure TDatabase.EndTransaction(TransEnd: EXEnd);
- begin
- if FTransHandle = nil then DBErrorFmt(SEndTransError, [FDatabaseName]);
- Check(DbiEndTran(FHandle, FTransHandle, TransEnd));
- FTransHandle := nil;
- end;
-
- function TDatabase.GetAliasName: string;
- begin
- if FAliased then Result := FDatabaseType else Result := '';
- end;
-
- function TDatabase.GetConnected: Boolean;
- begin
- Result := FHandle <> nil;
- end;
-
- function TDatabase.GetDataSet(Index: Integer): TDBDataSet;
- begin
- Result := FDataSets[Index];
- end;
-
- function TDatabase.GetDataSetCount: Integer;
- begin
- Result := FDataSets.Count;
- end;
-
- function TDatabase.GetDirectory: string;
- var
- SDirectory: DBIPATH;
- begin
- Check(DbiGetDirectory(Handle, False, SDirectory));
- SetLength(Result, StrLen(SDirectory));
- OemToChar(SDirectory, PChar(Result));
- end;
-
- function TDatabase.GetDriverName: string;
- begin
- if FAliased then Result := '' else Result := FDatabaseType;
- end;
-
- function TDatabase.GetIsSQLBased: Boolean;
- var
- Length: Word;
- Buffer: array[0..63] of Char;
- begin
- Result := False;
- if FHandle <> nil then
- begin
- Check(DbiGetProp(HDBIOBJ(FHandle), dbDATABASETYPE, @Buffer,
- SizeOf(Buffer), Length));
- Result := StrIComp(Buffer, szCFGDBSTANDARD) <> 0;
- end;
- end;
-
- function TDatabase.GetTraceFlags: TTraceFlags;
- begin
- if Connected and IsSQLBased then
- Result := TTraceFlags(Word(GetIntProp(FHandle, dbTraceMode)))
- else
- Result := [];
- end;
-
- function TDatabase.GetInTransaction: Boolean;
- var
- X: XInfo;
- begin
- Result := (Handle <> nil) and (DbiGetTranInfo(Handle, nil, @X) = DBIERR_NONE)
- and (X.exState = xsActive);
- end;
-
- procedure TDatabase.Loaded;
- begin
- inherited Loaded;
- try
- if FStreamedConnected then Open
- else CheckSessionName(False);
- except
- if csDesigning in ComponentState then
- Application.HandleException(Self)
- else
- raise;
- end;
- end;
-
- procedure TDatabase.LoadLocale;
- var
- LName: DBIName;
- DBLocale: TLocale;
- begin
- if IsSQLBased and (DbiGetLdNameFromDB(FHandle, nil, LName) = 0) and
- (OsLdLoadBySymbName(LName, DBLocale) = 0) then
- begin
- FLocale := DBLocale;
- FLocaleLoaded := True;
- end;
- end;
-
- procedure TDatabase.Login(LoginParams: TStrings);
- var
- UserName, Password: string;
- begin
- if Assigned(FOnLogin) then FOnLogin(Self, LoginParams) else
- begin
- UserName := LoginParams.Values[szUSERNAME];
- if not LoginDialogEx(DatabaseName, UserName, Password, False) then
- DBErrorFmt(SLoginError, [DatabaseName]);
- LoginParams.Values[szUSERNAME] := UserName;
- LoginParams.Values[szPASSWORD] := Password;
- end;
- end;
-
- procedure TDatabase.CheckDatabaseAlias(var Password: string);
- var
- Desc: DBDesc;
- Aliased: Boolean;
- DBName: string;
- DriverType: string;
- AliasParams: TStringList;
- LoginParams: TStringList;
-
- function NeedsDBAlias: Boolean;
- var
- I: Integer;
- PName: String;
- begin
- Result := not Aliased or ((FDatabaseType <> '') and
- (FDatabaseName <> FDatabaseType));
- for I := 0 to FParams.Count - 1 do
- begin
- if AliasParams.IndexOf(FParams[I]) > -1 then continue;
- PName := FParams.Names[I];
- if (CompareText(PName, szPASSWORD) = 0) then continue;
- if AliasParams.IndexOfName(PName) > -1 then
- begin
- Result := True;
- AliasParams.Values[PName] := FParams.Values[PName];
- end;
- end;
- end;
-
- begin
- Password := '';
- FSessionAlias := False;
- AliasParams := TStringList.Create;
- try
- begin
- if FDatabaseType <> '' then
- begin
- DBName := FDatabaseType;
- Aliased := FAliased;
- end else
- begin
- DBName := FDatabaseName;
- Aliased := True;
- end;
- if Aliased then
- begin
- if DbiGetDatabaseDesc(PChar(StrToOem(DBName)), @Desc) <> 0 then Exit;
- if Desc.szDBType[sizeOf(Desc.szDBType) - 1] <> #0 then
- Desc.szDBType[sizeOf(Desc.szDBType) - 1] := #0;
- OemToChar(Desc.szDbType, Desc.szDbType);
- DriverType := Desc.szDbType;
- FSession.GetAliasParams(DBName, AliasParams);
- end else
- begin
- FSession.GetDriverParams(DBName, AliasParams);
- DriverType := FDatabaseType;
- end;
- if (DriverType <> szCFGDBSTANDARD) then
- begin
- if LoginPrompt then
- begin
- LoginParams := TStringList.Create;
- try
- if FParams.Values[szUSERNAME] = '' then
- FParams.Values[szUSERNAME] := AliasParams.Values[szUSERNAME];
- LoginParams.Values[szUSERNAME] := FParams.Values[szUSERNAME];
- Login(LoginParams);
- Password := LoginParams.Values[szPASSWORD];
- FParams.Values[szUSERNAME] := LoginParams.Values[szUSERNAME];
- finally
- LoginParams.Free;
- end;
- end else
- Password := FParams.Values[szPASSWORD];
- end;
- end;
- if NeedsDBAlias then
- begin
- FSession.InternalAddAlias(FDatabaseName, DriverType, AliasParams,
- cmSession, False);
- FSessionAlias := True;
- end;
- finally
- AliasParams.Free;
- end;
- end;
-
- procedure TDatabase.Open;
- var
- DBName: string;
- DBPassword: string;
- CfgModeSave: TConfigMode;
- begin
- if FHandle = nil then
- begin
- CheckDatabaseName;
- CheckSessionName(True);
- FSession.LockSession;
- try
- CfgModeSave := FSession.ConfigMode;
- try
- CheckDatabaseAlias(DBPassword);
- try
- if (FDatabaseType = '') and IsDirectory(FDatabaseName) then
- DBName := '' else
- DBName := StrToOem(FDatabaseName);
- Check(DbiOpenDatabase(Pointer(DBName), nil, dbiREADWRITE, dbiOPENSHARED,
- Pointer(StrToOem(DBPassword)), 0, nil, nil, FHandle));
- if DBName = '' then SetDirectory(FDatabaseName);
- DbiSetProp(HDBIOBJ(FHandle), dbUSESCHEMAFILE, Longint(True));
- DbiSetProp(HDBIOBJ(FHandle), dbPARAMFMTQMARK, Longint(True));
- FSQLBased := GetIsSQLBased;
- LoadLocale;
- TraceFlags := FSession.FTraceFlags;
- Session.DBNotification(dbOpen, Self);
- except
- if FSessionAlias then
- FSession.InternalDeleteAlias(FDatabaseName, cmSession, False);
- raise;
- end;
- finally
- FSession.ConfigMode := CfgModeSave;
- end;
- finally
- FSession.UnlockSession;
- end;
- end;
- end;
-
- procedure TDatabase.ParamsChanging(Sender: TObject);
- begin
- CheckInactive;
- end;
-
- procedure TDatabase.Rollback;
- begin
- CheckActive;
- EndTransaction(xendABORT);
- end;
-
- procedure TDatabase.SetAliasName(const Value: string);
- begin
- SetDatabaseType(Value, True);
- end;
-
- procedure TDatabase.SetConnected(Value: Boolean);
- begin
- if csReading in ComponentState then
- FStreamedConnected := Value
- else
- if Value then Open else Close;
- end;
-
- procedure TDatabase.SetDatabaseName(const Value: string);
- begin
- if FDatabaseName <> Value then
- begin
- CheckInactive;
- ValidateName(Value);
- FDatabaseName := Value;
- end;
- end;
-
- procedure TDatabase.SetDatabaseType(const Value: string;
- Aliased: Boolean);
- begin
- CheckInactive;
- FDatabaseType := Value;
- FAliased := Aliased;
- end;
-
- procedure TDatabase.SetDirectory(const Value: string);
- begin
- Check(DbiSetDirectory(Handle, Pointer(StrToOem(Value))));
- end;
-
- procedure TDatabase.SetDriverName(const Value: string);
- begin
- SetDatabaseType(Value, False);
- end;
-
- procedure TDatabase.SetHandle(Value: HDBIDB);
- var
- DBSession: HDBISes;
- begin
- if Connected then Close;
- if Value <> nil then
- begin
- Check(DbiGetObjFromObj(HDBIObj(Value), objSESSION, HDBIObj(DBSession)));
- CheckDatabaseName;
- CheckSessionName(True);
- if FSession.Handle <> DBSession then DBError(SDatabaseHandleSet);
- FHandle := Value;
- FSQLBased := GetIsSQLBased;
- LoadLocale;
- Session.DBNotification(dbOpen, Self);
- FAcquiredHandle := True;
- end;
- end;
-
- procedure TDatabase.SetKeepConnection(Value: Boolean);
- begin
- if FKeepConnection <> Value then
- begin
- FKeepConnection := Value;
- if not Value and (FRefCount = 0) then Close;
- end;
- end;
-
- procedure TDatabase.SetParams(Value: TStrings);
- begin
- CheckInactive;
- FParams.Assign(Value);
- end;
-
- procedure TDatabase.SetSessionName(const Value: string);
- begin
- CheckInactive;
- if FSessionName <> Value then
- begin
- FSessionName := Value;
- CheckSessionName(False);
- end;
- end;
-
- procedure TDatabase.SetTraceFlags(Value: TTraceFlags);
- begin
- if Connected and IsSQLBased then
- DbiSetProp(hDBIObj(FHandle), dbTraceMode, Integer(Word(Value)));
- end;
-
- procedure TDatabase.StartTransaction;
- begin
- CheckActive;
- if FTransHandle <> nil then DBErrorFmt(SBeginTransError, [FDatabaseName]);
- if not IsSQLBased and (TransIsolation <> tiDirtyRead) then
- DBError(SLocalTransDirty);
- Check(DbiBeginTran(FHandle, EXILType(FTransIsolation), FTransHandle));
- end;
-
- procedure TDatabase.ValidateName(const Name: string);
- var
- Database: TDatabase;
- begin
- if Name <> '' then
- begin
- Database := FSession.FindDatabase(Name);
- if (Database <> nil) and (Database <> Self) then
- begin
- if not Database.Temporary or (Database.FRefCount <> 0) then
- DBErrorFmt(SDuplicateDatabaseName, [Name]);
- Database.Free;
- end;
- end;
- end;
-
- procedure TDatabase.FlushSchemaCache(const TableName: string);
- begin
- if Connected and IsSQLBased then
- Check(DbiSchemaCacheFlush(FHandle, PChar(TableName)));
- end;
-
- { TDataSetDesigner }
-
- constructor TDataSetDesigner.Create(DataSet: TDataSet);
- begin
- FDataSet := DataSet;
- FDataSet.FDesigner := Self;
- end;
-
- destructor TDataSetDesigner.Destroy;
- begin
- FDataSet.FDesigner := nil;
- end;
-
- procedure TDataSetDesigner.BeginDesign;
- begin
- FSaveActive := FDataSet.Active;
- if FSaveActive then
- begin
- FDataSet.InternalClose;
- FDataSet.SetState(dsInactive);
- end;
- FDataSet.DisableControls;
- end;
-
- procedure TDataSetDesigner.DataEvent(Event: TDataEvent; Info: Longint);
- begin
- end;
-
- procedure TDataSetDesigner.EndDesign;
- begin
- FDataSet.EnableControls;
- if FSaveActive then
- begin
- try
- FDataSet.InternalOpen;
- FDataSet.SetState(dsBrowse);
- except
- FDataSet.SetState(dsInactive);
- FDataSet.CloseCursor;
- raise;
- end;
- end;
- end;
-
- { TFieldDef }
-
- constructor TFieldDef.Create(Owner: TFieldDefs; const Name: string;
- DataType: TFieldType; Size: Word; Required: Boolean; FieldNo: Integer);
- begin
- CheckTypeSize(DataType, Size);
- if Owner <> nil then
- begin
- Owner.FItems.Add(Self);
- Owner.FUpdated := False;
- FOwner := Owner;
- end;
- FName := Name;
- FDataType := DataType;
- FSize := Size;
- FRequired := Required;
- FFieldNo := FieldNo;
- end;
-
- destructor TFieldDef.Destroy;
- begin
- if FOwner <> nil then
- begin
- FOwner.FItems.Remove(Self);
- FOwner.FUpdated := False;
- end;
- end;
-
- function TFieldDef.CreateField(Owner: TComponent): TField;
- var
- FieldClass: TFieldClass;
- begin
- FieldClass := GetFieldClass;
- if FieldClass = nil then DBErrorFmt(SUnknownFieldType, [Name]);
- Result := FieldClass.Create(Owner);
- try
- Result.FieldName := Name;
- Result.Size := FSize;
- Result.Required := FRequired;
- Result.SetFieldType(FDataType);
- if FOwner <> nil then Result.DataSet := FOwner.FDataSet;
- except
- Result.Free;
- raise;
- end;
- end;
-
- function TFieldDef.GetFieldClass: TFieldClass;
- const
- FieldClasses: array[TFieldType] of TFieldClass = (
- nil, { ftUnknown }
- TStringField, { ftString }
- TSmallintField, { ftSmallint }
- TIntegerField, { ftInteger }
- TWordField, { ftWord }
- TBooleanField, { ftBoolean }
- TFloatField, { ftFloat }
- TCurrencyField, { ftCurrency }
- TBCDField, { ftBCD }
- TDateField, { ftDate }
- TTimeField, { ftTime }
- TDateTimeField, { ftDateTime }
- TBytesField, { ftBytes }
- TVarBytesField, { ftVarBytes }
- TAutoIncField, { ftAutoInc }
- TBlobField, { ftBlob }
- TMemoField, { ftMemo }
- TGraphicField, { ftGraphic }
- TBlobField, { ftFmtMemo }
- TBlobField, { ftParadoxOle }
- TBlobField, { ftDBaseOle }
- TBlobField); { ftTypedBinary }
- begin
- Result := FieldClasses[FDataType];
- end;
-
- { TFieldDefs }
-
- constructor TFieldDefs.Create(DataSet: TDataSet);
- begin
- FDataSet := DataSet;
- FItems := TList.Create;
- end;
-
- destructor TFieldDefs.Destroy;
- begin
- if FItems <> nil then Clear;
- FItems.Free;
- end;
-
- procedure TFieldDefs.Add(const Name: string; DataType: TFieldType;
- Size: Word; Required: Boolean);
- begin
- if Name = '' then DBError(SFieldNameMissing);
- if IndexOf(Name) >= 0 then DBErrorFmt(SDuplicateFieldName, [Name]);
- TFieldDef.Create(Self, Name, DataType, Size, Required, FItems.Count + 1);
- end;
-
- procedure TFieldDefs.AddFieldDesc(FieldDesc: FLDDesc; Required: Boolean;
- FieldNo: Word);
- const
- TypeMap: array[0..MAXLOGFLDTYPES - 1] of TFieldType = (
- ftUnknown, ftString, ftDate, ftBlob, ftBoolean, ftSmallint,
- ftInteger, ftFloat, ftBCD, ftBytes, ftTime, ftDateTime,
- ftWord, ftInteger, ftUnknown, ftVarBytes, ftUnknown);
- BlobTypeMap: array[fldstMEMO..fldstTYPEDBINARY] of TFieldType = (
- ftMemo, ftBlob, ftFmtMemo, ftParadoxOle, ftGraphic,
- ftDBaseOle, ftTypedBinary);
- var
- DataType: TFieldType;
- Size: Word;
- I: Integer;
- FieldName, Name: string;
- begin
- with FieldDesc do
- begin
- NativeToAnsi(FDataSet.Locale, szName, FieldName);
- I := 0;
- Name := FieldName;
- while IndexOf(Name) >= 0 do
- begin
- Inc(I);
- Name := Format('%s_%d', [FieldName, I]);
- end;
- if iFldType < MAXLOGFLDTYPES then
- DataType := TypeMap[iFldType] else
- DataType := ftUnknown;
- Size := 0;
- case iFldType of
- fldZSTRING:
- Size := iUnits1;
- fldINT16, fldUINT16:
- if iLen <> 2 then DataType := ftUnknown;
- fldINT32:
- if iSubType = fldstAUTOINC then DataType := ftAutoInc;
- fldFLOAT:
- if iSubType = fldstMONEY then DataType := ftCurrency;
- fldBCD:
- Size := Abs(iUnits2);
- fldBYTES, fldVARBYTES:
- Size := iUnits1;
- fldBLOB:
- begin
- Size := iUnits1;
- if (iSubType >= fldstMEMO) and (iSubType <= fldstTYPEDBINARY) then
- DataType := BlobTypeMap[iSubType];
- end;
- end;
- if DataType <> ftUnknown then
- with TFieldDef.Create(Self, Name, DataType, Size, Required, FieldNo) do
- FBDECalcField := bCalcField;
- end;
- end;
-
- procedure TFieldDefs.Assign(FieldDefs: TFieldDefs);
- var
- I: Integer;
- begin
- Clear;
- for I := 0 to FieldDefs.Count - 1 do
- with FieldDefs[I] do Add(Name, DataType, Size, Required);
- end;
-
- procedure TFieldDefs.Clear;
- begin
- while FItems.Count > 0 do TFieldDef(FItems.Last).Free;
- end;
-
- function TFieldDefs.Find(const Name: string): TFieldDef;
- var
- I: Integer;
- begin
- I := IndexOf(Name);
- if I < 0 then DBErrorFmt(SFieldNotFound, [Name]);
- Result := FItems[I];
- end;
-
- function TFieldDefs.GetCount: Integer;
- begin
- Result := FItems.Count;
- end;
-
- function TFieldDefs.GetItem(Index: Integer): TFieldDef;
- begin
- Result := FItems[Index];
- end;
-
- function TFieldDefs.IndexOf(const Name: string): Integer;
- begin
- for Result := 0 to FItems.Count - 1 do
- if AnsiCompareText(TFieldDef(FItems[Result]).Name, Name) = 0 then Exit;
- Result := -1;
- end;
-
- procedure TFieldDefs.Update;
- begin
- FDataSet.UpdateFieldDefs;
- end;
-
- { TFilterExpr }
-
- type
-
- TExprNodeKind = (enField, enConst, enOperator);
-
- PExprNode = ^TExprNode;
- TExprNode = record
- FNext: PExprNode;
- FKind: TExprNodeKind;
- FPartial: Boolean;
- FOperator: CanOp;
- FData: Variant;
- FLeft: PExprNode;
- FRight: PExprNode;
- end;
-
- TFilterExpr = class
- private
- FDataSet: TDataSet;
- FOptions: TFilterOptions;
- FNodes: PExprNode;
- FExprBuffer: PCANExpr;
- FExprBufSize: Integer;
- FExprNodeSize: Integer;
- FExprDataSize: Integer;
- function FieldFromNode(Node: PExprNode): TField;
- function GetExprData(Pos, Size: Integer): PChar;
- function PutCompareNode(Node: PExprNode): Integer;
- function PutConstBCD(const Value: Variant; Decimals: Integer): Integer;
- function PutConstDate(const Value: Variant): Integer;
- function PutConstDateTime(const Value: Variant): Integer;
- function PutConstFloat(const Value: Variant): Integer;
- function PutConstInt(DataType: Integer; const Value: Variant): Integer;
- function PutConstNode(DataType: Integer; Data: PChar;
- Size: Integer): Integer;
- function PutConstStr(const Value: string): Integer;
- function PutConstTime(const Value: Variant): Integer;
- function PutData(Data: PChar; Size: Integer): Integer;
- function PutExprNode(Node: PExprNode): Integer;
- function PutFieldNode(Field: TField): Integer;
- function PutNode(NodeType: NodeClass; OpType: CanOp;
- OpCount: Integer): Integer;
- procedure SetNodeOp(Node, Index, Data: Integer);
- public
- constructor Create(DataSet: TDataSet; Options: TFilterOptions);
- destructor Destroy; override;
- function NewCompareNode(Field: TField; Operator: CanOp;
- const Value: Variant): PExprNode;
- function NewNode(Kind: TExprNodeKind; Operator: CanOp;
- const Data: Variant; Left, Right: PExprNode): PExprNode;
- function GetFilterData(Root: PExprNode): PCANExpr;
- end;
-
- constructor TFilterExpr.Create(DataSet: TDataSet; Options: TFilterOptions);
- begin
- FDataSet := DataSet;
- FOptions := Options;
- end;
-
- destructor TFilterExpr.Destroy;
- var
- Node: PExprNode;
- begin
- FreeMem(FExprBuffer, FExprBufSize);
- while FNodes <> nil do
- begin
- Node := FNodes;
- FNodes := Node^.FNext;
- Dispose(Node);
- end;
- end;
-
- function TFilterExpr.FieldFromNode(Node: PExprNode): TField;
- begin
- Result := FDataSet.FieldByName(Node^.FData);
- if Result.FieldKind <> fkData then
- DBErrorFmt(SExprBadField, [Result.FieldName]);
- end;
-
- function TFilterExpr.GetExprData(Pos, Size: Integer): PChar;
- begin
- ReallocMem(FExprBuffer, FExprBufSize + Size);
- Move(PChar(FExprBuffer)[Pos], PChar(FExprBuffer)[Pos + Size],
- FExprBufSize - Pos);
- Inc(FExprBufSize, Size);
- Result := PChar(FExprBuffer) + Pos;
- end;
-
- function TFilterExpr.GetFilterData(Root: PExprNode): PCANExpr;
- begin
- FExprBufSize := SizeOf(CANExpr);
- GetMem(FExprBuffer, FExprBufSize);
- PutExprNode(Root);
- with FExprBuffer^ do
- begin
- iVer := CANEXPRVERSION;
- iTotalSize := FExprBufSize;
- iNodes := $FFFF;
- iNodeStart := SizeOf(CANExpr);
- iLiteralStart := FExprNodeSize + SizeOf(CANExpr);
- end;
- Result := FExprBuffer;
- end;
-
- function TFilterExpr.NewCompareNode(Field: TField; Operator: CanOp;
- const Value: Variant): PExprNode;
- begin
- Result := NewNode(enOperator, Operator, Unassigned,
- NewNode(enField, canNOTDEFINED, Field.FieldName, nil, nil),
- NewNode(enConst, canNOTDEFINED, Value, nil, nil));
- end;
-
- function TFilterExpr.NewNode(Kind: TExprNodeKind; Operator: CanOp;
- const Data: Variant; Left, Right: PExprNode): PExprNode;
- begin
- New(Result);
- with Result^ do
- begin
- FNext := FNodes;
- FKind := Kind;
- FPartial := False;
- FOperator := Operator;
- FData := Data;
- FLeft := Left;
- FRight := Right;
- end;
- FNodes := Result;
- end;
-
- function TFilterExpr.PutCompareNode(Node: PExprNode): Integer;
- const
- ReverseOperator: array[canEQ..canLE] of CanOp = (
- canEQ, canNE, canLT, canGT, canLE, canGE);
- var
- Operator: CanOp;
- Left, Right, Temp: PExprNode;
- Field: TField;
- FieldPos, ConstPos, CaseInsensitive, PartialLength, L: Integer;
- S: string;
- begin
- Operator := Node^.FOperator;
- Left := Node^.FLeft;
- Right := Node^.FRight;
- if Right^.FKind = enField then
- begin
- Temp := Left;
- Left := Right;
- Right := Temp;
- Operator := ReverseOperator[Operator];
- end;
- if (Left^.FKind <> enField) or (Right^.FKind <> enConst) then
- DBError(SExprBadCompare);
- Field := FieldFromNode(Left);
- if VarIsNull(Right^.FData) then
- begin
- case Operator of
- canEQ: Operator := canISBLANK;
- canNE: Operator := canNOTBLANK;
- else
- DBError(SExprBadNullTest);
- end;
- Result := PutNode(nodeUNARY, Operator, 1);
- SetNodeOp(Result, 0, PutFieldNode(Field));
- end else
- begin
- if ((Operator = canEQ) or (Operator = canNE)) and
- (Field.DataType = ftString) then
- begin
- S := Right^.FData;
- L := Length(S);
- if L <> 0 then
- begin
- CaseInsensitive := 0;
- PartialLength := 0;
- if foCaseInsensitive in FOptions then CaseInsensitive := 1;
- if Node^.FPartial then PartialLength := L else
- if not (foNoPartialCompare in FOptions) and (L > 1) and
- (S[L] = '*') then
- begin
- Delete(S, L, 1);
- PartialLength := L - 1;
- end;
- if (CaseInsensitive <> 0) or (PartialLength <> 0) then
- begin
- Result := PutNode(nodeCOMPARE, Operator, 4);
- SetNodeOp(Result, 0, CaseInsensitive);
- SetNodeOp(Result, 1, PartialLength);
- SetNodeOp(Result, 2, PutFieldNode(Field));
- SetNodeOp(Result, 3, PutConstStr(S));
- Exit;
- end;
- end;
- end;
- Result := PutNode(nodeBINARY, Operator, 2);
- FieldPos := PutFieldNode(Field);
- case Field.DataType of
- ftString:
- ConstPos := PutConstStr(Right^.FData);
- ftSmallint:
- ConstPos := PutConstInt(fldINT16, Right^.FData);
- ftInteger, ftAutoInc:
- ConstPos := PutConstInt(fldINT32, Right^.FData);
- ftWord:
- ConstPos := PutConstInt(fldUINT16, Right^.FData);
- ftFloat, ftCurrency:
- ConstPos := PutConstFloat(Right^.FData);
- ftBCD:
- ConstPos := PutConstBCD(Right^.FData, Field.Size);
- ftDate:
- ConstPos := PutConstDate(Right^.FData);
- ftTime:
- ConstPos := PutConstTime(Right^.FData);
- ftDateTime:
- ConstPos := PutConstDateTime(Right^.FData);
- else
- DBErrorFmt(SExprBadField, [Field.FieldName]);
- end;
- SetNodeOp(Result, 0, FieldPos);
- SetNodeOp(Result, 1, ConstPos);
- end;
- end;
-
- function TFilterExpr.PutConstBCD(const Value: Variant;
- Decimals: Integer): Integer;
- var
- C: Currency;
- BCD: FMTBcd;
- begin
- if VarType(Value) = varString then
- C := StrToCurr(string(TVarData(Value).VString)) else
- C := Value;
- CurrToBCD(C, BCD, 32, Decimals);
- Result := PutConstNode(fldBCD, @BCD, 18);
- end;
-
- function TFilterExpr.PutConstDate(const Value: Variant): Integer;
- var
- DateTime: TDateTime;
- TimeStamp: TTimeStamp;
- begin
- if VarType(Value) = varString then
- DateTime := StrToDate(string(TVarData(Value).VString)) else
- DateTime := VarToDateTime(Value);
- TimeStamp := DateTimeToTimeStamp(DateTime);
- Result := PutConstNode(fldDATE, @TimeStamp.Date, 4);
- end;
-
- function TFilterExpr.PutConstDateTime(const Value: Variant): Integer;
- var
- DateTime: TDateTime;
- DateData: Double;
- begin
- if VarType(Value) = varString then
- DateTime := StrToDateTime(string(TVarData(Value).VString)) else
- DateTime := VarToDateTime(Value);
- DateData := TimeStampToMSecs(DateTimeToTimeStamp(DateTime));
- Result := PutConstNode(fldTIMESTAMP, @DateData, 8);
- end;
-
- function TFilterExpr.PutConstFloat(const Value: Variant): Integer;
- var
- F: Double;
- begin
- if VarType(Value) = varString then
- F := StrToFloat(string(TVarData(Value).VString)) else
- F := Value;
- Result := PutConstNode(fldFLOAT, @F, SizeOf(Double));
- end;
-
- function TFilterExpr.PutConstInt(DataType: Integer;
- const Value: Variant): Integer;
- var
- I, Size: Integer;
- begin
- if VarType(Value) = varString then
- I := StrToInt(string(TVarData(Value).VString)) else
- I := Value;
- Size := 2;
- case DataType of
- fldINT16:
- if (I < -32768) or (I > 32767) then DBError(SExprRangeError);
- fldUINT16:
- if (I < 0) or (I > 65535) then DBError(SExprRangeError);
- else
- Size := 4;
- end;
- Result := PutConstNode(DataType, @I, Size);
- end;
-
- function TFilterExpr.PutConstNode(DataType: Integer; Data: PChar;
- Size: Integer): Integer;
- begin
- Result := PutNode(nodeCONST, canCONST2, 3);
- SetNodeOp(Result, 0, DataType);
- SetNodeOp(Result, 1, Size);
- SetNodeOp(Result, 2, PutData(Data, Size));
- end;
-
- function TFilterExpr.PutConstStr(const Value: string): Integer;
- var
- Buffer: array[0..255] of Char;
- begin
- AnsiToNative(FDataSet.Locale, Value, Buffer, SizeOf(Buffer) - 1);
- Result := PutConstNode(fldZSTRING, Buffer, StrLen(Buffer) + 1);
- end;
-
- function TFilterExpr.PutConstTime(const Value: Variant): Integer;
- var
- DateTime: TDateTime;
- TimeStamp: TTimeStamp;
- begin
- if VarType(Value) = varString then
- DateTime := StrToTime(string(TVarData(Value).VString)) else
- DateTime := VarToDateTime(Value);
- TimeStamp := DateTimeToTimeStamp(DateTime);
- Result := PutConstNode(fldTIME, @TimeStamp.Time, 4);
- end;
-
- function TFilterExpr.PutData(Data: PChar; Size: Integer): Integer;
- begin
- Move(Data^, GetExprData(FExprBufSize, Size)^, Size);
- Result := FExprDataSize;
- Inc(FExprDataSize, Size);
- end;
-
- function TFilterExpr.PutExprNode(Node: PExprNode): Integer;
- const
- BoolFalse: WordBool = False;
- var
- Field: TField;
- begin
- case Node^.FKind of
- enField:
- begin
- Field := FieldFromNode(Node);
- if Field.DataType <> ftBoolean then
- DBErrorFmt(SExprNotBoolean, [Field.FieldName]);
- Result := PutNode(nodeBINARY, canNE, 2);
- SetNodeOp(Result, 0, PutFieldNode(Field));
- SetNodeOp(Result, 1, PutConstNode(fldBOOL, @BoolFalse,
- SizeOf(WordBool)));
- end;
- enOperator:
- case Node^.FOperator of
- canEQ..canLE:
- Result := PutCompareNode(Node);
- canAND, canOR:
- begin
- Result := PutNode(nodeBINARY, Node^.FOperator, 2);
- SetNodeOp(Result, 0, PutExprNode(Node^.FLeft));
- SetNodeOp(Result, 1, PutExprNode(Node^.FRight));
- end;
- else
- Result := PutNode(nodeUNARY, canNOT, 1);
- SetNodeOp(Result, 0, PutExprNode(Node^.FLeft));
- end;
- else
- DBError(SExprIncorrect);
- end;
- end;
-
- function TFilterExpr.PutFieldNode(Field: TField): Integer;
- var
- Buffer: array[0..255] of Char;
- begin
- AnsiToNative(FDataSet.Locale, Field.FieldName, Buffer, SizeOf(Buffer) - 1);
- Result := PutNode(nodeFIELD, canFIELD2, 2);
- SetNodeOp(Result, 0, Field.FieldNo);
- SetNodeOp(Result, 1, PutData(Buffer, StrLen(Buffer) + 1));
- end;
-
- function TFilterExpr.PutNode(NodeType: NodeClass; OpType: CanOp;
- OpCount: Integer): Integer;
- var
- Size: Integer;
- begin
- Size := SizeOf(CANHdr) + OpCount * SizeOf(Word);
- with PCANHdr(GetExprData(SizeOf(CANExpr) + FExprNodeSize, Size))^ do
- begin
- nodeClass := NodeType;
- canOp := OpType;
- end;
- Result := FExprNodeSize;
- Inc(FExprNodeSize, Size);
- end;
-
- procedure TFilterExpr.SetNodeOp(Node, Index, Data: Integer);
- begin
- PWordArray(PChar(FExprBuffer) + (SizeOf(CANExpr) + Node +
- SizeOf(CANHdr)))^[Index] := Data;
- end;
-
- { TExprParser }
-
- type
-
- TExprToken = (etEnd, etSymbol, etName, etLiteral, etLParen, etRParen,
- etEQ, etNE, etGE, etLE, etGT, etLT);
-
- TExprParser = class
- private
- FFilter: TFilterExpr;
- FText: string;
- FSourcePtr: PChar;
- FTokenPtr: PChar;
- FTokenString: string;
- FToken: TExprToken;
- FFilterData: PCANExpr;
- procedure NextToken;
- function ParseExpr: PExprNode;
- function ParseExpr2: PExprNode;
- function ParseExpr3: PExprNode;
- function ParseExpr4: PExprNode;
- function ParseExpr5: PExprNode;
- function TokenName: string;
- function TokenSymbolIs(const S: string): Boolean;
- public
- constructor Create(DataSet: TDataSet; const Text: string;
- Options: TFilterOptions);
- destructor Destroy; override;
- property FilterData: PCANExpr read FFilterData;
- end;
-
- constructor TExprParser.Create(DataSet: TDataSet; const Text: string;
- Options: TFilterOptions);
- var
- Root: PExprNode;
- begin
- FFilter := TFilterExpr.Create(DataSet, Options);
- FText := Text;
- FSourcePtr := PChar(Text);
- NextToken;
- Root := ParseExpr;
- if FToken <> etEnd then DBError(SExprTermination);
- FFilterData := FFilter.GetFilterData(Root);
- end;
-
- destructor TExprParser.Destroy;
- begin
- FFilter.Free;
- end;
-
- procedure TExprParser.NextToken;
- var
- P, TokenStart: PChar;
- L: Integer;
- StrBuf: array[0..255] of Char;
- begin
- FTokenString := '';
- P := FSourcePtr;
- while (P^ <> #0) and (P^ <= ' ') do Inc(P);
- FTokenPtr := P;
- case P^ of
- 'A'..'Z', 'a'..'z', '_':
- begin
- TokenStart := P;
- Inc(P);
- while P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_'] do Inc(P);
- SetString(FTokenString, TokenStart, P - TokenStart);
- FToken := etSymbol;
- end;
- '[':
- begin
- Inc(P);
- TokenStart := P;
- while (P^ <> ']') and (P^ <> #0) do Inc(P);
- if P^ = #0 then DBError(SExprNameError);
- SetString(FTokenString, TokenStart, P - TokenStart);
- FToken := etName;
- Inc(P);
- end;
- '''':
- begin
- Inc(P);
- L := 0;
- while True do
- begin
- if P^ = #0 then DBError(SExprStringError);
- if P^ = '''' then
- begin
- Inc(P);
- if P^ <> '''' then Break;
- end;
- if L < SizeOf(StrBuf) then
- begin
- StrBuf[L] := P^;
- Inc(L);
- end;
- Inc(P);
- end;
- SetString(FTokenString, StrBuf, L);
- FToken := etLiteral;
- end;
- '-', '0'..'9':
- begin
- TokenStart := P;
- Inc(P);
- while P^ in ['0'..'9', '.', 'e', 'E', '+', '-'] do Inc(P);
- SetString(FTokenString, TokenStart, P - TokenStart);
- FToken := etLiteral;
- end;
- '(':
- begin
- Inc(P);
- FToken := etLParen;
- end;
- ')':
- begin
- Inc(P);
- FToken := etRParen;
- end;
- '<':
- begin
- Inc(P);
- case P^ of
- '=':
- begin
- Inc(P);
- FToken := etLE;
- end;
- '>':
- begin
- Inc(P);
- FToken := etNE;
- end;
- else
- FToken := etLT;
- end;
- end;
- '=':
- begin
- Inc(P);
- FToken := etEQ;
- end;
- '>':
- begin
- Inc(P);
- if P^ = '=' then
- begin
- Inc(P);
- FToken := etGE;
- end else
- FToken := etGT;
- end;
- #0:
- FToken := etEnd;
- else
- DBErrorFmt(SExprInvalidChar, [P^]);
- end;
- FSourcePtr := P;
- end;
-
- function TExprParser.ParseExpr: PExprNode;
- begin
- Result := ParseExpr2;
- while TokenSymbolIs('OR') do
- begin
- NextToken;
- Result := FFilter.NewNode(enOperator, canOR, Unassigned,
- Result, ParseExpr2);
- end;
- end;
-
- function TExprParser.ParseExpr2: PExprNode;
- begin
- Result := ParseExpr3;
- while TokenSymbolIs('AND') do
- begin
- NextToken;
- Result := FFilter.NewNode(enOperator, canAND, Unassigned,
- Result, ParseExpr3);
- end;
- end;
-
- function TExprParser.ParseExpr3: PExprNode;
- begin
- if TokenSymbolIs('NOT') then
- begin
- NextToken;
- Result := FFilter.NewNode(enOperator, canNOT, Unassigned,
- ParseExpr4, nil);
- end else
- Result := ParseExpr4;
- end;
-
- function TExprParser.ParseExpr4: PExprNode;
- const
- Operators: array[etEQ..etLT] of CanOp = (
- canEQ, canNE, canGE, canLE, canGT, canLT);
- var
- Operator: CanOp;
- begin
- Result := ParseExpr5;
- if FToken in [etEQ..etLT] then
- begin
- Operator := Operators[FToken];
- NextToken;
- Result := FFilter.NewNode(enOperator, Operator, Unassigned,
- Result, ParseExpr5);
- end;
- end;
-
- function TExprParser.ParseExpr5: PExprNode;
- begin
- case FToken of
- etSymbol:
- if TokenSymbolIs('NULL') then
- Result := FFilter.NewNode(enConst, canNOTDEFINED, System.Null, nil, nil) else
- Result := FFilter.NewNode(enField, canNOTDEFINED, FTokenString, nil, nil);
- etName:
- Result := FFilter.NewNode(enField, canNOTDEFINED, FTokenString, nil, nil);
- etLiteral:
- Result := FFilter.NewNode(enConst, canNOTDEFINED, FTokenString, nil, nil);
- etLParen:
- begin
- NextToken;
- Result := ParseExpr;
- if FToken <> etRParen then DBErrorFmt(SExprNoRParen, [TokenName]);
- end;
- else
- DBErrorFmt(SExprExpected, [TokenName]);
- end;
- NextToken;
- end;
-
- function TExprParser.TokenName: string;
- begin
- if FSourcePtr = FTokenPtr then Result := LoadStr(SExprNothing) else
- begin
- SetString(Result, FTokenPtr, FSourcePtr - FTokenPtr);
- Result := '''' + Result + '''';
- end;
- end;
-
- function TExprParser.TokenSymbolIs(const S: string): Boolean;
- begin
- Result := (FToken = etSymbol) and (CompareText(FTokenString, S) = 0);
- end;
-
- { TDataSet }
-
- constructor TDataSet.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FFieldDefs := TFieldDefs.Create(Self);
- FFields := TList.Create;
- FDataSources := TList.Create;
- FAutoCalcFields := True;
- ClearBuffers;
- SetLocale(DB.Session.Locale);
- end;
-
- destructor TDataSet.Destroy;
- begin
- Destroying;
- Close;
- SetUpdateObject(nil);
- FDesigner.Free;
- while FDataSources.Count > 0 do RemoveDataSource(FDataSources.Last);
- FDataSources.Free;
- DestroyFields;
- FFields.Free;
- FFieldDefs.Free;
- FAsyncCallback.Free;
- inherited Destroy;
- end;
-
- procedure TDataSet.SetName(const Value: TComponentName);
- var
- I: Integer;
- OldName, FieldName, NamePrefix: TComponentName;
- Field: TField;
- begin
- OldName := Name;
- inherited SetName(Value);
- if (csDesigning in ComponentState) and (Name <> OldName) then
- { In design mode the name of the fields should track the data set name }
- for I := 0 to FFields.Count - 1 do
- begin
- Field := FFields[I];
- if Field.Owner = Owner then
- begin
- FieldName := Field.Name;
- NamePrefix := FieldName;
- if Length(NamePrefix) > Length(OldName) then
- begin
- SetLength(NamePrefix, Length(OldName));
- if CompareText(OldName, NamePrefix) = 0 then
- begin
- System.Delete(FieldName, 1, Length(OldName));
- System.Insert(Value, FieldName, 1);
- try
- Field.Name := FieldName;
- except
- on EComponentError do {Ignore rename errors };
- end;
- end;
- end;
- end;
- end;
- end;
-
- procedure TDataSet.GetChildren(Proc: TGetChildProc);
- var
- I: Integer;
- Field: TField;
- begin
- for I := 0 to FFields.Count - 1 do
- begin
- Field := FFields[I];
- if Field.Owner <> Self then Proc(Field);
- end;
- end;
-
- procedure TDataSet.SetChildOrder(Component: TComponent; Order: Integer);
- begin
- if FFields.IndexOf(Component) >= 0 then
- (Component as TField).Index := Order;
- end;
-
- procedure TDataSet.Loaded;
- begin
- inherited Loaded;
- try
- if FStreamedActive then Active := True;
- except
- if csDesigning in ComponentState then
- Application.HandleException(Self)
- else
- raise;
- end;
- end;
-
- procedure TDataSet.SetState(Value: TDataSetState);
- begin
- if FState <> Value then
- begin
- FState := Value;
- FModified := False;
- DataEvent(deUpdateState, 0);
- end;
- end;
-
- procedure TDataSet.Open;
- begin
- Active := True;
- end;
-
- procedure TDataSet.Close;
- begin
- Active := False;
- end;
-
- procedure TDataSet.CheckInactive;
- begin
- if Active then
- if csUpdating in ComponentState then
- Close else
- DBError(SDataSetOpen);
- end;
-
- function TDataSet.GetActive: Boolean;
- begin
- Result := State <> dsInactive;
- end;
-
- procedure TDataSet.SetActive(Value: Boolean);
- begin
- if (csReading in ComponentState) then
- begin
- if Value then FStreamedActive := Value;
- end
- else
- if Active <> Value then
- begin
- if Value then
- begin
- DoBeforeOpen;
- try
- OpenCursor;
- SetState(dsBrowse);
- except
- SetState(dsInactive);
- CloseCursor;
- raise;
- end;
- DoAfterOpen;
- end else
- begin
- if not (csDestroying in ComponentState) then DoBeforeClose;
- SetState(dsInactive);
- CloseCursor;
- if not (csDestroying in ComponentState) then DoAfterClose;
- end;
- end;
- end;
-
- procedure TDataSet.SetLocale(Value: TLocale);
- begin
- FLocale := Value;
- end;
-
- procedure TDataSet.OpenCursor;
- var
- CursorLocale: TLocale;
- begin
- if FAsyncCallback = nil then
- FAsyncCallback := TBDECallback.Create(Self, nil, cbYIELDCLIENT,
- @FCBYieldStep, SizeOf(CBYieldStep), YieldCallBack, False);
- FHandle := CreateHandle;
- if FHandle = nil then DBError(SHandleError);
- if DbiGetLdObj(FHandle, CursorLocale) = 0 then SetLocale(CursorLocale);
- InternalOpen;
- end;
-
- procedure TDataSet.CloseCursor;
- begin
- InternalClose;
- SetLocale(DB.Session.Locale);
- if FHandle <> nil then
- begin
- DestroyHandle;
- FHandle := nil;
- end;
- end;
-
- function TDataSet.CreateHandle: HDBICur;
- begin
- Result := nil;
- end;
-
- procedure TDataSet.DestroyHandle;
- begin
- DbiRelRecordLock(FHandle, False);
- DbiCloseCursor(FHandle);
- end;
-
- procedure TDataSet.InternalOpen;
- var
- I: Integer;
- FieldDescs: PFieldDescList;
- RequiredFields: set of 0..255;
- CursorProps: CurProps;
- ValCheckDesc: VCHKDesc;
- begin
- if not InfoQueryMode and CachedUpdates then
- begin
- DbiGetCursorProps(FHandle, CursorProps);
- Check(DbiBeginDelayedUpdates(FHandle));
- end;
- DbiGetCursorProps(FHandle, CursorProps);
- FRecordSize := CursorProps.iRecBufSize;
- FBookmarkSize := CursorProps.iBookmarkSize;
- FCanModify := (CursorProps.eOpenMode = dbiReadWrite) and
- not CursorProps.bTempTable;
- FRecNoStatus := TRecNoStatus(CursorProps.ISeqNums);
- RequiredFields := [];
- for I := 1 to CursorProps.iValChecks do
- begin
- DbiGetVChkDesc(FHandle, I, @ValCheckDesc);
- if ValCheckDesc.bRequired and not ValCheckDesc.bHasDefVal then
- Include(RequiredFields, ValCheckDesc.iFldNum - 1);
- end;
- FieldDescs := AllocMem(CursorProps.iFields * SizeOf(FLDDesc));
- try
- DbiGetFieldDescs(FHandle, PFLDDesc(FieldDescs));
- FieldDefs.Clear;
- for I := 0 to CursorProps.iFields - 1 do
- FieldDefs.AddFieldDesc(FieldDescs^[I], I in RequiredFields, I + 1);
- finally
- FreeMem(FieldDescs, CursorProps.iFields * SizeOf(FLDDesc));
- end;
- if not InfoQueryMode then
- begin
- GetIndexInfo;
- FDefaultFields := FFields.Count = 0;
- if FDefaultFields then CreateFields;
- BindFields(True);
- FRecInfoOfs := FRecordSize + FCalcFieldsSize;
- FBookmarkOfs := FRecInfoOfs + SizeOf(TRecInfo);
- FRecBufSize := FBookmarkOfs + 1 + FBookmarkSize;
- if CachedUpdates then
- begin
- AllocDelUpdCBBuf(True);
- SetupCallBack(UpdateCallBackRequired);
- end;
- AllocKeyBuffers;
- DbiSetToBegin(FHandle);
- PrepareCursor;
- if FFilterText <> '' then
- FExprFilter := CreateExprFilter(FFilterText, FFilterOptions, 0);
- if Assigned(FOnFilterRecord) then
- FFuncFilter := CreateFuncFilter(@TDataSet.RecordFilter, 1);
- if FFiltered then ActivateFilters;
- UpdateBufferCount;
- FBOF := True;
- end;
- end;
-
- procedure TDataSet.InternalClose;
- begin
- if not InfoQueryMode then
- begin
- FreeFieldBuffers;
- SetBufListSize(0);
- FBufferCount := 0;
- ClearBuffers;
- FFuncFilter := nil;
- FExprFilter := nil;
- FreeKeyBuffers;
- if CachedUpdates then
- begin
- SetupCallBack(False);
- AllocDelUpdCBBuf(False);
- DbiEndDelayedUpdates(FHandle);
- end;
- BindFields(False);
- if FDefaultFields then DestroyFields;
- FDefaultFields := False;
- FIndexFieldCount := 0;
- FKeySize := 0;
- FExpIndex := False;
- FCaseInsIndex := False;
- end;
- FCanModify := False;
- end;
-
- procedure TDataSet.GetIndexInfo;
- var
- IndexDesc: IDXDesc;
- begin
- if DbiGetIndexDesc(FHandle, 0, IndexDesc) = 0 then
- begin
- FExpIndex := IndexDesc.bExpIdx;
- FCaseInsIndex := IndexDesc.bCaseInsensitive;
- if not ExpIndex then
- begin
- FIndexFieldCount := IndexDesc.iFldsInKey;
- FIndexFieldMap := IndexDesc.aiKeyFld;
- end;
- FKeySize := IndexDesc.iKeyLen;
- end;
- end;
-
- procedure TDataSet.PrepareCursor;
- begin
- end;
-
- procedure TDataSet.ActivateFilters;
- begin
- if FExprFilter <> nil then DbiActivateFilter(FHandle, FExprFilter);
- if FFuncFilter <> nil then DbiActivateFilter(FHandle, FFuncFilter);
- end;
-
- procedure TDataSet.DeactivateFilters;
- begin
- if FFuncFilter <> nil then DbiDeactivateFilter(FHandle, FFuncFilter);
- if FExprFilter <> nil then DbiDeactivateFilter(FHandle, FExprFilter);
- end;
-
- procedure TDataSet.CreateFields;
- var
- I: Integer;
- begin
- for I := 0 to FFieldDefs.Count - 1 do
- with FFieldDefs[I] do
- if DataType <> ftUnknown then CreateField(Self);
- end;
-
- procedure TDataSet.DestroyFields;
- var
- Field: TField;
- begin
- while FFields.Count > 0 do
- begin
- Field := FFields.Last;
- RemoveField(Field);
- Field.Free;
- end;
- end;
-
- procedure TDataSet.BindFields(Binding: Boolean);
- const
- CalcFieldTypes = [ftString, ftSmallint, ftInteger, ftWord, ftBoolean,
- ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime];
- BaseTypes: array[TFieldType] of TFieldType = (
- ftUnknown, ftString, ftSmallint, ftInteger, ftWord,
- ftBoolean, ftFloat, ftFloat, ftBCD, ftDate, ftTime, ftDateTime,
- ftBytes, ftVarBytes, ftInteger, ftBlob, ftBlob, ftBlob,
- ftBlob, ftBlob, ftBlob, ftBlob);
- var
- I: Integer;
- FieldDef: TFieldDef;
- begin
- FCalcFieldsSize := 0;
- FBDECalcFields := False;
- for I := 0 to FFields.Count - 1 do
- with TField(FFields[I]) do
- if Binding then
- begin
- if FieldKind <> fkData then
- begin
- if not (DataType in CalcFieldTypes) then
- DBErrorFmt(SInvalidCalcType, [DisplayName]);
- FFieldNo := -1;
- FOffset := FCalcFieldsSize;
- Inc(FCalcFieldsSize, DataSize + 1);
- end else
- begin
- FieldDef := FieldDefs.Find(FFieldName);
- if (BaseTypes[DataType] <> BaseTypes[FieldDef.DataType]) or
- (Size <> FieldDef.Size) then
- DBErrorFmt(SFieldTypeMismatch, [DisplayName]);
- FFieldNo := FieldDef.FieldNo;
- if FieldDef.BDECalcField and not FBDECalcFields then
- FBDECalcFields := True;
- end;
- Bind(True);
- end else
- begin
- Bind(False);
- FFieldNo := 0;
- end;
- end;
-
- procedure TDataSet.SwitchToIndex(const IndexName, TagName: string);
- var
- Status: DBIResult;
- CursorProps: CurProps;
- begin
- UpdateCursorPos;
- Status := DbiSwitchToIndex(FHandle, PChar(IndexName),
- PChar(TagName), 0, True);
- if Status = DBIERR_NOCURRREC then
- Status := DbiSwitchToIndex(FHandle, PChar(IndexName),
- PChar(TagName), 0, False);
- Check(Status);
- SetBufListSize(0);
- FIndexFieldCount := 0;
- FKeySize := 0;
- FExpIndex := False;
- FCaseInsIndex := False;
- DbiGetCursorProps(FHandle, CursorProps);
- FBookmarkSize := CursorProps.iBookmarkSize;
- FRecBufSize := FBookmarkOfs + FBookmarkSize + 1;
- try
- SetBufListSize(FBufferCount + 1);
- except
- SetState(dsInactive);
- CloseCursor;
- raise;
- end;
- GetIndexInfo;
- end;
-
- procedure TDataSet.FetchAll;
- begin
- if not EOF then
- begin
- CheckBrowseMode;
- Check(DbiSetToEnd(Handle));
- Check(DbiGetPriorRecord(FHandle, dbiNoLock, nil, nil));
- UpdateCursorPos;
- end;
- end;
-
- procedure TDataSet.FreeFieldBuffers;
- var
- I: Integer;
- begin
- for I := 0 to FFields.Count - 1 do TField(FFields[I]).FreeBuffers;
- end;
-
- procedure TDataSet.SetFieldDefs(Value: TFieldDefs);
- begin
- FFieldDefs.Assign(Value);
- end;
-
- procedure TDataSet.UpdateFieldDefs;
- begin
- if not FFieldDefs.FUpdated then
- begin
- InitFieldDefs;
- FFieldDefs.FUpdated := True;
- end;
- end;
-
- procedure TDataSet.InitFieldDefs;
- begin
- if not Active then
- try
- FInfoQueryMode := True;
- OpenCursor;
- finally
- CloseCursor;
- FInfoQueryMode := False;
- end;
- end;
-
- procedure TDataSet.AddField(Field: TField);
- begin
- FFields.Add(Field);
- Field.FDataSet := Self;
- DataEvent(deFieldListChange, 0)
- end;
-
- procedure TDataSet.RemoveField(Field: TField);
- begin
- Field.FDataSet := nil;
- FFields.Remove(Field);
- if not (csDestroying in ComponentState) then
- DataEvent(deFieldListChange, 0)
- end;
-
- function TDataSet.GetFieldCount: Integer;
- begin
- Result := FFields.Count;
- end;
-
- function TDataSet.GetField(Index: Integer): TField;
- begin
- Result := FFields[Index];
- end;
-
- procedure TDataSet.SetField(Index: Integer; Value: TField);
- begin
- TField(FFields[Index]).Assign(Value);
- end;
-
- function TDataSet.GetFieldValue(const FieldName: string): Variant;
- var
- I: Integer;
- Fields: TList;
- begin
- if Pos(';', FieldName) <> 0 then
- begin
- Fields := TList.Create;
- try
- GetFieldList(Fields, FieldName);
- Result := VarArrayCreate([0, Fields.Count - 1], varVariant);
- for I := 0 to Fields.Count - 1 do
- Result[I] := TField(Fields[I]).Value;
- finally
- Fields.Free;
- end;
- end else
- Result := FieldByName(FieldName).Value
- end;
-
- procedure TDataSet.SetFieldValue(const FieldName: string;
- const Value: Variant);
- var
- I: Integer;
- Fields: TList;
- begin
- if Pos(';', FieldName) <> 0 then
- begin
- Fields := TList.Create;
- try
- GetFieldList(Fields, FieldName);
- for I := 0 to Fields.Count - 1 do
- TField(Fields[I]).Value := Value[I];
- finally
- Fields.Free;
- end;
- end else
- FieldByName(FieldName).Value := Value;
- end;
-
- function TDataSet.FieldByName(const FieldName: string): TField;
- begin
- Result := FindField(FieldName);
- if Result = nil then DBErrorFmt(SFieldNotFound, [FieldName]);
- end;
-
- function TDataSet.FieldByNumber(FieldNo: Integer): TField;
- var
- I: Integer;
- begin
- for I := 0 to FFields.Count - 1 do
- begin
- Result := Fields[I];
- if Result.FieldNo = FieldNo then Exit;
- end;
- Result := nil;
- end;
-
- function TDataSet.FindField(const FieldName: string): TField;
- var
- I: Integer;
- begin
- for I := 0 to FFields.Count - 1 do
- begin
- Result := FFields[I];
- if AnsiCompareText(Result.FFieldName, FieldName) = 0 then Exit;
- end;
- Result := nil;
- end;
-
- procedure TDataSet.CheckFieldName(const FieldName: string);
- begin
- if FieldName = '' then DBError(SFieldNameMissing);
- if FindField(FieldName) <> nil then
- DBErrorFmt(SDuplicateFieldName, [FieldName]);
- end;
-
- procedure TDataSet.CheckFieldNames(const FieldNames: string);
- var
- Pos: Integer;
- begin
- Pos := 1;
- while Pos <= Length(FieldNames) do
- FieldByName(ExtractFieldName(FieldNames, Pos));
- end;
-
- function TDataSet.GetIndexField(Index: Integer): TField;
- var
- FieldNo: Integer;
- begin
- if (Index < 0) or (Index >= FIndexFieldCount) then
- DBError(SFieldIndexError);
- FieldNo := FIndexFieldMap[Index];
- Result := FieldByNumber(FieldNo);
- if Result = nil then
- DBErrorFmt(SIndexFieldMissing, [FFieldDefs[FieldNo - 1].Name]);
- end;
-
- procedure TDataSet.SetIndexField(Index: Integer; Value: TField);
- begin
- GetIndexField(Index).Assign(Value);
- end;
-
- function TDataSet.GetIndexFieldCount: Integer;
- begin
- Result := FIndexFieldCount;
- end;
-
- procedure TDataSet.GetFieldNames(List: TStrings);
- var
- I: Integer;
- begin
- List.BeginUpdate;
- try
- List.Clear;
- if FFields.Count > 0 then
- for I := 0 to FFields.Count - 1 do
- List.Add(TField(FFields[I]).FFieldName)
- else
- begin
- UpdateFieldDefs;
- for I := 0 to FFieldDefs.Count - 1 do
- List.Add(FFieldDefs[I].Name);
- end;
- finally
- List.EndUpdate;
- end;
- end;
-
- function TDataSet.GetDataSource: TDataSource;
- begin
- Result := nil;
- end;
-
- function TDataSet.IsLinkedTo(DataSource: TDataSource): Boolean;
- var
- DataSet: TDataSet;
- begin
- Result := True;
- while DataSource <> nil do
- begin
- DataSet := DataSource.DataSet;
- if DataSet = nil then Break;
- if DataSet = Self then Exit;
- DataSource := DataSet.DataSource;
- end;
- Result := False;
- end;
-
- procedure TDataSet.AddDataSource(DataSource: TDataSource);
- begin
- FDataSources.Add(DataSource);
- DataSource.FDataSet := Self;
- UpdateBufferCount;
- DataSource.UpdateState;
- end;
-
- procedure TDataSet.RemoveDataSource(DataSource: TDataSource);
- begin
- DataSource.FDataSet := nil;
- FDataSources.Remove(DataSource);
- DataSource.UpdateState;
- UpdateBufferCount;
- end;
-
- procedure TDataSet.SetBufListSize(Value: Integer);
- var
- I: Integer;
- NewList: PBufferList;
- begin
- if FBufListSize <> Value then
- begin
- GetMem(NewList, Value * SizeOf(Pointer));
- if FBufListSize > Value then
- begin
- if Value <> 0 then
- Move(FBuffers^, NewList^, Value * SizeOf(Pointer));
- for I := Value to FBufListSize - 1 do
- FreeMem(FBuffers^[I], FRecBufSize);
- end else
- begin
- if FBufListSize <> 0 then
- Move(FBuffers^, NewList^, FBufListSize * SizeOf(Pointer));
- I := FBufListSize;
- try
- while I < Value do
- begin
- GetMem(NewList^[I], FRecBufSize);
- Inc(I);
- end;
- except
- while I > FBufListSize do
- begin
- FreeMem(NewList^[I], FRecBufSize);
- Dec(I);
- end;
- FreeMem(NewList, Value * SizeOf(Pointer));
- raise;
- end;
- end;
- FreeMem(FBuffers, FBufListSize * SizeOf(Pointer));
- FBuffers := NewList;
- FBufListSize := Value;
- end;
- end;
-
- procedure TDataSet.SetBufferCount(Value: Integer);
- var
- I, Delta: Integer;
- DataLink: TDataLink;
-
- procedure AdjustFirstRecord(Delta: Integer);
- var
- DataLink: TDataLink;
- begin
- if Delta <> 0 then
- begin
- DataLink := FFirstDataLink;
- while DataLink <> nil do
- begin
- if DataLink.Active then Inc(DataLink.FFirstRecord, Delta);
- DataLink := DataLink.FNext;
- end;
- end;
- end;
-
- begin
- if FBufferCount <> Value then
- begin
- if (FBufferCount > Value) and (FRecordCount > 0) then
- begin
- Delta := FActiveRecord;
- DataLink := FFirstDataLink;
- while DataLink <> nil do
- begin
- if DataLink.Active and (DataLink.FFirstRecord < Delta) then
- Delta := DataLink.FFirstRecord;
- DataLink := DataLink.FNext;
- end;
- for I := 0 to Value - 1 do MoveBuffer(I + Delta, I);
- Dec(FActiveRecord, Delta);
- if FCurrentRecord <> -1 then Dec(FCurrentRecord, Delta);
- if FRecordCount > Value then FRecordCount := Value;
- AdjustFirstRecord(-Delta);
- end;
- SetBufListSize(Value + 1);
- FBufferCount := Value;
- GetNextRecords;
- AdjustFirstRecord(GetPriorRecords);
- end;
- end;
-
- procedure TDataSet.UpdateBufferCount;
- var
- I, J, MaxBufferCount: Integer;
- DataLink: TDataLink;
- begin
- if FHandle <> nil then
- begin
- MaxBufferCount := 1;
- FFirstDataLink := nil;
- for I := FDataSources.Count - 1 downto 0 do
- with TDataSource(FDataSources[I]) do
- for J := FDataLinks.Count - 1 downto 0 do
- begin
- DataLink := FDataLinks[J];
- DataLink.FNext := FFirstDataLink;
- FFirstDataLink := DataLink;
- if DataLink.FBufferCount > MaxBufferCount then
- MaxBufferCount := DataLink.FBufferCount;
- end;
- SetBufferCount(MaxBufferCount);
- end;
- end;
-
- procedure TDataSet.InitRecord(Buffer: PChar);
- begin
- DbiInitRecord(FHandle, Buffer);
- FillChar(Buffer[FRecordSize], FCalcFieldsSize, 0);
- with PRecInfo(Buffer + FRecInfoOfs)^ do
- begin
- UpdateStatus := TUpdateStatus(usInserted);
- RecordNumber := -1;
- end;
- end;
-
- procedure TDataSet.AllocKeyBuffers;
- var
- KeyIndex: TKeyIndex;
- begin
- try
- for KeyIndex := Low(TKeyIndex) to High(TKeyIndex) do
- FKeyBuffers[KeyIndex] := InitKeyBuffer(
- AllocMem(SizeOf(TKeyBuffer) + FRecordSize));
- except
- FreeKeyBuffers;
- raise;
- end;
- end;
-
- procedure TDataSet.FreeKeyBuffers;
- var
- KeyIndex: TKeyIndex;
- begin
- for KeyIndex := Low(TKeyIndex) to High(TKeyIndex) do
- DisposeMem(FKeyBuffers[KeyIndex], SizeOf(TKeyBuffer) + FRecordSize);
- end;
-
- function TDataSet.InitKeyBuffer(Buffer: PKeyBuffer): PKeyBuffer;
- begin
- FillChar(Buffer^, SizeOf(TKeyBuffer) + FRecordSize, 0);
- DbiInitRecord(FHandle, PChar(Buffer) + SizeOf(TKeyBuffer));
- Result := Buffer;
- end;
-
- procedure TDataSet.DataEvent(Event: TDataEvent; Info: Longint);
- var
- I: Integer;
- begin
- case Event of
- deFieldChange:
- begin
- if TField(Info).FieldKind = fkData then FModified := True;
- if State <> dsSetKey then
- begin
- if FBDECalcFields and (TField(Info).FieldKind = fkData) and
- not TField(Info).BDECalcField then
- CalculateBDEFields
- else if (FCalcFieldsSize <> 0) and FAutoCalcFields and
- (TField(Info).FieldKind = fkData) then
- begin
- FillChar(ActiveBuffer[FRecordSize], FCalcFieldsSize, 0);
- CalculateFields;
- end;
- TField(Info).Change;
- end;
- end;
- dePropertyChange:
- FFieldDefs.FUpdated := False;
- end;
- if FDisableCount = 0 then
- begin
- for I := 0 to FDataSources.Count - 1 do
- TDataSource(FDataSources[I]).DataEvent(Event, Info);
- if FDesigner <> nil then FDesigner.DataEvent(Event, Info);
- end else
- if (Event = deUpdateState) and (State = dsInactive) or
- (Event = deLayoutChange) then FEnableEvent := deLayoutChange;
- end;
-
- function TDataset.ControlsDisabled: Boolean;
- begin
- Result := FDisableCount <> 0;
- end;
-
- procedure TDataSet.DisableControls;
- begin
- if FDisableCount = 0 then
- begin
- FDisableState := FState;
- FEnableEvent := deDataSetChange;
- end;
- Inc(FDisableCount);
- end;
-
- procedure TDataSet.EnableControls;
- begin
- if FDisableCount <> 0 then
- begin
- Dec(FDisableCount);
- if FDisableCount = 0 then
- begin
- if FDisableState <> FState then DataEvent(deUpdateState, 0);
- if (FDisableState <> dsInactive) and (FState <> dsInactive) then
- DataEvent(FEnableEvent, 0);
- end;
- end;
- end;
-
- procedure TDataSet.UpdateRecord;
- begin
- if not (State in dsEditModes) then DBError(SNotEditing);
- DataEvent(deUpdateRecord, 0);
- end;
-
- procedure TDataSet.MoveBuffer(CurIndex, NewIndex: Integer);
- var
- Buffer: PChar;
- begin
- if CurIndex <> NewIndex then
- begin
- Buffer := FBuffers^[CurIndex];
- if CurIndex < NewIndex then
- Move(FBuffers^[CurIndex + 1], FBuffers^[CurIndex],
- (NewIndex - CurIndex) * SizeOf(Pointer))
- else
- Move(FBuffers^[NewIndex], FBuffers^[NewIndex + 1],
- (CurIndex - NewIndex) * SizeOf(Pointer));
- FBuffers^[NewIndex] := Buffer;
- end;
- end;
-
- procedure TDataSet.CopyBuffer(SourceIndex, DestIndex: Integer);
- begin
- Move(FBuffers^[SourceIndex]^, FBuffers^[DestIndex]^, FRecBufSize);
- end;
-
- function TDataSet.ActiveBuffer: PChar;
- begin
- Result := FBuffers^[FActiveRecord];
- end;
-
- procedure TDataSet.ClearBuffers;
- begin
- FRecordCount := 0;
- FActiveRecord := 0;
- FCurrentRecord := -1;
- FBOF := True;
- FEOF := True;
- end;
-
- procedure TDataSet.ActivateBuffers;
- begin
- FRecordCount := 1;
- FActiveRecord := 0;
- FCurrentRecord := 0;
- FBOF := False;
- FEOF := False;
- end;
-
- procedure TDataSet.GetCalcFields(Index: Integer);
- var
- SaveState: TDataSetState;
- begin
- if FCalcFieldsSize <> 0 then
- begin
- SaveState := FState;
- FState := dsCalcFields;
- try
- FCalcBuffer := FBuffers^[Index];
- FillChar(FCalcBuffer[FRecordSize], FCalcFieldsSize, 0);
- CalculateFields;
- finally
- FState := SaveState;
- end;
- end;
- end;
-
- procedure TDataSet.CalculateFields;
- var
- I: Integer;
- begin
- for I := 0 to FFields.Count - 1 do
- with TField(FFields[I]) do
- if FieldKind = fkLookup then CalcLookupValue;
- DoOnCalcFields;
- end;
-
- procedure TDataSet.CalculateBDEFields;
- var
- I: Integer;
- begin
- for I := 0 to FFields.Count - 1 do
- with TField(FFields[I]) do
- if BDECalcField then Value := Value;
- end;
-
- function TDataSet.GetCanModify: Boolean;
- begin
- Result := FCanModify or ForceUpdateCallback;
- end;
-
- function TDataSet.GetRecord(Index: Integer; GetMode: TGetMode): DBIResult;
- var
- Buffer: PChar;
- begin
- Buffer := FBuffers^[Index];
- case GetMode of
- gmCurrent:
- Result := DbiGetRecord(FHandle, dbiNoLock, Buffer, @FRecProps);
- gmNext:
- Result := DbiGetNextRecord(FHandle, dbiNoLock, Buffer, @FRecProps);
- gmPrior:
- Result := DbiGetPriorRecord(FHandle, dbiNoLock, Buffer, @FRecProps);
- else
- Result := 0;
- end;
- if Result = 0 then
- begin
- with PRecInfo(Buffer + FRecInfoOfs)^ do
- begin
- UpdateStatus := TUpdateStatus(FRecProps.iRecStatus);
- case FRecNoStatus of
- rnParadox: RecordNumber := FRecProps.iSeqNum;
- rnDBase: RecordNumber := FRecProps.iPhyRecNum;
- else
- RecordNumber := -1;
- end;
- end;
- GetCalcFields(Index);
- Buffer[FBookmarkOfs] := #0;
- Check(DbiGetBookmark(FHandle, Buffer + FBookmarkOfs + 1));
- end;
- end;
-
- procedure TDataSet.SetCurrentRecord(Index: Integer);
- var
- Buffer: PChar;
- begin
- if FCurrentRecord <> Index then
- begin
- Buffer := FBuffers^[Index];
- case Buffer[FBookmarkOfs] of
- #0,#255: Check(DbiSetToBookmark(FHandle, Buffer + FBookmarkOfs + 1));
- #1: Check(DbiSetToBegin(FHandle));
- #2: Check(DbiSetToEnd(FHandle));
- end;
- FCurrentRecord := Index;
- end;
- end;
-
- procedure TDataSet.UpdateCursorPos;
- begin
- if FRecordCount > 0 then SetCurrentRecord(FActiveRecord);
- end;
-
- procedure TDataSet.CursorPosChanged;
- begin
- FCurrentRecord := -1;
- end;
-
- function TDataSet.GetCurrentRecord(Buffer: PChar): Boolean;
- begin
- Result := False;
- if (FActiveRecord < FRecordCount) and
- (FBuffers^[FActiveRecord][FBookmarkOfs] = #0) then
- begin
- if FCurrentRecord <> FActiveRecord then
- begin
- if DbiSetToBookmark(FHandle, FBuffers^[FActiveRecord] +
- FBookmarkOfs + 1) <> 0 then Exit;
- FCurrentRecord := FActiveRecord;
- end;
- Result := DbiGetRecord(FHandle, dbiNoLock, Buffer, nil) = 0;
- end;
- end;
-
- function TDataSet.GetNextRecord: Boolean;
- var
- GetMode: TGetMode;
- Status: DBIResult;
- begin
- GetMode := gmNext;
- if FRecordCount > 0 then
- begin
- SetCurrentRecord(FRecordCount - 1);
- if (State = dsInsert) and (FCurrentRecord = FActiveRecord) and
- (ActiveBuffer[FBookmarkOfs] = #0) then GetMode := gmCurrent;
- end;
- Status := GetRecord(FRecordCount, GetMode);
- case Status of
- DBIERR_NONE:
- begin
- if FRecordCount = 0 then
- ActivateBuffers
- else
- if FRecordCount < FBufferCount then
- Inc(FRecordCount)
- else
- MoveBuffer(0, FRecordCount);
- FCurrentRecord := FRecordCount - 1;
- Result := True;
- end;
- DBIERR_EOF:
- begin
- FCurrentRecord := -1;
- Result := False;
- end;
- else
- DbiError(Status);
- end;
- end;
-
- function TDataSet.GetPriorRecord: Boolean;
- var
- Status: DBIResult;
- begin
- if FRecordCount > 0 then SetCurrentRecord(0);
- Status := GetRecord(FRecordCount, gmPrior);
- case Status of
- DBIERR_NONE:
- begin
- if FRecordCount = 0 then
- ActivateBuffers
- else
- begin
- MoveBuffer(FRecordCount, 0);
- if FRecordCount < FBufferCount then
- begin
- Inc(FRecordCount);
- Inc(FActiveRecord);
- end;
- end;
- FCurrentRecord := 0;
- Result := True;
- end;
- DBIERR_BOF:
- begin
- FCurrentRecord := -1;
- Result := False;
- end;
- else
- DbiError(Status);
- end;
- end;
-
- function TDataSet.GetNextRecords: Integer;
- begin
- Result := 0;
- try
- while (FRecordCount < FBufferCount) and GetNextRecord do Inc(Result);
- except
- end;
- end;
-
- function TDataSet.GetPriorRecords: Integer;
- begin
- Result := 0;
- try
- while (FRecordCount < FBufferCount) and GetPriorRecord do Inc(Result);
- except
- end;
- end;
-
- procedure TDataSet.Resync(Mode: TResyncMode);
- var
- Count: Integer;
- begin
- if rmExact in Mode then
- begin
- FCurrentRecord := -1;
- Check(GetRecord(FRecordCount, gmCurrent));
- end else
- if (GetRecord(FRecordCount, gmCurrent) <> 0) and
- (GetRecord(FRecordCount, gmNext) <> 0) and
- (GetRecord(FRecordCount, gmPrior) <> 0) then
- begin
- ClearBuffers;
- DataEvent(deDataSetChange, 0);
- Exit;
- end;
- if rmCenter in Mode then
- Count := (FBufferCount - 1) div 2 else
- Count := FActiveRecord;
- MoveBuffer(FRecordCount, 0);
- ActivateBuffers;
- try
- while (Count > 0) and GetPriorRecord do Dec(Count);
- GetNextRecords;
- GetPriorRecords;
- except
- end;
- DataEvent(deDataSetChange, 0);
- end;
-
- procedure TDataSet.CheckBrowseMode;
- begin
- if State = dsInactive then DBError(SDataSetClosed);
- DataEvent(deCheckBrowseMode, 0);
- case State of
- dsEdit, dsInsert:
- begin
- UpdateRecord;
- if Modified then Post else Cancel;
- end;
- dsSetKey:
- Post;
- end;
- end;
-
- procedure TDataSet.CheckSetKeyMode;
- begin
- if State <> dsSetKey then DBError(SNotEditing);
- end;
-
- procedure TDataSet.CheckCanModify;
- begin
- if not CanModify then DBError(SDataSetReadOnly);
- end;
-
- procedure TDataSet.CheckCachedUpdateMode;
- begin
- if not CachedUpdates then DBError(SNoCachedUpdates);
- end;
-
- procedure TDataSet.First;
- begin
- CheckBrowseMode;
- ClearBuffers;
- try
- Check(DbiSetToBegin(FHandle));
- GetNextRecord;
- GetNextRecords;
- finally
- FBOF := True;
- DataEvent(deDataSetChange, 0);
- end;
- end;
-
- procedure TDataSet.Last;
- begin
- CheckBrowseMode;
- ClearBuffers;
- try
- Check(DbiSetToEnd(FHandle));
- GetPriorRecord;
- GetPriorRecords;
- finally
- FEOF := True;
- DataEvent(deDataSetChange, 0);
- end;
- end;
-
- function TDataSet.MoveBy(Distance: Integer): Integer;
- var
- I, ScrollCount: Integer;
- begin
- CheckBrowseMode;
- Result := 0;
- if ((Distance > 0) and not FEOF) or ((Distance < 0) and not FBOF) then
- begin
- FBOF := False;
- FEOF := False;
- ScrollCount := 0;
- try
- while Distance > 0 do
- begin
- if FActiveRecord < FRecordCount - 1 then Inc(FActiveRecord) else
- begin
- if FRecordCount < FBufferCount then I := 0 else I := 1;
- if GetNextRecord then Dec(ScrollCount, I) else
- begin
- FEOF := True;
- Break;
- end;
- end;
- Dec(Distance);
- Inc(Result);
- end;
- while Distance < 0 do
- begin
- if FActiveRecord > 0 then Dec(FActiveRecord) else
- begin
- if FRecordCount < FBufferCount then I := 0 else I := 1;
- if GetPriorRecord then Inc(ScrollCount, I) else
- begin
- FBOF := True;
- Break;
- end;
- end;
- Inc(Distance);
- Dec(Result);
- end;
- finally
- DataEvent(deDataSetScroll, ScrollCount);
- end;
- end;
- end;
-
- procedure TDataSet.Next;
- begin
- MoveBy(1);
- end;
-
- procedure TDataSet.Prior;
- begin
- MoveBy(-1);
- end;
-
- procedure TDataSet.Refresh;
- begin
- CheckBrowseMode;
- UpdateCursorPos;
- Check(DbiForceReread(FHandle));
- Resync([]);
- end;
-
- procedure TDataSet.SetFields(const Values: array of const);
- var
- I: Integer;
- begin
- for I := 0 to High(Values) do Fields[I].AssignValue(Values[I]);
- end;
-
- procedure TDataSet.Insert;
- var
- Buffer: PChar;
- begin
- BeginInsertAppend;
- MoveBuffer(FRecordCount, FActiveRecord);
- Buffer := ActiveBuffer;
- InitRecord(Buffer);
- if FRecordCount = 0 then
- Buffer[FBookmarkOfs] := #1
- else
- begin
- Move(FBuffers^[FActiveRecord + 1][FBookmarkOfs], Buffer[FBookmarkOfs],
- FBookmarkSize + 1);
- Buffer[FBookmarkOfs] := #255;
- end;
- if FRecordCount < FBufferCount then Inc(FRecordCount);
- EndInsertAppend;
- end;
-
- procedure TDataSet.Append;
- var
- Buffer: PChar;
- begin
- BeginInsertAppend;
- ClearBuffers;
- Buffer := FBuffers^[0];
- InitRecord(Buffer);
- Buffer[FBookmarkOfs] := #2;
- FRecordCount := 1;
- FBOF := False;
- GetPriorRecords;
- EndInsertAppend;
- end;
-
- procedure TDataSet.BeginInsertAppend;
- begin
- CheckBrowseMode;
- CheckCanModify;
- DoBeforeInsert;
- end;
-
- procedure TDataSet.EndInsertAppend;
- begin
- SetState(dsInsert);
- try
- DoOnNewRecord;
- except
- UpdateCursorPos;
- FreeFieldBuffers;
- SetState(dsBrowse);
- Resync([]);
- raise;
- end;
- FModified := False;
- DataEvent(deDataSetChange, 0);
- DoAfterInsert;
- end;
-
- procedure TDataSet.AddRecord(const Values: array of const; Append: Boolean);
- var
- Buffer: PChar;
- begin
- BeginInsertAppend;
- if not Append then UpdateCursorPos;
- DisableControls;
- try
- MoveBuffer(FRecordCount, FActiveRecord);
- try
- Buffer := ActiveBuffer;
- InitRecord(Buffer);
- FState := dsInsert;
- try
- DoOnNewRecord;
- DoAfterInsert;
- SetFields(Values);
- DoBeforePost;
- if Append then
- Check(DbiAppendRecord(FHandle, Buffer)) else
- Check(DbiInsertRecord(FHandle, dbiNoLock, Buffer));
- finally
- FreeFieldBuffers;
- FState := dsBrowse;
- FModified := False;
- end;
- except
- MoveBuffer(FActiveRecord, FRecordCount);
- raise;
- end;
- Resync([]);
- DoAfterPost;
- finally
- EnableControls;
- end;
- end;
-
- procedure TDataSet.InsertRecord(const Values: array of const);
- begin
- AddRecord(Values, False);
- end;
-
- procedure TDataSet.AppendRecord(const Values: array of const);
- begin
- AddRecord(Values, True);
- end;
-
- procedure TDataSet.CheckOperation(Operation: TDataOperation;
- ErrorEvent: TDataSetErrorEvent);
- var
- Done: Boolean;
- Action: TDataAction;
- begin
- Done := False;
- repeat
- try
- UpdateCursorPos;
- Check(Operation);
- Done := True;
- except
- on E: EDatabaseError do
- begin
- Action := daFail;
- if Assigned(ErrorEvent) then ErrorEvent(Self, E, Action);
- if Action = daFail then raise;
- if Action = daAbort then SysUtils.Abort;
- end;
- end;
- until Done;
- end;
-
- function TDataSet.EditRecord: DBIResult;
- begin
- Result := DbiGetRecord(FHandle, dbiWriteLock, ActiveBuffer, nil);
- end;
-
- procedure TDataSet.Edit;
- begin
- if not (State in [dsEdit, dsInsert]) then
- if FRecordCount = 0 then Insert else
- begin
- CheckBrowseMode;
- CheckCanModify;
- DoBeforeEdit;
- CheckOperation(EditRecord, FOnEditError);
- GetCalcFields(FActiveRecord);
- SetState(dsEdit);
- DataEvent(deRecordChange, 0);
- DoAfterEdit;
- end;
- end;
-
- procedure TDataSet.ClearFields;
- begin
- if not (State in dsEditModes) then DBError(SNotEditing);
- DataEvent(deCheckBrowseMode, 0);
- DbiInitRecord(FHandle, ActiveBuffer);
- if State <> dsSetKey then GetCalcFields(FActiveRecord);
- DataEvent(deRecordChange, 0);
- end;
-
- procedure TDataSet.CheckRequiredFields;
- const
- CheckTypes = [ftString, ftSmallint, ftInteger, ftWord, ftBoolean, ftFloat,
- ftCurrency, ftBCD, ftDate, ftTime, ftDateTime, ftBytes, ftVarBytes];
- var
- I: Integer;
- begin
- for I := 0 to FFields.Count - 1 do
- with TField(FFields[I]) do
- if Required and not ReadOnly and (FieldKind = fkData) and
- (DataType in CheckTypes) and IsNull then
- begin
- FocusControl;
- DBErrorFmt(SFieldRequired, [DisplayName]);
- end;
- end;
-
- function TDataSet.PostRecord: DBIResult;
- begin
- if State = dsEdit then
- Result := DbiModifyRecord(FHandle, ActiveBuffer, True) else
- Result := DbiInsertRecord(FHandle, dbiNoLock, ActiveBuffer);
- end;
-
- procedure TDataSet.Post;
- begin
- UpdateRecord;
- case State of
- dsEdit, dsInsert:
- begin
- DataEvent(deCheckBrowseMode, 0);
- CheckRequiredFields;
- DoBeforePost;
- CheckOperation(PostRecord, FOnPostError);
- FreeFieldBuffers;
- SetState(dsBrowse);
- Resync([]);
- DoAfterPost;
- end;
- dsSetKey:
- PostKeyBuffer(True);
- end;
- end;
-
- procedure TDataSet.Cancel;
- begin
- case State of
- dsEdit, dsInsert:
- begin
- DataEvent(deCheckBrowseMode, 0);
- DoBeforeCancel;
- UpdateCursorPos;
- if State = dsEdit then DbiRelRecordLock(FHandle, False);
- FreeFieldBuffers;
- SetState(dsBrowse);
- Resync([]);
- DoAfterCancel;
- end;
- dsSetKey:
- PostKeyBuffer(False);
- end;
- end;
-
- function TDataSet.DeleteRecord: DBIResult;
- begin
- Result := DbiDeleteRecord(FHandle, nil);
- if Hi(Result) = ERRCAT_NOTFOUND then Result := 0;
- end;
-
- procedure TDataSet.Delete;
- begin
- if State = dsInactive then DBError(SDataSetClosed);
- if State in [dsInsert, dsSetKey] then Cancel else
- begin
- if FRecordCount = 0 then DBError(SDataSetEmpty);
- DataEvent(deCheckBrowseMode, 0);
- DoBeforeDelete;
- CheckOperation(DeleteRecord, FOnDeleteError);
- FreeFieldBuffers;
- SetState(dsBrowse);
- Resync([]);
- DoAfterDelete;
- end;
- end;
-
- function TDataSet.GetBookmark: TBookmark;
- begin
- Result := nil;
- if (State in [dsBrowse, dsEdit, dsInsert]) and (FRecordCount > 0)
- and (ActiveBuffer[FBookmarkOfs] = #0) then
- begin
- Result := StrAlloc(FBookmarkSize);
- Move(ActiveBuffer[FBookmarkOfs + 1], Result^, FBookmarkSize);
- end;
- end;
-
- function TDataset.GetBookmarkStr: TBookmarkStr;
- begin
- Result := '';
- if (State in [dsBrowse, dsEdit, dsInsert]) and (FRecordCount > 0)
- and (ActiveBuffer[FBookmarkOfs] = #0) then
- begin
- SetString(Result, PChar(@ActiveBuffer[FBookmarkOfs + 1]), FBookmarkSize);
- end;
- end;
-
- procedure TDataSet.GotoBookmark(Bookmark: TBookmark);
- begin
- if Bookmark <> nil then
- begin
- CheckBrowseMode;
- Check(DbiSetToBookmark(FHandle, Bookmark));
- Resync([rmExact, rmCenter]);
- end;
- end;
-
- procedure TDataset.SetBookmarkStr(const Value: TBookmarkStr);
- begin
- GotoBookmark(Pointer(Value));
- end;
-
- procedure TDataSet.FreeBookmark(Bookmark: TBookmark);
- begin
- StrDispose(Bookmark);
- end;
-
- function TDataSet.GetKeyBuffer(KeyIndex: TKeyIndex): PKeyBuffer;
- begin
- Result := FKeyBuffers[KeyIndex];
- end;
-
- procedure TDataSet.SetKeyBuffer(KeyIndex: TKeyIndex; Clear: Boolean);
- begin
- CheckBrowseMode;
- FKeyBuffer := FKeyBuffers[KeyIndex];
- Move(FKeyBuffer^, FKeyBuffers[kiSave]^, SizeOf(TKeyBuffer) + FRecordSize);
- if Clear then InitKeyBuffer(FKeyBuffer);
- SetState(dsSetKey);
- DataEvent(deDataSetChange, 0);
- end;
-
- procedure TDataSet.PostKeyBuffer(Commit: Boolean);
- begin
- DataEvent(deCheckBrowseMode, 0);
- if Commit then
- FKeyBuffer^.Modified := FModified
- else
- Move(FKeyBuffers[kiSave]^, FKeyBuffer^, SizeOf(TKeyBuffer) + FRecordSize);
- SetState(dsBrowse);
- DataEvent(deDataSetChange, 0);
- end;
-
- function TDataSet.GetKeyExclusive: Boolean;
- begin
- CheckSetKeyMode;
- Result := FKeyBuffer^.Exclusive;
- end;
-
- procedure TDataSet.SetKeyExclusive(Value: Boolean);
- begin
- CheckSetKeyMode;
- FKeyBuffer^.Exclusive := Value;
- end;
-
- function TDataSet.GetKeyFieldCount: Integer;
- begin
- CheckSetKeyMode;
- Result := FKeyBuffer^.FieldCount;
- end;
-
- procedure TDataSet.SetKeyFieldCount(Value: Integer);
- begin
- CheckSetKeyMode;
- FKeyBuffer^.FieldCount := Value;
- end;
-
- procedure TDataSet.SetKeyFields(KeyIndex: TKeyIndex;
- const Values: array of const);
- var
- I: Integer;
- begin
- if ExpIndex then DBError(SCompositeIndexError);
- if FIndexFieldCount = 0 then DBError(SNoFieldIndexes);
- Inc(FDisableCount);
- FState := dsSetKey;
- FModified := False;
- FKeyBuffer := InitKeyBuffer(FKeyBuffers[KeyIndex]);
- try
- for I := 0 to High(Values) do GetIndexField(I).AssignValue(Values[I]);
- FKeyBuffer^.FieldCount := High(Values) + 1;
- FKeyBuffer^.Modified := FModified;
- finally
- FState := dsBrowse;
- FModified := False;
- Dec(FDisableCount);
- end;
- end;
-
- procedure TDataSet.SetDetailFields(MasterFields: TList);
- var
- SaveState: TDataSetState;
- I: Integer;
- begin
- Inc(FDisableCount);
- SaveState := FState;
- FState := dsSetKey;
- try
- FKeyBuffer := InitKeyBuffer(FKeyBuffers[kiLookup]);
- FKeyBuffer^.Modified := True;
- for I := 0 to MasterFields.Count - 1 do
- GetIndexField(I).Assign(TField(MasterFields[I]));
- FKeyBuffer^.FieldCount := MasterFields.Count;
- finally
- FState := SaveState;
- FModified := False;
- Dec(FDisableCount);
- end;
- end;
-
- function TDataSet.SetCursorRange: Boolean;
- var
- RangeStart, RangeEnd: PKeyBuffer;
- StartKey, EndKey: PChar;
- IndexBuffer: PChar;
- UseStartKey, UseEndKey, UseKey: Boolean;
- begin
- Result := False;
- if not (
- BuffersEqual(FKeyBuffers[kiRangeStart], FKeyBuffers[kiCurRangeStart],
- SizeOf(TKeyBuffer) + FRecordSize) and
- BuffersEqual(FKeyBuffers[kiRangeEnd], FKeyBuffers[kiCurRangeEnd],
- SizeOf(TKeyBuffer) + FRecordSize)) then
- begin
- IndexBuffer := AllocMem(KeySize * 2);
- try
- UseStartKey := True;
- UseEndKey := True;
- RangeStart := FKeyBuffers[kiRangeStart];
- if RangeStart^.Modified then
- begin
- StartKey := PChar(RangeStart) + SizeOf(TKeyBuffer);
- UseStartKey := DbiExtractKey(Handle, StartKey, IndexBuffer) = 0;
- end
- else StartKey := nil;
- RangeEnd := FKeyBuffers[kiRangeEnd];
- if RangeEnd^.Modified then
- begin
- EndKey := PChar(RangeEnd) + SizeOf(TKeyBuffer);
- UseEndKey := DbiExtractKey(Handle, EndKey, IndexBuffer + KeySize) = 0;
- end
- else EndKey := nil;
- UseKey := UseStartKey and UseEndKey;
- if UseKey then
- begin
- if StartKey <> nil then StartKey := IndexBuffer;
- if EndKey <> nil then EndKey := IndexBuffer + KeySize;
- end;
- Check(DbiSetRange(FHandle, UseKey,
- RangeStart^.FieldCount, 0, StartKey, not RangeStart^.Exclusive,
- RangeEnd^.FieldCount, 0, EndKey, not RangeEnd^.Exclusive));
- Move(FKeyBuffers[kiRangeStart]^, FKeyBuffers[kiCurRangeStart]^,
- SizeOf(TKeyBuffer) + FRecordSize);
- Move(FKeyBuffers[kiRangeEnd]^, FKeyBuffers[kiCurRangeEnd]^,
- SizeOf(TKeyBuffer) + FRecordSize);
- DestroyLookupCursor;
- Result := True;
- finally
- FreeMem(IndexBuffer, KeySize * 2);
- end;
- end;
- end;
-
- function TDataSet.ResetCursorRange: Boolean;
- begin
- Result := False;
- if FKeyBuffers[kiCurRangeStart]^.Modified or
- FKeyBuffers[kiCurRangeEnd]^.Modified then
- begin
- Check(DbiResetRange(FHandle));
- InitKeyBuffer(FKeyBuffers[kiCurRangeStart]);
- InitKeyBuffer(FKeyBuffers[kiCurRangeEnd]);
- DestroyLookupCursor;
- Result := True;
- end;
- end;
-
- procedure TDataSet.SetLinkRanges(MasterFields: TList);
- var
- SaveState: TDataSetState;
- I: Integer;
- begin
- Inc(FDisableCount);
- SaveState := FState;
- FState := dsSetKey;
- try
- FKeyBuffer := InitKeyBuffer(FKeyBuffers[kiRangeStart]);
- FKeyBuffer^.Modified := True;
- for I := 0 to MasterFields.Count - 1 do
- GetIndexField(I).Assign(TField(MasterFields[I]));
- FKeyBuffer^.FieldCount := MasterFields.Count;
- finally
- FState := SaveState;
- FModified := False;
- Dec(FDisableCount);
- end;
- Move(FKeyBuffers[kiRangeStart]^, FKeyBuffers[kiRangeEnd]^,
- SizeOf(TKeyBuffer) + FRecordSize);
- end;
-
- function TDataSet.GetRecordCount: Longint;
- begin
- if State = dsInactive then DBError(SDataSetClosed);
- Check(DbiGetExactRecordCount(FHandle, Result));
- end;
-
- function TDataSet.GetRecordNumber: Longint;
- var
- BufPtr: PChar;
- begin
- case State of
- dsInactive: DBError(SDataSetClosed);
- dsCalcFields: BufPtr := FCalcBuffer
- else
- BufPtr := ActiveBuffer;
- end;
- Result := PRecInfo(BufPtr + FRecInfoOfs).RecordNumber;
- end;
-
- procedure TDataSet.AllocDelUpdCBBuf(Allocate: Boolean);
- begin
- if Allocate then
- begin
- FUpdateCBBuf := AllocMem(SizeOf(DELAYUPDCbDesc));
- FUpdateCBBuf.pNewRecBuf := StrAlloc(FRecBufSize);
- FUpdateCBBuf.pOldRecBuf := StrAlloc(FRecBufSize);
- FUpdateCBBuf.iRecBufSize := FRecordSize;
- end else
- begin
- if Assigned(FUpdateCBBuf) then
- begin
- StrDispose(FUpdateCBBuf.pNewRecBuf);
- StrDispose(FUpdateCBBuf.pOldRecBuf);
- DisposeMem(FUpdateCBBuf, SizeOf(DELAYUPDCbDesc));
- end;
- end;
- end;
-
- function TDataSet.UpdateCallbackRequired: Boolean;
- begin
- Result := FCachedUpdates and (Assigned(FOnUpdateError) or
- Assigned(FOnUpdateRecord) or Assigned(FUpdateObject));
- end;
-
- function TDataSet.ForceUpdateCallback: Boolean;
- begin
- Result := FCachedUpdates and (Assigned(FOnUpdateRecord) or
- Assigned(FUpdateObject));
- end;
-
- procedure TDataSet.SetCachedUpdates(Value: Boolean);
-
- procedure ReAllocBuffers;
- var
- CursorProps: CurProps;
- begin
- FreeFieldBuffers;
- FreeKeyBuffers;
- SetBufListSize(0);
- DbiGetCursorProps(FHandle, CursorProps);
- FRecordSize := CursorProps.iRecBufSize;
- FBookmarkSize := CursorProps.iBookmarkSize;
- FRecInfoOfs := FRecordSize + FCalcFieldsSize;
- FBookmarkOfs := FRecordSize + FCalcFieldsSize + SizeOf(TRecInfo);
- FRecBufSize := FBookmarkOfs + FBookmarkSize + 1;
- try
- SetBufListSize(FBufferCount + 1);
- AllocKeyBuffers;
- except
- SetState(dsInactive);
- CloseCursor;
- raise;
- end;
- end;
-
- begin
- if State = dsInActive then
- FCachedUpdates := Value
- else if FCachedUpdates <> Value then
- begin
- CheckBrowseMode;
- UpdateCursorPos;
- if FCachedUpdates then
- Check(DbiEndDelayedUpdates(FHandle))
- else
- Check(DbiBeginDelayedUpdates(FHandle));
- FCachedUpdates := Value;
- ReAllocBuffers;
- AllocDelUpdCBBuf(Value);
- SetupCallBack(UpdateCallBackRequired);
- Resync([]);
- end;
- end;
-
- procedure TDataSet.SetupCallBack(Value: Boolean);
- begin
- if Value then
- begin
- if (csDesigning in ComponentState) then Exit;
- if not Assigned(FUpdateCallback) then
- FUpdateCallback := TBDECallback.Create(Self, Self.Handle, cbDELAYEDUPD,
- FUpdateCBBuf, SizeOf(DELAYUPDCbDesc), CachedUpdateCallBack, True);
- end
- else
- begin
- if Assigned(FUpdateCallback) then
- begin
- FUpdateCallback.Free;
- FUpdateCallback := nil;
- end;
- end;
- end;
-
- function TDataSet.ProcessUpdates(UpdCmd: DBIDelayedUpdCmd): DBIResult;
- begin
- CheckCachedUpdateMode;
- UpdateCursorPos;
- Result := DbiApplyDelayedUpdates(Handle, UpdCmd);
- Resync([]);
- end;
-
- procedure TDataSet.ApplyUpdates;
- var
- Status: DBIResult;
- begin
- if State <> dsBrowse then Post;
- Status := ProcessUpdates(dbiDelayedUpdPrepare);
- if Status <> DBIERR_NONE then
- if Status = DBIERR_UPDATEABORT then SysUtils.Abort
- else DbiError(Status);
- end;
-
- procedure TDataSet.CommitUpdates;
- begin
- Check(ProcessUpdates(dbiDelayedUpdCommit));
- end;
-
- procedure TDataSet.CancelUpdates;
- begin
- Cancel;
- ProcessUpdates(dbiDelayedUpdCancel);
- end;
-
- procedure TDataSet.RevertRecord;
- var
- Status: DBIResult;
- begin
- if State in dsEditModes then Cancel;
- Status := ProcessUpdates(dbiDelayedUpdCancelCurrent);
- if not ((Status = DBIERR_NONE) or (Status = DBIERR_NOTSUPPORTED)) then
- Check(Status);
- end;
-
- function TDataSet.UpdateStatus: TUpdateStatus;
- var
- BufPtr: PChar;
- begin
- CheckCachedUpdateMode;
- if FState = dsCalcFields then
- BufPtr := FCalcBuffer
- else
- BufPtr := ActiveBuffer;
- Result := PRecInfo(BufPtr + FRecInfoOfs).UpdateStatus;
- end;
-
- function TDataSet.CachedUpdateCallBack(CBInfo: Pointer): CBRType;
- const
- CBRetCode: array[TUpdateAction] of CBRType = (cbrAbort, cbrAbort,
- cbrSkip, cbrRetry, cbrPartialAssist);
- var
- UpdateAction: TUpdateAction;
- UpdateKind: TUpdateKind;
- begin
- try
- Result := cbrUSEDEF;
- FInUpdateCallBack := True;
- UpdateAction := uaFail;
- UpdateKind := TUpdateKind(ord(FUpdateCBBuf.eDelayUpdOpType)-1);
- try
- if Assigned(FOnUpdateRecord) then
- FOnUpdateRecord(Self, UpdateKind, UpdateAction)
- else
- if Assigned(FUpdateObject) then
- begin
- FUpdateObject.Apply(UpdateKind);
- UpdateAction := uaApplied;
- end
- else
- DbiError(FUpdateCBBuf.iErrCode);
- except
- on E: EDatabaseError do
- begin
- if Assigned(FOnUpdateError) then
- FOnUpdateError(Self, E, UpdateKind, UpdateAction)
- else
- begin
- Application.HandleException(Self);
- UpdateAction := uaAbort;
- end;
- end;
- end;
- Result := CBRetCode[UpdateAction];
- if UpdateAction = uaAbort then FUpdateCBBuf.iErrCode := DBIERR_UPDATEABORT;
- except
- Application.HandleException(Self);
- end;
- FInUpdateCallBack := False;
- end;
-
- function TDataSet.GetUpdateRecordSet: TUpdateRecordTypes;
- begin
- if Active then
- begin
- CheckCachedUpdateMode;
- Result := TUpdateRecordTypes(Byte(GetIntProp(FHandle, curDELAYUPDDISPLAYOPT)));
- end
- else
- Result := [];
- end;
-
- procedure TDataSet.SetUpdateRecordSet(RecordTypes: TUpdateRecordTypes);
- begin
- CheckCachedUpdateMode;
- CheckBrowseMode;
- UpdateCursorPos;
- Check(DbiSetProp(hDbiObj(Handle), curDELAYUPDDISPLAYOPT, Longint(Byte(RecordTypes))));
- Resync([]);
- end;
-
- procedure TDataSet.SetUpdateObject(Value: TDataSetUpdateObject);
- begin
- if Value <> FUpdateObject then
- begin
- if Assigned(FUpdateObject) and (FUpdateObject.DataSet = Self) then
- FUpdateObject.DataSet := nil;
- FUpdateObject := Value;
- if Assigned(FUpdateObject) then
- begin
- { If another dataset already references this updateobject, then
- remove the reference }
- if Assigned(FUpdateObject.DataSet) and
- (FUpdateObject.DataSet <> Self) then
- FUpdateObject.DataSet.UpdateObject := nil;
- FUpdateObject.DataSet := Self;
- end;
- end;
- end;
-
- procedure TDataSet.SetOnUpdateError(UpdateEvent: TUpdateErrorEvent);
- begin
- if Active then SetupCallback(UpdateCallBackRequired);
- FOnUpdateError := UpdateEvent;
- end;
-
- function TDataSet.GetUpdatesPending: Boolean;
- begin
- Result := GetIntProp(FHandle, curDELAYUPDNUMUPDATES) > 0;
- end;
-
- function TDataSet.CreateExprFilter(const Expr: string;
- Options: TFilterOptions; Priority: Integer): HDBIFilter;
- var
- Parser: TExprParser;
- begin
- Parser := TExprParser.Create(Self, Expr, Options);
- try
- Check(DbiAddFilter(FHandle, 0, Priority, False, Parser.FilterData,
- nil, Result));
- finally
- Parser.Free;
- end;
- end;
-
- function TDataSet.CreateFuncFilter(FilterFunc: Pointer;
- Priority: Integer): HDBIFilter;
- begin
- Check(DbiAddFilter(FHandle, Integer(Self), Priority, False, nil,
- PFGENFilter(FilterFunc), Result));
- end;
-
- function TDataSet.CreateLookupFilter(Fields: TList; const Values: Variant;
- Options: TLocateOptions; Priority: Integer): HDBIFilter;
- var
- I: Integer;
- Filter: TFilterExpr;
- Expr, Node: PExprNode;
- FilterOptions: TFilterOptions;
- begin
- if loCaseInsensitive in Options then
- FilterOptions := [foNoPartialCompare, foCaseInsensitive] else
- FilterOptions := [foNoPartialCompare];
- Filter := TFilterExpr.Create(Self, FilterOptions);
- try
- if Fields.Count = 1 then
- begin
- Node := Filter.NewCompareNode(TField(Fields[0]), canEQ, Values);
- Expr := Node;
- end else
- for I := 0 to Fields.Count - 1 do
- begin
- Node := Filter.NewCompareNode(TField(Fields[I]), canEQ, Values[I]);
- if I = 0 then
- Expr := Node else
- Expr := Filter.NewNode(enOperator, canAND, Unassigned, Expr, Node);
- end;
- if loPartialKey in Options then Node^.FPartial := True;
- Check(DbiAddFilter(FHandle, 0, Priority, False,
- Filter.GetFilterData(Expr), nil, Result));
- finally
- Filter.Free;
- end;
- end;
-
- procedure TDataSet.SetFilterHandle(var Filter: HDBIFilter;
- Value: HDBIFilter);
- begin
- if FFiltered then
- begin
- CursorPosChanged;
- DestroyLookupCursor;
- DbiSetToBegin(FHandle);
- if Filter <> nil then DbiDropFilter(FHandle, Filter);
- Filter := Value;
- if Filter <> nil then DbiActivateFilter(FHandle, Filter);
- end else
- Filter := Value;
- end;
-
- procedure TDataSet.SetFilterData(const Text: string; Options: TFilterOptions);
- var
- Filter: HDBIFilter;
- begin
- if Active then
- begin
- CheckBrowseMode;
- if (FFilterText <> Text) or (FFilterOptions <> Options) then
- begin
- if Text <> '' then
- Filter := CreateExprFilter(Text, Options, 0) else
- Filter := nil;
- SetFilterHandle(FExprFilter, Filter);
- end;
- end;
- FFilterText := Text;
- FFilterOptions := Options;
- if Active and FFiltered then First;
- end;
-
- procedure TDataSet.SetFilterText(const Value: string);
- begin
- SetFilterData(Value, FFilterOptions);
- end;
-
- procedure TDataSet.SetFilterOptions(Value: TFilterOptions);
- begin
- SetFilterData(FFilterText, Value);
- end;
-
- procedure TDataSet.SetOnFilterRecord(const Value: TFilterRecordEvent);
- var
- Filter: HDBIFilter;
- begin
- if Active then
- begin
- CheckBrowseMode;
- if Assigned(FOnFilterRecord) <> Assigned(Value) then
- begin
- if Assigned(Value) then
- Filter := CreateFuncFilter(@TDataSet.RecordFilter, 1) else
- Filter := nil;
- SetFilterHandle(FFuncFilter, Filter);
- end;
- FOnFilterRecord := Value;
- if FFiltered then First;
- end else
- FOnFilterRecord := Value;
- end;
-
- procedure TDataSet.SetFiltered(Value: Boolean);
- begin
- if Active then
- begin
- CheckBrowseMode;
- if FFiltered <> Value then
- begin
- DestroyLookupCursor;
- DbiSetToBegin(FHandle);
- if Value then ActivateFilters else DeactivateFilters;
- FFiltered := Value;
- end;
- First;
- end else
- FFiltered := Value;
- end;
-
- function TDataSet.FindRecord(Restart, GoForward: Boolean): Boolean;
- var
- Status: DBIResult;
- begin
- CheckBrowseMode;
- FFound := False;
- UpdateCursorPos;
- CursorPosChanged;
- if not FFiltered then ActivateFilters;
- try
- if GoForward then
- begin
- if Restart then Check(DbiSetToBegin(FHandle));
- Status := DbiGetNextRecord(FHandle, dbiNoLock, nil, nil);
- end else
- begin
- if Restart then Check(DbiSetToEnd(FHandle));
- Status := DbiGetPriorRecord(FHandle, dbiNoLock, nil, nil);
- end;
- finally
- if not FFiltered then DeactivateFilters;
- end;
- if Status = DBIERR_NONE then
- begin
- Resync([rmExact, rmCenter]);
- FFound := True;
- end;
- Result := FFound;
- end;
-
- function TDataSet.FindFirst: Boolean;
- begin
- Result := FindRecord(True, True);
- end;
-
- function TDataSet.FindLast: Boolean;
- begin
- Result := FindRecord(True, False);
- end;
-
- function TDataSet.FindNext: Boolean;
- begin
- Result := FindRecord(False, True);
- end;
-
- function TDataSet.FindPrior: Boolean;
- begin
- Result := FindRecord(False, False);
- end;
-
- function TDataSet.RecordFilter(RecBuf: Pointer; RecNo: Integer): Smallint;
- var
- SaveState: TDataSetState;
- Accept: Boolean;
- begin
- SaveState := FState;
- FState := dsFilter;
- FFilterBuffer := RecBuf;
- try
- Accept := True;
- FOnFilterRecord(Self, Accept);
- except
- Application.HandleException(Self);
- end;
- FState := SaveState;
- Result := Ord(Accept);
- end;
-
- procedure TDataSet.GetFieldList(List: TList; const FieldNames: string);
- var
- Pos: Integer;
- begin
- Pos := 1;
- while Pos <= Length(FieldNames) do
- List.Add(FieldByName(ExtractFieldName(FieldNames, Pos)));
- end;
-
- function TDataSet.MapsToIndex(Fields: TList;
- CaseInsensitive: Boolean): Boolean;
- var
- I: Integer;
- begin
- Result := False;
- if CaseInsensitive and not FCaseInsIndex then Exit;
- if Fields.Count > FIndexFieldCount then Exit;
- for I := 0 to Fields.Count - 1 do
- if TField(Fields[I]).FieldNo <> FIndexFieldMap[I] then Exit;
- Result := True;
- end;
-
- function TDataSet.LocateRecord(const KeyFields: string;
- const KeyValues: Variant; Options: TLocateOptions;
- SyncCursor: Boolean): Boolean;
- var
- I, FieldCount, PartialLength: Integer;
- Buffer: PChar;
- Fields: TList;
- LookupCursor: HDBICur;
- Filter: HDBIFilter;
- Status: DBIResult;
- CaseInsensitive: Boolean;
- begin
- CheckBrowseMode;
- CursorPosChanged;
- Buffer := FBuffers^[FRecordCount];
- Fields := TList.Create;
- try
- GetFieldList(Fields, KeyFields);
- CaseInsensitive := loCaseInsensitive in Options;
- if CachedUpdates then
- LookupCursor := nil
- else
- if MapsToIndex(Fields, CaseInsensitive) then
- LookupCursor := FHandle else
- LookupCursor := GetLookupCursor(KeyFields, CaseInsensitive);
- if (LookupCursor <> nil) then
- begin
- FState := dsFilter;
- FFilterBuffer := Buffer;
- try
- DbiInitRecord(FHandle, Buffer);
- FieldCount := Fields.Count;
- if FieldCount = 1 then
- TField(Fields.First).Value := KeyValues
- else
- for I := 0 to FieldCount - 1 do
- TField(Fields[I]).Value := KeyValues[I];
- PartialLength := 0;
- if (loPartialKey in Options) and
- (TField(Fields.Last).DataType = ftString) then
- begin
- Dec(FieldCount);
- PartialLength := Length(TField(Fields.Last).AsString);
- end;
- Status := DbiGetRecordForKey(LookupCursor, False, FieldCount,
- PartialLength, Buffer, Buffer);
- finally
- FState := dsBrowse;
- end;
- if (Status = DBIERR_NONE) and SyncCursor and
- (LookupCursor <> FHandle) then
- Check(DbiSetToCursor(FHandle, LookupCursor));
- end else
- begin
- Check(DbiSetToBegin(FHandle));
- Filter := CreateLookupFilter(Fields, KeyValues, Options, 2);
- DbiActivateFilter(FHandle, Filter);
- Status := DbiGetNextRecord(FHandle, dbiNoLock, Buffer, nil);
- DbiDropFilter(FHandle, Filter);
- end;
- finally
- Fields.Free;
- end;
- Result := Status = DBIERR_NONE;
- end;
-
- function TDataSet.Lookup(const KeyFields: string; const KeyValues: Variant;
- const ResultFields: string): Variant;
- begin
- Result := Null;
- if LocateRecord(KeyFields, KeyValues, [], False) then
- begin
- FState := dsCalcFields;
- try
- FCalcBuffer := FBuffers^[FRecordCount];
- FillChar(FCalcBuffer[FRecordSize], FCalcFieldsSize, 0);
- CalculateFields;
- Result := FieldValues[ResultFields];
- finally
- FState := dsBrowse;
- end;
- end;
- end;
-
- function TDataSet.Locate(const KeyFields: string;
- const KeyValues: Variant; Options: TLocateOptions): Boolean;
- begin
- Result := LocateRecord(KeyFields, KeyValues, Options, True);
- if Result then Resync([rmExact, rmCenter]);
- end;
-
- function TDataSet.GetLookupCursor(const KeyFields: string;
- CaseInsensitive: Boolean): HDBICur;
- begin
- Result := nil;
- end;
-
- procedure TDataSet.DestroyLookupCursor;
- begin
- end;
-
- procedure TDataSet.DoAfterCancel;
- begin
- if Assigned(FAfterCancel) then FAfterCancel(Self);
- end;
-
- procedure TDataSet.DoAfterClose;
- begin
- if Assigned(FAfterClose) then FAfterClose(Self);
- end;
-
- procedure TDataSet.DoAfterDelete;
- begin
- if Assigned(FAfterDelete) then FAfterDelete(Self);
- end;
-
- procedure TDataSet.DoAfterEdit;
- begin
- if Assigned(FAfterEdit) then FAfterEdit(Self);
- end;
-
- procedure TDataSet.DoAfterInsert;
- begin
- if Assigned(FAfterInsert) then FAfterInsert(Self);
- end;
-
- procedure TDataSet.DoAfterOpen;
- begin
- if Assigned(FAfterOpen) then FAfterOpen(Self);
- end;
-
- procedure TDataSet.DoAfterPost;
- begin
- if Assigned(FAfterPost) then FAfterPost(Self);
- end;
-
- procedure TDataSet.DoBeforeCancel;
- begin
- if Assigned(FBeforeCancel) then FBeforeCancel(Self);
- end;
-
- procedure TDataSet.DoBeforeClose;
- begin
- if Assigned(FBeforeClose) then FBeforeClose(Self);
- end;
-
- procedure TDataSet.DoBeforeDelete;
- begin
- if Assigned(FBeforeDelete) then FBeforeDelete(Self);
- end;
-
- procedure TDataSet.DoBeforeEdit;
- begin
- if Assigned(FBeforeEdit) then FBeforeEdit(Self);
- end;
-
- procedure TDataSet.DoBeforeInsert;
- begin
- if Assigned(FBeforeInsert) then FBeforeInsert(Self);
- end;
-
- procedure TDataSet.DoBeforeOpen;
- begin
- if Assigned(FBeforeOpen) then FBeforeOpen(Self);
- end;
-
- procedure TDataSet.DoBeforePost;
- begin
- if Assigned(FBeforePost) then FBeforePost(Self);
- end;
-
- procedure TDataSet.DoOnCalcFields;
- begin
- if Assigned(FOnCalcFields) then FOnCalcFields(Self);
- end;
-
- procedure TDataSet.DoOnNewRecord;
- begin
- if Assigned(FOnNewRecord) then FOnNewRecord(Self);
- end;
-
- function TDataSet.YieldCallBack(CBInfo: Pointer): CBRType;
- var
- AbortQuery: Boolean;
- begin
- AbortQuery := False;
- if Assigned(OnServerYield) and (FCBYieldStep <> cbYieldLast) then
- OnServerYield(Self, AbortQuery);
- if AbortQuery then
- Result := cbrABORT else
- Result := cbrUSEDEF;
- end;
-
- { TDBDataSet }
-
- procedure TDBDataSet.OpenCursor;
- begin
- SetDBFlag(dbfOpened, True);
- inherited OpenCursor;
- SetUpdateMode(FUpdateMode);
- end;
-
- procedure TDBDataSet.CloseCursor;
- begin
- inherited CloseCursor;
- SetDBFlag(dbfOpened, False);
- end;
-
- procedure TDBDataSet.CheckDBSessionName;
- var
- S: TSession;
- Database: TDatabase;
- begin
- if (SessionName <> '') and (DatabaseName <> '') then
- begin
- S := Sessions.FindSession(SessionName);
- if Assigned(S) and not Assigned(S.FindDatabase(DatabaseName)) then
- begin
- Database := DB.Session.FindDatabase(DatabaseName);
- if Assigned(Database) then Database.CheckSessionName(True);
- end;
- end;
- end;
-
- function TDBDataSet.CheckOpen(Status: DBIResult): Boolean;
- begin
- case Status of
- DBIERR_NONE:
- Result := True;
- DBIERR_NOTSUFFTABLERIGHTS:
- begin
- if not FDatabase.Session.GetPassword then DbiError(Status);
- Result := False;
- end;
- else
- DbiError(Status);
- end;
- end;
-
- procedure TDBDataSet.Disconnect;
- begin
- Close;
- end;
-
- function TDBDataSet.GetDBFlag(Flag: Integer): Boolean;
- begin
- Result := Flag in FDBFlags;
- end;
-
- procedure TDBDataSet.SetDBFlag(Flag: Integer; Value: Boolean);
- begin
- if Value then
- begin
- if not (Flag in FDBFlags) then
- begin
- if FDBFlags = [] then
- begin
- CheckDBSessionName;
- FDatabase := Sessions.List[SessionName].OpenDatabase(FDatabaseName);
- FDatabase.FDataSets.Add(Self);
- SetLocale(FDatabase.Locale);
- end;
- Include(FDBFlags, Flag);
- end;
- end else
- begin
- if Flag in FDBFlags then
- begin
- Exclude(FDBFlags, Flag);
- if FDBFlags = [] then
- begin
- SetLocale(DBLocale);
- FDatabase.FDataSets.Remove(Self);
- FDatabase.Session.CloseDatabase(FDatabase);
- FDatabase := nil;
- end;
- end;
- end;
- end;
-
- function TDBDataSet.GetDBHandle: HDBIDB;
- begin
- if FDatabase <> nil then
- Result := FDatabase.Handle else
- Result := nil;
- end;
-
- function TDBDataSet.GetDBLocale: TLocale;
- begin
- if Database <> nil then
- Result := Database.Locale else
- Result := nil;
- end;
-
- function TDBDataSet.GetDBSession: TSession;
- begin
- if (FDatabase <> nil) then
- Result := FDatabase.Session else
- Result := Sessions.FindSession(SessionName);
- if Result = nil then Result := DB.Session;
- end;
-
- procedure TDBDataSet.SetDatabaseName(const Value: string);
- begin
- if FDatabaseName <> Value then
- begin
- CheckInactive;
- if FDatabase <> nil then DBError(SDatabaseOpen);
- FDatabaseName := Value;
- DataEvent(dePropertyChange, 0);
- end;
- end;
-
- procedure TDBDataSet.SetSessionName(const Value: string);
- begin
- CheckInactive;
- FSessionName := Value;
- DataEvent(dePropertyChange, 0);
- end;
-
- procedure TDBDataSet.SetUpdateMode(const Value: TUpdateMode);
- begin
- if (FHandle <> nil) and Database.IsSQLBased and CanModify then
- Check(DbiSetProp(hDbiObj(FHandle), curUPDLOCKMODE, Longint(Value)));
- FUpdateMode := Value;
- end;
-
- { TField }
-
- constructor TField.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FVisible := True;
- end;
-
- destructor TField.Destroy;
- begin
- if FDataSet <> nil then
- begin
- FDataSet.Close;
- FDataSet.RemoveField(Self);
- end;
- inherited Destroy;
- end;
-
- procedure TField.AccessError(const TypeName: string);
- begin
- DBErrorFmt(SFieldAccessError, [DisplayName, TypeName]);
- end;
-
- procedure TField.Assign(Source: TPersistent);
- begin
- if Source = nil then
- begin
- Clear;
- Exit;
- end;
- if Source is TField then
- begin
- Value := TField(Source).Value;
- Exit;
- end;
- inherited Assign(Source);
- end;
-
- procedure TField.AssignValue(const Value: TVarRec);
-
- procedure Error;
- begin
- DBErrorFmt(SFieldValueError, [DisplayName]);
- end;
-
- begin
- with Value do
- case VType of
- vtInteger:
- AsInteger := VInteger;
- vtBoolean:
- AsBoolean := VBoolean;
- vtChar:
- AsString := VChar;
- vtExtended:
- AsFloat := VExtended^;
- vtString:
- AsString := VString^;
- vtPointer:
- if VPointer <> nil then Error;
- vtPChar:
- AsString := VPChar;
- vtObject:
- if (VObject = nil) or (VObject is TPersistent) then
- Assign(TPersistent(VObject))
- else
- Error;
- vtAnsiString:
- AsString := string(VAnsiString);
- vtCurrency:
- AsCurrency := VCurrency^;
- vtVariant:
- if not VarIsEmpty(VVariant^) then AsVariant := VVariant^;
- else
- Error;
- end;
- end;
-
- procedure TField.Bind(Binding: Boolean);
- begin
- if FFieldKind = fkLookup then
- if Binding then
- begin
- if (FLookupDataSet = nil) or (FKeyFields = '') or
- (FLookupKeyFields = '') or (FLookupResultField = '') then
- DBErrorFmt(SLookupInfoError, [DisplayName]);
- FDataSet.CheckFieldNames(FKeyFields);
- FLookupDataSet.Open;
- FLookupDataSet.CheckFieldNames(FLookupKeyFields);
- FLookupDataSet.FieldByName(FLookupResultField);
- end;
- end;
-
- procedure TField.CalcLookupValue;
- begin
- if (FLookupDataSet <> nil) and FLookupDataSet.Active then
- Value := FLookupDataSet.Lookup(FLookupKeyFields,
- FDataSet.FieldValues[FKeyFields], FLookupResultField);
- end;
-
- procedure TField.Change;
- begin
- if Assigned(FOnChange) then FOnChange(Self);
- end;
-
- procedure TField.CheckInactive;
- begin
- if FDataSet <> nil then FDataSet.CheckInactive;
- end;
-
- procedure TField.Clear;
- begin
- SetData(nil);
- end;
-
- procedure TField.DataChanged;
- begin
- FDataSet.DataEvent(deFieldChange, Longint(Self));
- end;
-
- procedure TField.DefineProperties(Filer: TFiler);
-
- function DoWrite: Boolean;
- begin
- if Assigned(Filer.Ancestor) then
- Result := CompareText(FAttributeSet, TField(Filer.Ancestor).FAttributeSet) <> 0
- else
- Result := FAttributeSet <> '';
- end;
-
- begin
- Filer.DefineProperty('AttributeSet', ReadAttributeSet, WriteAttributeSet,
- DoWrite);
- end;
-
- procedure TField.FocusControl;
- var
- Field: TField;
- begin
- if (FDataSet <> nil) and FDataSet.Active then
- begin
- Field := Self;
- FDataSet.DataEvent(deFocusControl, Longint(@Field));
- end;
- end;
-
- procedure TField.FreeBuffers;
- begin
- end;
-
- function TField.GetAsBoolean: Boolean;
- begin
- AccessError('Boolean');
- end;
-
- function TField.GetAsCurrency: Currency;
- begin
- Result := GetAsFloat;
- end;
-
- function TField.GetAsDateTime: TDateTime;
- begin
- AccessError('DateTime');
- end;
-
- function TField.GetAsFloat: Double;
- begin
- AccessError('Float');
- end;
-
- function TField.GetAsInteger: Longint;
- begin
- AccessError('Integer');
- end;
-
- function TField.GetAsString: string;
- var
- I, L: Integer;
- S: string[63];
- begin
- S := ClassName;
- I := 1;
- L := Length(S);
- if S[1] = 'T' then I := 2;
- if (L >= 5) and (CompareText(Copy(S, L - 4, 5), 'FIELD') = 0) then Dec(L, 5);
- FmtStr(Result, '(%s)', [Copy(S, I, L + 1 - I)]);
- end;
-
- function TField.GetAsVariant: Variant;
- begin
- AccessError('Variant');
- end;
-
- function TField.GetCalculated: Boolean;
- begin
- Result := FFieldKind = fkCalculated;
- end;
-
- function TField.GetBDECalcField: Boolean;
- begin
- if FieldNo >= 0 then
- Result := DataSet.FieldDefs.Find(FieldName).BDECalcField
- else Result := False;
- end;
-
- function TField.GetCanModify: Boolean;
- begin
- if FieldNo > 0 then
- if DataSet.State <> dsSetKey then
- Result := not ReadOnly and DataSet.CanModify
- else
- Result := (DataSet.FIndexFieldCount = 0) or IsIndexField
- else
- Result := False;
- end;
-
- function TField.GetData(Buffer: Pointer): Boolean;
- var
- IsBlank: LongBool;
- RecBuf: PChar;
- begin
- if FDataSet = nil then DBErrorFmt(SDataSetMissing, [DisplayName]);
- Result := False;
- with FDataSet do
- begin
- case State of
- dsSetKey: RecBuf := PChar(FKeyBuffer) + SizeOf(TKeyBuffer);
- dsCalcFields: RecBuf := FCalcBuffer;
- dsUpdateNew: RecBuf := FUpdateCBBuf.pNewRecBuf;
- dsUpdateOld: RecBuf := FUpdateCBBuf.pOldRecBuf;
- dsFilter: RecBuf := FFilterBuffer;
- else
- if FActiveRecord >= FRecordCount then Exit;
- RecBuf := FBuffers^[FActiveRecord];
- end;
- if FieldNo > 0 then
- if FValidating then
- begin
- Result := LongBool(FValueBuffer);
- if Result and (Buffer <> nil) then
- Move(FValueBuffer^, Buffer^, DataSize);
- end else
- begin
- Check(DbiGetField(FHandle, FieldNo, RecBuf, Buffer, IsBlank));
- Result := not IsBlank;
- end
- else
- if (FieldNo < 0) and (State <> dsSetKey) then
- begin
- Inc(RecBuf, FRecordSize + FOffset);
- Result := Boolean(RecBuf[0]);
- if Result and (Buffer <> nil) then
- Move(RecBuf[1], Buffer^, DataSize);
- end;
- end;
- end;
-
- function TField.GetDefaultWidth: Integer;
- begin
- Result := 10;
- end;
-
- function TField.GetDisplayLabel: string;
- begin
- Result := GetDisplayName;
- end;
-
- function TField.GetDisplayName: string;
- begin
- if FDisplayLabel <> '' then
- Result := FDisplayLabel else
- Result := FFieldName;
- end;
-
- function TField.GetDisplayText: string;
- begin
- Result := '';
- if Assigned(FOnGetText) then
- FOnGetText(Self, Result, True) else
- GetText(Result, True);
- end;
-
- function TField.GetDisplayWidth: Integer;
- begin
- if FDisplayWidth > 0 then
- Result := FDisplayWidth else
- Result := GetDefaultWidth;
- end;
-
- function TField.GetEditText: string;
- begin
- Result := '';
- if Assigned(FOnGetText) then
- FOnGetText(Self, Result, False) else
- GetText(Result, False);
- end;
-
- function TField.GetIndex: Integer;
- begin
- if FDataSet <> nil then
- Result := FDataSet.FFields.IndexOf(Self) else
- Result := -1;
- end;
-
- function TField.GetIsIndexField: Boolean;
- var
- I: Integer;
- begin
- Result := False;
- if FFieldNo > 0 then
- for I := 0 to FDataSet.FIndexFieldCount - 1 do
- if FDataSet.FIndexFieldMap[I] = FFieldNo then
- begin
- Result := True;
- Exit;
- end;
- end;
-
- function TField.GetIsNull: Boolean;
- begin
- Result := not GetData(nil);
- end;
-
- function TField.GetLookup: Boolean;
- begin
- Result := FFieldKind = fkLookup;
- end;
-
- procedure TField.GetText(var Text: string; DisplayText: Boolean);
- begin
- Text := GetAsString;
- end;
-
- function TField.HasParent: Boolean;
- begin
- HasParent := True;
- end;
-
- function TField.GetNewValue: Variant;
- begin
- FDataSet.CheckCachedUpdateMode;
- if FDataSet.FInUpdateCallBack then
- Result := GetUpdateValue(dsUpdateNew)
- else
- Result := Value;
- end;
-
- function TField.GetOldValue: Variant;
- begin
- with FDataSet do
- begin
- CheckCachedUpdateMode;
- if FInUpdateCallBack and not (Self is TBlobField) then
- Result := GetUpdateValue(dsUpdateOld)
- else
- begin
- UpdateCursorPos;
- Check(DbiSetProp(hDbiObj(Handle), curDELAYUPDGETOLDRECORD, Longint(True)));
- try
- Check(DbiGetRecord(FHandle, dbiNoLock, FUpdateCBBuf.pOldRecBuf, nil));
- Result := GetUpdateValue(dsUpdateOld);
- finally
- DbiSetProp(hDbiObj(Handle), curDELAYUPDGETOLDRECORD, Longint(False));
- end;
- end;
- end;
- end;
-
- function TField.GetUpdateValue(ValueState: TDataSetState): Variant;
- var
- SaveState: TDataSetState;
- begin
- if FieldKind <> fkData then
- DBErrorFmt(SOldNewNonData, [FieldName]);
- SaveState := FDataset.FState;
- FDataSet.FState := ValueState;
- try
- Result := GetAsVariant;
- finally
- FDataSet.FState := SaveState;
- end;
- end;
-
- function TField.GetParentComponent: TComponent;
- begin
- Result := DataSet;
- end;
-
- procedure TField.SetParentComponent(AParent: TComponent);
- begin
- if not (csLoading in ComponentState) then DataSet := AParent as TDataSet;
- end;
-
- function TField.IsValidChar(InputChar: Char): Boolean;
- begin
- Result := True;
- end;
-
- function TField.IsDisplayLabelStored: Boolean;
- begin
- Result := FDisplayLabel <> '';
- end;
-
- function TField.IsDisplayWidthStored: Boolean;
- begin
- Result := FDisplayWidth > 0;
- end;
-
- procedure TField.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- inherited Notification(AComponent, Operation);
- if (Operation = opRemove) and (AComponent = FLookupDataSet) then
- FLookupDataSet := nil;
- end;
-
- procedure TField.PropertyChanged(LayoutAffected: Boolean);
- const
- Events: array[Boolean] of TDataEvent = (deDataSetChange, deLayoutChange);
- begin
- if (FDataSet <> nil) and FDataSet.Active then
- FDataSet.DataEvent(Events[LayoutAffected], 0);
- end;
-
- procedure TField.ReadAttributeSet(Reader: TReader);
- begin
- FAttributeSet := Reader.ReadString;
- end;
-
- procedure TField.ReadState(Reader: TReader);
- begin
- inherited ReadState(Reader);
- if Reader.Parent is TDataSet then DataSet := TDataSet(Reader.Parent);
- end;
-
- procedure TField.SetAsBoolean(Value: Boolean);
- begin
- AccessError('Boolean');
- end;
-
- procedure TField.SetAsCurrency(Value: Currency);
- begin
- SetAsFloat(Value);
- end;
-
- procedure TField.SetAsDateTime(Value: TDateTime);
- begin
- AccessError('DateTime');
- end;
-
- procedure TField.SetAsFloat(Value: Double);
- begin
- AccessError('Float');
- end;
-
- procedure TField.SetAsInteger(Value: Longint);
- begin
- AccessError('Integer');
- end;
-
- procedure TField.SetAsString(const Value: string);
- begin
- AccessError('String');
- end;
-
- procedure TField.SetAsVariant(const Value: Variant);
- begin
- if TVarData(Value).VType = varNull then
- Clear
- else
- try
- SetVarValue(Value);
- except
- on EVariantError do DBErrorFmt(SFieldValueError, [DisplayName]);
- end;
- end;
-
- procedure TField.SetAlignment(Value: TAlignment);
- begin
- if FAlignment <> Value then
- begin
- FAlignment := Value;
- PropertyChanged(False);
- end;
- end;
-
- procedure TField.SetCalculated(Value: Boolean);
- begin
- if Value then
- FieldKind := fkCalculated
- else if not Lookup then FieldKind := fkData;
- end;
-
- procedure TField.SetData(Buffer: Pointer);
- var
- RecBuf: PChar;
- begin
- if FDataSet = nil then DBErrorFmt(SDataSetMissing, [DisplayName]);
- with FDataSet do
- begin
- case State of
- dsEdit, dsInsert: RecBuf := FBuffers^[FActiveRecord];
- dsSetKey:
- begin
- RecBuf := PChar(FKeyBuffer) + SizeOf(TKeyBuffer);
- if (FieldNo < 0) or (FIndexFieldCount > 0) and not IsIndexField then
- DBErrorFmt(SNotIndexField, [DisplayName]);
- end;
- dsCalcFields: RecBuf := FCalcBuffer;
- dsUpdateNew: RecBuf := FUpdateCBBuf.pNewRecBuf;
- dsUpdateOld: DBError(SNoOldValueUpdate);
- dsFilter: RecBuf := FFilterBuffer;
- else
- DBError(SNotEditing);
- end;
- if FieldNo > 0 then
- begin
- if (State <> dsSetKey) and (State <> dsFilter) and ReadOnly then
- DBErrorFmt(SFieldReadOnly, [DisplayName]);
- if State = dsCalcFields then DBError(SNotEditing);
- if Assigned(FOnValidate) then
- begin
- FValueBuffer := Buffer;
- FValidating := True;
- try
- FOnValidate(Self);
- finally
- FValidating := False;
- end;
- end;
- if not BDECalcField then
- Check(DbiPutField(FHandle, FieldNo, RecBuf, Buffer));
- end else
- begin
- Inc(RecBuf, FRecordSize + FOffset);
- Boolean(RecBuf[0]) := LongBool(Buffer);
- if Boolean(RecBuf[0]) then Move(Buffer^, RecBuf[1], DataSize);
- end;
- if (State <> dsCalcFields) and (State <> dsFilter) then
- DataEvent(deFieldChange, Longint(Self));
- end;
- end;
-
- procedure TField.SetDataSet(ADataSet: TDataSet);
- begin
- if ADataset <> FDataset then
- begin
- if FDataSet <> nil then FDataSet.CheckInactive;
- if ADataSet <> nil then
- begin
- ADataSet.CheckInactive;
- ADataSet.CheckFieldName(FFieldName);
- end;
- if FDataSet <> nil then FDataSet.RemoveField(Self);
- if ADataSet <> nil then ADataSet.AddField(Self);
- end;
- end;
-
- procedure TField.SetDataType(Value: TFieldType);
- begin
- FDataType := Value;
- UpdateDataSize;
- end;
-
- procedure TField.SetDisplayLabel(Value: string);
- begin
- if Value = FFieldName then Value := '';
- if FDisplayLabel <> Value then
- begin
- FDisplaylabel := Value;
- PropertyChanged(True);
- end;
- end;
-
- procedure TField.SetDisplayWidth(Value: Integer);
- begin
- if FDisplayWidth <> Value then
- begin
- FDisplayWidth := Value;
- PropertyChanged(True);
- end;
- end;
-
- procedure TField.SetEditMask(const Value: string);
- begin
- FEditMask := Value;
- PropertyChanged(False);
- end;
-
- procedure TField.SetEditText(const Value: string);
- begin
- if Assigned(FOnSetText) then FOnSetText(Self, Value) else SetText(Value);
- end;
-
- procedure TField.SetFieldKind(Value: TFieldKind);
- begin
- if FFieldKind <> Value then
- begin
- CheckInactive;
- FFieldKind := Value;
- end;
- end;
-
- procedure TField.SetFieldName(const Value: string);
- begin
- CheckInactive;
- if FDataSet <> nil then FDataSet.CheckFieldName(Value);
- FFieldName := Value;
- if FDisplayLabel = Value then FDisplayLabel := '';
- if FDataSet <> nil then FDataSet.DataEvent(deFieldListChange, 0);
- end;
-
- procedure TField.SetFieldType(Value: TFieldType);
- begin
- end;
-
- procedure TField.SetIndex(Value: Integer);
- var
- CurIndex, Count: Integer;
- begin
- CurIndex := GetIndex;
- if CurIndex >= 0 then
- begin
- Count := FDataSet.FFields.Count;
- if Value < 0 then Value := 0;
- if Value >= Count then Value := Count - 1;
- if Value <> CurIndex then
- begin
- FDataSet.FFields.Delete(CurIndex);
- FDataSet.FFields.Insert(Value, Self);
- PropertyChanged(True);
- FDataSet.DataEvent(deFieldListChange, 0);
- end;
- end;
- end;
-
- procedure TField.SetLookup(Value: Boolean);
- begin
- if Value then
- FieldKind := fkLookup
- else if not Calculated then FieldKind := fkData;
- end;
-
- procedure TField.SetLookupDataSet(Value: TDataSet);
- begin
- CheckInactive;
- if (Value <> nil) and (Value = FDataSet) then DBError(SCircularDataLink);
- FLookupDataSet := Value;
- end;
-
- procedure TField.SetLookupKeyFields(const Value: string);
- begin
- CheckInactive;
- FLookupKeyFields := Value;
- end;
-
- procedure TField.SetLookupResultField(const Value: string);
- begin
- CheckInactive;
- FLookupResultField := Value;
- end;
-
- procedure TField.SetKeyFields(const Value: string);
- begin
- CheckInactive;
- FKeyFields := Value;
- end;
-
- procedure TField.SetNewValue(const Value: Variant);
- begin
- FDataSet.FState := dsUpdateNew;
- try
- SetAsVariant(Value);
- finally
- FDataSet.FState := dsBrowse;
- end;
- end;
-
- procedure TField.SetSize(Value: Word);
- begin
- CheckInactive;
- CheckTypeSize(DataType, Value);
- FSize := Value;
- UpdateDataSize;
- end;
-
- procedure TField.SetText(const Value: string);
- begin
- SetAsString(Value);
- end;
-
- procedure TField.SetVarValue(const Value: Variant);
- begin
- AccessError('Variant');
- end;
-
- procedure TField.SetVisible(Value: Boolean);
- begin
- if FVisible <> Value then
- begin
- FVisible := Value;
- PropertyChanged(True);
- end;
- end;
-
- procedure TField.UpdateDataSize;
- begin
- case FDataType of
- ftSmallint, ftWord, ftBoolean:
- FDataSize := 2;
- ftInteger, ftDate, ftTime, ftAutoInc:
- FDataSize := 4;
- ftFloat, ftCurrency, ftDateTime:
- FDataSize := 8;
- ftBCD:
- FDataSize := 34;
- ftBytes:
- FDataSize := Size;
- ftVarBytes:
- FDataSize := Size + 2;
- ftString:
- FDataSize := Size + 1;
- else
- FDataSize := 0;
- end;
- end;
-
- procedure TField.WriteAttributeSet(Writer: TWriter);
- begin
- Writer.WriteString(FAttributeSet);
- end;
-
- { TDataSource }
-
- constructor TDataSource.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FDataLinks := TList.Create;
- FEnabled := True;
- FAutoEdit := True;
- end;
-
- destructor TDataSource.Destroy;
- begin
- FOnStateChange := nil;
- SetDataSet(nil);
- while FDataLinks.Count > 0 do RemoveDataLink(FDataLinks.Last);
- FDataLinks.Free;
- inherited Destroy;
- end;
-
- procedure TDataSource.Edit;
- begin
- if AutoEdit and (State = dsBrowse) then DataSet.Edit;
- end;
-
- procedure TDataSource.SetState(Value: TDataSetState);
- var
- PriorState: TDataSetState;
- begin
- if FState <> Value then
- begin
- PriorState := FState;
- FState := Value;
- NotifyDataLinks(deUpdateState, 0);
- if not (csDestroying in ComponentState) then
- begin
- if Assigned(FOnStateChange) then FOnStateChange(Self);
- if PriorState = dsInactive then
- if Assigned(FOnDataChange) then FOnDataChange(Self, nil);
- end;
- end;
- end;
-
- procedure TDataSource.UpdateState;
- begin
- if Enabled and (DataSet <> nil) then
- SetState(DataSet.State) else
- SetState(dsInactive);
- end;
-
- function TDataSource.IsLinkedTo(DataSet: TDataSet): Boolean;
- var
- DataSource: TDataSource;
- begin
- Result := True;
- while DataSet <> nil do
- begin
- DataSource := DataSet.GetDataSource;
- if DataSource = nil then Break;
- if DataSource = Self then Exit;
- DataSet := DataSource.DataSet;
- end;
- Result := False;
- end;
-
- procedure TDataSource.SetDataSet(ADataSet: TDataSet);
- begin
- if IsLinkedTo(ADataSet) then DBError(SCircularDataLink);
- if FDataSet <> nil then FDataSet.RemoveDataSource(Self);
- if ADataSet <> nil then ADataSet.AddDataSource(Self);
- end;
-
- procedure TDataSource.SetEnabled(Value: Boolean);
- begin
- FEnabled := Value;
- UpdateState;
- end;
-
- procedure TDataSource.AddDataLink(DataLink: TDataLink);
- begin
- FDataLinks.Add(DataLink);
- DataLink.FDataSource := Self;
- if DataSet <> nil then DataSet.UpdateBufferCount;
- DataLink.UpdateState;
- end;
-
- procedure TDataSource.RemoveDataLink(DataLink: TDataLink);
- begin
- DataLink.FDataSource := nil;
- FDataLinks.Remove(DataLink);
- DataLink.UpdateState;
- if DataSet <> nil then DataSet.UpdateBufferCount;
- end;
-
- procedure TDataSource.NotifyDataLinks(Event: TDataEvent; Info: Longint);
- var
- I: Integer;
- begin
- for I := 0 to FDataLinks.Count - 1 do
- with TDataLink(FDataLinks[I]) do
- if FBufferCount = 1 then DataEvent(Event, Info);
- for I := 0 to FDataLinks.Count - 1 do
- with TDataLink(FDataLinks[I]) do
- if FBufferCount > 1 then DataEvent(Event, Info);
- end;
-
- procedure TDataSource.DataEvent(Event: TDataEvent; Info: Longint);
- begin
- if Event = deUpdateState then UpdateState else
- if FState <> dsInactive then
- begin
- NotifyDataLinks(Event, Info);
- case Event of
- deFieldChange:
- if Assigned(FOnDataChange) then FOnDataChange(Self, TField(Info));
- deRecordChange, deDataSetChange, deDataSetScroll, deLayoutChange:
- if Assigned(FOnDataChange) then FOnDataChange(Self, nil);
- deUpdateRecord:
- if Assigned(FOnUpdateData) then FOnUpdateData(Self);
- end;
- end;
- end;
-
- { TDataLink }
-
- constructor TDataLink.Create;
- begin
- inherited Create;
- FBufferCount := 1;
- end;
-
- destructor TDataLink.Destroy;
- begin
- FActive := False;
- FEditing := False;
- FDataSourceFixed := False;
- SetDataSource(nil);
- inherited Destroy;
- end;
-
- procedure TDataLink.UpdateRange;
- var
- Min, Max: Integer;
- begin
- Min := DataSet.FActiveRecord - FBufferCount + 1;
- if Min < 0 then Min := 0;
- Max := DataSet.FBufferCount - FBufferCount;
- if Max < 0 then Max := 0;
- if Max > DataSet.FActiveRecord then Max := DataSet.FActiveRecord;
- if FFirstRecord < Min then FFirstRecord := Min;
- if FFirstRecord > Max then FFirstRecord := Max;
- end;
-
- function TDataLink.GetDataSet: TDataSet;
- begin
- if DataSource <> nil then Result := DataSource.DataSet else Result := nil;
- end;
-
- procedure TDataLink.SetDataSource(ADataSource: TDataSource);
- begin
- if FDataSource <> ADataSource then
- begin
- if FDataSourceFixed then DBError(SDataSourceChange);
- if FDataSource <> nil then FDataSource.RemoveDataLink(Self);
- if ADataSource <> nil then ADataSource.AddDataLink(Self);
- end;
- end;
-
- procedure TDataLink.SetReadOnly(Value: Boolean);
- begin
- if FReadOnly <> Value then
- begin
- FReadOnly := Value;
- UpdateState;
- end;
- end;
-
- procedure TDataLink.SetActive(Value: Boolean);
- begin
- if FActive <> Value then
- begin
- FActive := Value;
- if Value then UpdateRange else FFirstRecord := 0;
- ActiveChanged;
- end;
- end;
-
- procedure TDataLink.SetEditing(Value: Boolean);
- begin
- if FEditing <> Value then
- begin
- FEditing := Value;
- EditingChanged;
- end;
- end;
-
- procedure TDataLink.UpdateState;
- begin
- SetActive((DataSource <> nil) and (DataSource.State <> dsInactive));
- SetEditing((DataSource <> nil) and (DataSource.State in dsEditModes) and
- not FReadOnly);
- end;
-
- procedure TDataLink.UpdateRecord;
- begin
- FUpdating := True;
- try
- UpdateData;
- finally
- FUpdating := False;
- end;
- end;
-
- function TDataLink.Edit: Boolean;
- begin
- if not FReadOnly and (DataSource <> nil) then DataSource.Edit;
- Result := FEditing;
- end;
-
- function TDataLink.GetActiveRecord: Integer;
- begin
- if DataSource.State = dsSetKey then
- Result := 0 else
- Result := DataSource.DataSet.FActiveRecord - FFirstRecord;
- end;
-
- procedure TDataLink.SetActiveRecord(Value: Integer);
- begin
- if DataSource.State <> dsSetKey then
- DataSource.DataSet.FActiveRecord := Value + FFirstRecord;
- end;
-
- procedure TDataLink.SetBufferCount(Value: Integer);
- begin
- if FBufferCount <> Value then
- begin
- FBufferCount := Value;
- if Active then
- begin
- UpdateRange;
- DataSet.UpdateBufferCount;
- UpdateRange;
- end;
- end;
- end;
-
- function TDataLink.GetRecordCount: Integer;
- begin
- if DataSource.State = dsSetKey then Result := 1 else
- begin
- Result := DataSource.DataSet.FRecordCount;
- if Result > FBufferCount then Result := FBufferCount;
- end;
- end;
-
- procedure TDataLink.DataEvent(Event: TDataEvent; Info: Longint);
- var
- Active, First, Last, Count: Integer;
- begin
- if Event = deUpdateState then UpdateState else
- if FActive then
- case Event of
- deFieldChange, deRecordChange:
- if not FUpdating then RecordChanged(TField(Info));
- deDataSetChange, deDataSetScroll, deLayoutChange:
- begin
- Count := 0;
- if DataSource.State <> dsSetKey then
- begin
- Active := DataSource.DataSet.FActiveRecord;
- First := FFirstRecord + Info;
- Last := First + FBufferCount - 1;
- if Active > Last then Count := Active - Last else
- if Active < First then Count := Active - First;
- FFirstRecord := First + Count;
- end;
- case Event of
- deDataSetChange: DataSetChanged;
- deDataSetScroll: DataSetScrolled(Count);
- deLayoutChange: LayoutChanged;
- end;
- end;
- deUpdateRecord:
- UpdateRecord;
- deCheckBrowseMode:
- CheckBrowseMode;
- deFocusControl:
- FocusControl(TFieldRef(Info));
- end;
- end;
-
- procedure TDataLink.ActiveChanged;
- begin
- end;
-
- procedure TDataLink.CheckBrowseMode;
- begin
- end;
-
- procedure TDataLink.DataSetChanged;
- begin
- RecordChanged(nil);
- end;
-
- procedure TDataLink.DataSetScrolled(Distance: Integer);
- begin
- DataSetChanged;
- end;
-
- procedure TDataLink.EditingChanged;
- begin
- end;
-
- procedure TDataLink.FocusControl(Field: TFieldRef);
- begin
- end;
-
- procedure TDataLink.LayoutChanged;
- begin
- DataSetChanged;
- end;
-
- procedure TDataLink.RecordChanged(Field: TField);
- begin
- end;
-
- procedure TDataLink.UpdateData;
- begin
- end;
-
- initialization
- Sessions := TSessionList.Create;
- Session := TSession.Create(nil);
- Session.SessionName := 'Default';
- finalization
- Sessions.Free;
- BDEInitProcs.Free;
- FreeTimer;
- end.
-