PageRenderTime 466ms CodeModel.GetById 37ms RepoModel.GetById 10ms app.codeStats 1ms

/Gedemin/IBX/IBCustomDataSet.2

http://gedemin.googlecode.com/
Unknown | 2046 lines | 1871 code | 175 blank | 0 comment | 0 complexity | 8c120e0ae32d5e12e473126c5ffc711c MD5 | raw file
Possible License(s): AGPL-3.0, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.0, LGPL-2.1
  1. {************************************************************************}
  2. { }
  3. { Borland Delphi Visual Component Library }
  4. { InterBase Express core components }
  5. { }
  6. { Copyright (c) 1998-2001 Borland Software Corporation }
  7. { }
  8. { InterBase Express is based in part on the product }
  9. { Free IB Components, written by Gregory H. Deatz for }
  10. { Hoagland, Longo, Moran, Dunst & Doukas Company. }
  11. { Free IB Components is used under license. }
  12. { }
  13. { The contents of this file are subject to the InterBase }
  14. { Public License Version 1.0 (the "License"); you may not }
  15. { use this file except in compliance with the License. You may obtain }
  16. { a copy of the License at http://www.borland.com/interbase/IPL.html }
  17. { Software distributed under the License is distributed on }
  18. { an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
  19. { express or implied. See the License for the specific language }
  20. { governing rights and limitations under the License. }
  21. { The Original Code was created by InterBase Software Corporation }
  22. { and its successors. }
  23. { Portions created by Borland Software Corporation are Copyright }
  24. { (C) Borland Software Corporation. All Rights Reserved. }
  25. { Contributor(s): Jeff Overcash }
  26. { }
  27. {************************************************************************}
  28. unit IBCustomDataSet;
  29. interface
  30. // ?????????? ???? ??????, ????? ??????? ?????? ???????????
  31. // ? ?????? ???????????, ? ?? ? ?????? ??????
  32. {_$_DEFINE HEAP_STRING_FIELD}
  33. uses
  34. Windows, SysUtils, Classes, Controls, IBExternals, IB, IBHeader, StdVcl,
  35. IBDatabase, IBSQL, Db, IBUtils, IBBlob
  36. //!!!b
  37. , DBGrids
  38. //!!!e
  39. ;
  40. const
  41. BufferCacheSize = 1000; { Allocate cache in this many record chunks}
  42. UniCache = 2; { Uni-directional cache is 2 records big }
  43. type
  44. TIBCustomDataSet = class;
  45. TIBDataSet = class;
  46. //!!!b
  47. //////////////////////////////////////////////////////////
  48. // ????????? -- ????????, ??????????? ?? ?????? ???????
  49. //
  50. TgdcAggregate = class;
  51. TgdcAggregates = class;
  52. TgdcAggUpdateEvent = procedure(Agg: TgdcAggregate) of object;
  53. TgdcAggregate = class(TCollectionItem)
  54. private
  55. FVisible: Boolean;
  56. FActive: Boolean;
  57. FInUse: Boolean;
  58. FDataSize: Integer;
  59. FIndexName: String;
  60. FAggregateName: String;
  61. FExpression: String;
  62. FDataType: TFieldType;
  63. FOnUpdate: TgdcAggUpdateEvent;
  64. FDataSet: TIBCustomDataSet;
  65. FValue: Variant;
  66. procedure SetActive(const Value: Boolean);
  67. procedure SetExpression(const Value: String);
  68. procedure SetIndexName(const Value: String);
  69. procedure SetVisible(const Value: Boolean);
  70. public
  71. constructor Create(AnAggregates: TgdcAggregates; ADataSet: TIBCustomDataSet); reintroduce;
  72. function Value: Variant;
  73. function GetDisplayName: String; override;
  74. procedure SetValue(AValue: Variant);
  75. property Active: Boolean read FActive write SetActive;
  76. property AggregateName: String read FAggregateName write FAggregateName;
  77. property DataSet: TIBCustomDataSet read FDataSet;
  78. property DataSize: Integer read FDataSize;
  79. property DataType: TFieldType read FDataType write FDataType;
  80. property Expression: String read FExpression write SetExpression;
  81. property IndexName: String read FIndexName write SetIndexName;
  82. property InUse: Boolean read FInUse;
  83. property OnUpdate: TgdcAggUpdateEvent read FOnUpdate write FOnUpdate;
  84. property Visible: Boolean read FVisible write SetVisible;
  85. end;
  86. TgdcAggregates = class(TCollection)
  87. private
  88. FOwner: TPersistent;
  89. function GetItem(Index: Integer): TgdcAggregate;
  90. procedure SetItem(Index: Integer; const Value: TgdcAggregate);
  91. protected
  92. function GetOwner: TPersistent; override;
  93. public
  94. constructor Create(Owner: TPersistent);
  95. function Add: TgdcAggregate;
  96. procedure Clear;
  97. function Find(const DisplayName: string): TgdcAggregate;
  98. function IndexOf(const DisplayName: string): Integer;
  99. property Items[Index: Integer]: TgdcAggregate read GetItem write SetItem; default;
  100. end;
  101. //!!!e
  102. TIBDataSetUpdateObject = class(TComponent)
  103. private
  104. FRefreshSQL: TStrings;
  105. procedure SetRefreshSQL(value: TStrings);
  106. protected
  107. function GetDataSet: TIBCustomDataSet; virtual; abstract;
  108. procedure SetDataSet(ADataSet: TIBCustomDataSet); virtual; abstract;
  109. {
  110. procedure Apply(UpdateKind: TUpdateKind); virtual; abstract;
  111. function GetSQL(UpdateKind: TUpdateKind): TStrings; virtual; abstract;
  112. }
  113. property DataSet: TIBCustomDataSet read GetDataSet write SetDataSet;
  114. public
  115. constructor Create(AOwner: TComponent); override;
  116. destructor Destroy; override;
  117. //!!!!
  118. //?????????? Andreik
  119. procedure Apply(UpdateKind: TUpdateKind); virtual; abstract;
  120. function GetSQL(UpdateKind: TUpdateKind): TStrings; virtual; abstract;
  121. //!!!!
  122. published
  123. property RefreshSQL: TStrings read FRefreshSQL write SetRefreshSQL;
  124. end;
  125. PDateTime = ^TDateTime;
  126. TBlobDataArray = array[0..0] of TIBBlobStream;
  127. PBlobDataArray = ^TBlobDataArray;
  128. { TIBCustomDataSet }
  129. TFieldData = record
  130. fdDataType: Short;
  131. fdDataScale: Short;
  132. fdNullable: Boolean;
  133. fdIsNull: Boolean;
  134. fdDataSize: Short;
  135. fdDataLength: Short;
  136. fdDataOfs: Integer;
  137. end;
  138. PFieldData = ^TFieldData;
  139. TCachedUpdateStatus = (
  140. cusUnmodified, cusModified, cusInserted,
  141. cusDeleted, cusUninserted
  142. );
  143. TIBDBKey = record
  144. DBKey: array[0..7] of Byte;
  145. end;
  146. PIBDBKey = ^TIBDBKey;
  147. TRecordData = record
  148. rdBookmarkFlag: TBookmarkFlag;
  149. rdFieldCount: Short;
  150. rdRecordNumber: Long;
  151. rdCachedUpdateStatus: TCachedUpdateStatus;
  152. rdUpdateStatus: TUpdateStatus;
  153. rdSavedOffset: DWORD;
  154. rdDBKey: TIBDBKey;
  155. rdFields: array[1..1] of TFieldData;
  156. end;
  157. PRecordData = ^TRecordData;
  158. { TIBStringField allows us to have strings longer than 8196 }
  159. TIBStringField = class(TStringField)
  160. public
  161. constructor create(AOwner: TComponent); override;
  162. class procedure CheckTypeSize(Value: Integer); override;
  163. function GetAsString: string; override;
  164. function GetAsVariant: Variant; override;
  165. function GetValue(var Value: string): Boolean;
  166. procedure SetAsString(const Value: string); override;
  167. end;
  168. { TIBBCDField }
  169. { Actually, there is no BCD involved in this type,
  170. instead it deals with currency types.
  171. In IB, this is an encapsulation of Numeric (x, y)
  172. where x < 18 and y <= 4.
  173. Note: y > 4 will default to Floats
  174. }
  175. TIBBCDField = class(TBCDField)
  176. protected
  177. class procedure CheckTypeSize(Value: Integer); override;
  178. function GetAsCurrency: Currency; override;
  179. function GetAsString: string; override;
  180. function GetAsVariant: Variant; override;
  181. function GetDataSize: Integer; override;
  182. public
  183. constructor Create(AOwner: TComponent); override;
  184. published
  185. property Size default 8;
  186. end;
  187. TIBDataLink = class(TDetailDataLink)
  188. private
  189. FDataSet: TIBCustomDataSet;
  190. protected
  191. procedure ActiveChanged; override;
  192. procedure RecordChanged(Field: TField); override;
  193. function GetDetailDataSet: TDataSet; override;
  194. procedure CheckBrowseMode; override;
  195. public
  196. constructor Create(ADataSet: TIBCustomDataSet);
  197. destructor Destroy; override;
  198. end;
  199. TIBGeneratorApplyEvent = (gamOnNewRecord, gamOnPost, gamOnServer);
  200. TIBGeneratorField = class(TPersistent)
  201. private
  202. FField: string;
  203. FGenerator: string;
  204. FIncrementBy: Integer;
  205. DataSet: TIBCustomDataSet;
  206. FApplyEvent: TIBGeneratorApplyEvent;
  207. function IsComplete: Boolean;
  208. public
  209. constructor Create(ADataSet: TIBCustomDataSet);
  210. function ValueName: string;
  211. procedure Apply;
  212. procedure Assign(Source: TPersistent); override;
  213. published
  214. property Field : string read FField write FField;
  215. property Generator : string read FGenerator write FGenerator;
  216. property IncrementBy : Integer read FIncrementBy write FIncrementBy default 1;
  217. property ApplyEvent : TIBGeneratorApplyEvent read FApplyEvent write FApplyEvent default gamOnNewRecord;
  218. end;
  219. { TIBCustomDataSet }
  220. TIBUpdateAction = (uaFail, uaAbort, uaSkip, uaRetry, uaApply, uaApplied);
  221. TIBUpdateErrorEvent = procedure(DataSet: TDataSet; E: EDatabaseError;
  222. UpdateKind: TUpdateKind; var UpdateAction: TIBUpdateAction)
  223. of object;
  224. TIBUpdateRecordEvent = procedure(DataSet: TDataSet; UpdateKind: TUpdateKind;
  225. var UpdateAction: TIBUpdateAction) of object;
  226. TIBUpdateRecordTypes = set of TCachedUpdateStatus;
  227. TLiveMode = (lmInsert, lmModify, lmDelete, lmRefresh);
  228. TLiveModes = Set of TLiveMode;
  229. TIBCustomDataSet = class(TDataset)
  230. private
  231. //FNeedsRefresh: Boolean;
  232. FForcedRefresh: Boolean;
  233. FIBLoaded: Boolean;
  234. FBase: TIBBase;
  235. //!!!b
  236. FAggregatesActive: Boolean;
  237. FAggregates: TgdcAggregates;
  238. FReadBase: TIBBase;
  239. FBeforeInternalPostRecord: TDataSetNotifyEvent;
  240. FAfterInternalPostRecord: TDataSetNotifyEvent;
  241. FBeforeInternalDeleteRecord: TDataSetNotifyEvent;
  242. FAfterInternalDeleteRecord: TDataSetNotifyEvent;
  243. //!!!e
  244. //FBlobCacheOffset: Integer;
  245. FBlobStreamList: TList;
  246. FBufferChunks: Integer;
  247. //FBufferCache,
  248. FOldBufferCache: PChar;
  249. FBufferChunkSize,
  250. FCacheSize,
  251. FOldCacheSize: Integer;
  252. //FFilterBuffer: PChar;
  253. FBPos,
  254. FOBPos,
  255. FBEnd,
  256. FOBEnd: DWord;
  257. FCachedUpdates: Boolean;
  258. FCalcFieldsOffset: Integer;
  259. FCurrentRecord: Long;
  260. FDeletedRecords: Long;
  261. //FModelBuffer,
  262. FOldBuffer: PChar;
  263. FOpen: Boolean;
  264. FInternalPrepared: Boolean;
  265. //FQDelete,
  266. FQInsert,
  267. FQRefresh,
  268. //FQSelect,
  269. FQModify: TIBSQL;
  270. FRecordBufferSize: Integer;
  271. //FRecordCount: Integer;
  272. FRecordSize: Integer;
  273. FUniDirectional: Boolean;
  274. FUpdateMode: TUpdateMode;
  275. //FUpdateObject: TIBDataSetUpdateObject;
  276. FParamCheck: Boolean;
  277. FUpdatesPending: Boolean;
  278. FUpdateRecordTypes: TIBUpdateRecordTypes;
  279. //FMappedFieldPosition: array of Integer;
  280. FDataLink: TIBDataLink;
  281. FStreamedActive : Boolean;
  282. FLiveMode: TLiveModes;
  283. FGeneratorField: TIBGeneratorField;
  284. //FRowsAffected: Integer;
  285. FBeforeDatabaseDisconnect,
  286. FAfterDatabaseDisconnect,
  287. FDatabaseFree: TNotifyEvent;
  288. FOnUpdateError: TIBUpdateErrorEvent;
  289. FOnUpdateRecord: TIBUpdateRecordEvent;
  290. FBeforeTransactionEnd,
  291. FAfterTransactionEnd,
  292. FTransactionFree: TNotifyEvent;
  293. //!!!
  294. FReadTransactionSet: Boolean;
  295. FInsertedAt: Integer;
  296. FAllowStreamedActive: Boolean;
  297. FSavedRecordCount: Integer;
  298. //!!!
  299. function GetSelectStmtHandle: TISC_STMT_HANDLE;
  300. procedure SetUpdateMode(const Value: TUpdateMode);
  301. procedure SetUpdateObject(Value: TIBDataSetUpdateObject);
  302. function AdjustCurrentRecord(Buffer: Pointer; GetMode: TGetMode): TGetResult;
  303. procedure AdjustRecordOnInsert(Buffer: Pointer);
  304. function CanEdit: Boolean;
  305. function CanInsert: Boolean;
  306. function CanDelete: Boolean;
  307. //function CanRefresh: Boolean;
  308. procedure CheckEditState;
  309. procedure ClearBlobCache;
  310. //b!!!
  311. //procedure CopyRecordBuffer(Source, Dest: Pointer);
  312. //e!!!
  313. procedure DoBeforeDatabaseDisconnect(Sender: TObject);
  314. procedure DoAfterDatabaseDisconnect(Sender: TObject);
  315. procedure DoDatabaseFree(Sender: TObject);
  316. procedure DoBeforeTransactionEnd(Sender: TObject);
  317. //procedure DoAfterTransactionEnd(Sender: TObject);
  318. procedure DoTransactionFree(Sender: TObject);
  319. procedure FetchCurrentRecordToBuffer(Qry: TIBSQL; RecordNumber: Integer;
  320. Buffer: PChar);
  321. function GetDatabase: TIBDatabase;
  322. function GetDBHandle: PISC_DB_HANDLE;
  323. function GetDeleteSQL: TStrings;
  324. function GetInsertSQL: TStrings;
  325. function GetSQLParams: TIBXSQLDA;
  326. function GetRefreshSQL: TStrings;
  327. function GetSelectSQL: TStrings;
  328. function GetStatementType: TIBSQLTypes;
  329. function GetModifySQL: TStrings;
  330. function GetTransaction: TIBTransaction;
  331. function GetTRHandle: PISC_TR_HANDLE;
  332. //procedure InternalDeleteRecord(Qry: TIBSQL; Buff: Pointer);
  333. function InternalLocate(const KeyFields: string; const KeyValues: Variant;
  334. Options: TLocateOptions): Boolean;
  335. //procedure InternalPostRecord(Qry: TIBSQL; Buff: Pointer);
  336. procedure InternalRevertRecord(RecordNumber: Integer);
  337. function IsVisible(Buffer: PChar): Boolean;
  338. procedure SaveOldBuffer(Buffer: PChar);
  339. procedure SetBufferChunks(Value: Integer);
  340. procedure SetDatabase(Value: TIBDatabase);
  341. procedure SetDeleteSQL(Value: TStrings);
  342. procedure SetInsertSQL(Value: TStrings);
  343. //procedure SetInternalSQLParams(Qry: TIBSQL; Buffer: Pointer);
  344. procedure SetRefreshSQL(Value: TStrings);
  345. procedure SetSelectSQL(Value: TStrings);
  346. procedure SetModifySQL(Value: TStrings);
  347. //procedure SetTransaction(Value: TIBTransaction);
  348. procedure SetUpdateRecordTypes(Value: TIBUpdateRecordTypes);
  349. procedure SetUniDirectional(Value: Boolean);
  350. procedure RefreshParams;
  351. procedure SQLChanging(Sender: TObject);
  352. function AdjustPosition(FCache: PChar; Offset: DWORD;
  353. Origin: Integer): Integer;
  354. procedure ReadCache(FCache: PChar; Offset: DWORD; Origin: Integer;
  355. Buffer: PChar);
  356. //procedure ReadRecordCache(RecordNumber: Integer; Buffer: PChar;
  357. // ReadOldBuffer: Boolean);
  358. procedure WriteCache(FCache: PChar; Offset: DWORD; Origin: Integer;
  359. Buffer: PChar);
  360. //procedure WriteRecordCache(RecordNumber: Integer; Buffer: PChar);
  361. function InternalGetRecord(Buffer: PChar; GetMode: TGetMode;
  362. DoCheck: Boolean): TGetResult;
  363. procedure SetGeneratorField(const Value: TIBGeneratorField);
  364. {!!!}
  365. {
  366. function InternalGetFieldData(Field: TField; Buffer: Pointer): Boolean;
  367. procedure InternalSetFieldData(Field: TField; Buffer: Pointer); virtual;
  368. }
  369. {!!!}
  370. function GetPlan: String;
  371. //!!!
  372. function GetReadTransaction: TIBTransaction;
  373. procedure SetAggregatesActive(const Value: Boolean);
  374. {$IFDEF HEAP_STRING_FIELD}
  375. // ?? ????? ????????? ??? ???? ? ???? ??? ???????????
  376. // ??????????? ???????
  377. function IsHeapField(FD: TFieldData): Boolean;
  378. // ???? ???? ????, ??????????? ? ????, ?? ??????? ??? ???
  379. // ?????? ? ???????? ?? ?????????? ?? ?????????
  380. // ?.?. ???????? ????? ???????????? ?????
  381. // ????? ????????????? ????? ???? ???? ???????????
  382. // ??????????????!
  383. procedure InitializeRecordBuffer(Source, Dest: Pointer);
  384. // ??? ???????? ????????? ??????? ???????
  385. // ?????????????? ??? ???????? ???????? ?? ???? ?
  386. // ??? ???? ???????, ??? ??????? ? ?????? ?????????? ????????????
  387. // ?????? ?????????? ??????
  388. procedure FinalizeCacheBuffer(Buffer: PChar; const Size: Integer);
  389. {$ENDIF}
  390. //!!!
  391. protected
  392. {andreik}
  393. //!!!
  394. // ?????????? ?? ??????
  395. FRowsAffected: Integer;
  396. FUpdateObject: TIBDataSetUpdateObject;
  397. FQSelect, FQDelete: TIBSQL;
  398. FBlobCacheOffset: Integer;
  399. FMappedFieldPosition: array of Integer;
  400. FNeedsRefresh: Boolean;
  401. FFilterBuffer: PChar;
  402. FBufferCache: PChar;
  403. FRecordCount: Integer;
  404. FDataTransfer: Boolean; // ?????????!
  405. FAggregatesObsolete: Boolean; // !!!
  406. FPeekBuffer: PChar; // !!!
  407. FOpenCounter: Integer; //!!!
  408. FModelBuffer: PChar; //!!!
  409. FOnCalcAggregates: TFilterRecordEvent; //?????????
  410. function CanRefresh: Boolean;
  411. procedure InternalPostRecord(Qry: TIBSQL; Buff: Pointer); virtual;
  412. procedure SetInternalSQLParams(Qry: TIBSQL; Buffer: Pointer);
  413. procedure InternalDeleteRecord(Qry: TIBSQL; Buff: Pointer); virtual;
  414. procedure ReadRecordCache(RecordNumber: Integer; Buffer: PChar;
  415. ReadOldBuffer: Boolean);
  416. procedure WriteRecordCache(RecordNumber: Integer; Buffer: PChar);
  417. procedure DoAfterTransactionEnd(Sender: TObject); virtual;
  418. function InternalGetFieldData(Field: TField; Buffer: Pointer): Boolean;
  419. procedure InternalSetFieldData(Field: TField; Buffer: Pointer); virtual;
  420. procedure SetTransaction(Value: TIBTransaction); virtual;
  421. procedure SetFiltered(Value: Boolean); override;
  422. //b!!!
  423. procedure CopyRecordBuffer(Source, Dest: Pointer);
  424. //e!!!
  425. //!!!
  426. // ???? ???? ????, ??????????? ? ????, ????????? ??????
  427. // ??????? ??? ?? ?????????, ??? ??? ????????? ?????
  428. // ?? ???????? ? ????????? ????????????
  429. procedure FinalizeRecordBuffer(Buffer: Pointer);
  430. //!!!
  431. // ?????????
  432. procedure DoBeforeReadDatabaseDisconnect(Sender: TObject);
  433. procedure DoAfterReadDatabaseDisconnect(Sender: TObject);
  434. procedure DoReadDatabaseFree(Sender: TObject);
  435. procedure DoBeforeReadTransactionEnd(Sender: TObject);
  436. procedure DoAfterReadTransactionEnd(Sender: TObject);
  437. procedure DoReadTransactionFree(Sender: TObject);
  438. function AllowCloseTransaction: Boolean;
  439. procedure CheckOperation(Operation: TDataOperation;
  440. ErrorEvent: TDataSetErrorEvent);
  441. procedure SetReadTransaction(const Value: TIBTransaction); virtual;
  442. //!!!
  443. procedure ActivateConnection;
  444. function ActivateTransaction: Boolean;
  445. function ActivateReadTransaction: Boolean;
  446. procedure DeactivateTransaction;
  447. procedure DeactivateReadTransaction;
  448. procedure CheckDatasetClosed;
  449. procedure CheckDatasetOpen;
  450. function GetActiveBuf: PChar;
  451. procedure InternalBatchInput(InputObject: TIBBatchInput); virtual;
  452. procedure InternalBatchOutput(OutputObject: TIBBatchOutput); virtual;
  453. procedure InternalPrepare; virtual;
  454. procedure InternalUnPrepare; virtual;
  455. procedure InternalExecQuery; virtual;
  456. procedure InternalRefreshRow; virtual;
  457. procedure InternalSetParamsFromCursor; virtual;
  458. procedure CheckNotUniDirectional;
  459. procedure SetActive(Value: Boolean); override;
  460. { IProviderSupport }
  461. procedure PSEndTransaction(Commit: Boolean); override;
  462. function PSExecuteStatement(const ASQL: string; AParams: TParams;
  463. ResultSet: Pointer = nil): Integer; override;
  464. function PsGetTableName: string; override;
  465. function PSGetQuoteChar: string; override;
  466. function PSGetUpdateException(E: Exception; Prev: EUpdateError): EUpdateError; override;
  467. function PSInTransaction: Boolean; override;
  468. function PSIsSQLBased: Boolean; override;
  469. function PSIsSQLSupported: Boolean; override;
  470. procedure PSStartTransaction; override;
  471. procedure PSReset; override;
  472. function PSUpdateRecord(UpdateKind: TUpdateKind; Delta: TDataSet): Boolean; override;
  473. { TDataSet support }
  474. procedure InternalInsert; override;
  475. procedure InitRecord(Buffer: PChar); override;
  476. procedure Disconnect; virtual;
  477. function ConstraintsStored: Boolean;
  478. procedure ClearCalcFields(Buffer: PChar); override;
  479. procedure CreateFields; override;
  480. function AllocRecordBuffer: PChar; override;
  481. procedure DoBeforeDelete; override;
  482. procedure DoBeforeEdit; override;
  483. procedure DoBeforeInsert; override;
  484. procedure FreeRecordBuffer(var Buffer: PChar); override;
  485. procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
  486. function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
  487. function GetCanModify: Boolean; override;
  488. function GetDataSource: TDataSource; override;
  489. function GetFieldClass(FieldType: TFieldType): TFieldClass; override;
  490. function GetRecNo: Integer; override;
  491. function GetRecord(Buffer: PChar; GetMode: TGetMode;
  492. DoCheck: Boolean): TGetResult; override;
  493. function GetRecordCount: Integer; override;
  494. function GetRecordSize: Word; override;
  495. procedure InternalAddRecord(Buffer: Pointer; Append: Boolean); override;
  496. procedure InternalCancel; override;
  497. procedure InternalClose; override;
  498. procedure InternalDelete; override;
  499. procedure InternalFirst; override;
  500. procedure InternalGotoBookmark(Bookmark: Pointer); override;
  501. procedure InternalHandleException; override;
  502. procedure InternalInitFieldDefs; override;
  503. procedure InternalInitRecord(Buffer: PChar); override;
  504. procedure InternalLast; override;
  505. procedure InternalOpen; override;
  506. procedure InternalPost; override;
  507. procedure InternalRefresh; override;
  508. procedure InternalSetToRecord(Buffer: PChar); override;
  509. function IsCursorOpen: Boolean; override;
  510. procedure ReQuery;
  511. procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
  512. procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
  513. procedure SetCachedUpdates(Value: Boolean);
  514. procedure SetDataSource(Value: TDataSource);
  515. procedure SetFieldData(Field : TField; Buffer : Pointer); override;
  516. procedure SetFieldData(Field : TField; Buffer : Pointer;
  517. NativeFormat : Boolean); overload; override;
  518. procedure SetRecNo(Value: Integer); override;
  519. procedure DoOnNewRecord; override;
  520. procedure Loaded; override;
  521. //!!!b
  522. procedure DoAfterDelete; override;
  523. procedure DoAfterPost; override;
  524. procedure DoAfterRefresh; override;
  525. //!!!e
  526. protected
  527. {Likely to be made public by descendant classes}
  528. property SQLParams: TIBXSQLDA read GetSQLParams;
  529. property Params: TIBXSQLDA read GetSQLParams;
  530. property InternalPrepared: Boolean read FInternalPrepared;
  531. property QDelete: TIBSQL read FQDelete;
  532. property QInsert: TIBSQL read FQInsert;
  533. property QRefresh: TIBSQL read FQRefresh;
  534. //property QSelect: TIBSQL read FQSelect;
  535. property QModify: TIBSQL read FQModify;
  536. property StatementType: TIBSQLTypes read GetStatementType;
  537. property SelectStmtHandle: TISC_STMT_HANDLE read GetSelectStmtHandle;
  538. property LiveMode : TLiveModes read FLiveMode;
  539. {Likely to be made published by descendant classes}
  540. property BufferChunks: Integer read FBufferChunks write SetBufferChunks;
  541. property CachedUpdates: Boolean read FCachedUpdates write SetCachedUpdates;
  542. property UniDirectional: Boolean read FUniDirectional write SetUniDirectional default False;
  543. property DeleteSQL: TStrings read GetDeleteSQL write SetDeleteSQL;
  544. property InsertSQL: TStrings read GetInsertSQL write SetInsertSQL;
  545. property RefreshSQL: TStrings read GetRefreshSQL write SetRefreshSQL;
  546. property SelectSQL: TStrings read GetSelectSQL write SetSelectSQL;
  547. property ModifySQL: TStrings read GetModifySQL write SetModifySQL;
  548. property UpdateMode: TUpdateMode read FUpdateMode write SetUpdateMode default upWhereAll;
  549. property ParamCheck: Boolean read FParamCheck write FParamCheck default True;
  550. property GeneratorField : TIBGeneratorField read FGeneratorField write SetGeneratorField;
  551. property BeforeDatabaseDisconnect: TNotifyEvent read FBeforeDatabaseDisconnect
  552. write FBeforeDatabaseDisconnect;
  553. property AfterDatabaseDisconnect: TNotifyEvent read FAfterDatabaseDisconnect
  554. write FAfterDatabaseDisconnect;
  555. property DatabaseFree: TNotifyEvent read FDatabaseFree
  556. write FDatabaseFree;
  557. property BeforeTransactionEnd: TNotifyEvent read FBeforeTransactionEnd
  558. write FBeforeTransactionEnd;
  559. property AfterTransactionEnd: TNotifyEvent read FAfterTransactionEnd
  560. write FAfterTransactionEnd;
  561. property TransactionFree: TNotifyEvent read FTransactionFree
  562. write FTransactionFree;
  563. //
  564. property _RecordBufferSize: Integer read FRecordBufferSize;
  565. property _CurrentRecord: Integer read FCurrentRecord;
  566. //
  567. public
  568. constructor Create(AOwner: TComponent); override;
  569. destructor Destroy; override;
  570. procedure ApplyUpdates;
  571. function CachedUpdateStatus: TCachedUpdateStatus;
  572. procedure CancelUpdates;
  573. procedure FetchAll;
  574. function LocateNext(const KeyFields: string; const KeyValues: Variant;
  575. Options: TLocateOptions): Boolean;
  576. procedure RecordModified(Value: Boolean);
  577. procedure RevertRecord;
  578. procedure Undelete;
  579. procedure Post; override;
  580. function Current : TIBXSQLDA;
  581. function SQLType : TIBSQLTypes;
  582. //!!!b
  583. procedure Cancel; override;
  584. procedure CheckRequiredFields;
  585. //!!!e
  586. //!!!b
  587. procedure Sort(F: TField; const Ascending: Boolean = True);
  588. //!!!e
  589. //!!!b
  590. //
  591. procedure ResetAllAggs(AnActive: Boolean; BL: TBookmarkList);
  592. //!!!e
  593. { TDataSet support methods }
  594. function BookmarkValid(Bookmark: TBookmark): Boolean; override;
  595. function CompareBookmarks(Bookmark1, Bookmark2: TBookmark): Integer; override;
  596. function CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream; override;
  597. function GetCurrentRecord(Buffer: PChar): Boolean; override;
  598. function GetFieldData(Field : TField; Buffer : Pointer) : Boolean; overload; override;
  599. function GetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean): Boolean; overload; override;
  600. function Locate(const KeyFields: string; const KeyValues: Variant;
  601. Options: TLocateOptions): Boolean; override;
  602. function Lookup(const KeyFields: string; const KeyValues: Variant;
  603. const ResultFields: string): Variant; override;
  604. function UpdateStatus: TUpdateStatus; override;
  605. function IsSequenced: Boolean; override;
  606. property DBHandle: PISC_DB_HANDLE read GetDBHandle;
  607. property TRHandle: PISC_TR_HANDLE read GetTRHandle;
  608. property UpdateObject: TIBDataSetUpdateObject read FUpdateObject write SetUpdateObject;
  609. property UpdatesPending: Boolean read FUpdatesPending;
  610. property UpdateRecordTypes: TIBUpdateRecordTypes read FUpdateRecordTypes
  611. write SetUpdateRecordTypes;
  612. property RowsAffected : Integer read FRowsAffected;
  613. property Plan: String read GetPlan;
  614. //!!!b
  615. property QSelect: TIBSQL read FQSelect;
  616. property ReadTransaction: TIBTransaction read GetReadTransaction write SetReadTransaction;
  617. property CacheSize: Integer read FCacheSize;
  618. //
  619. property AggregatesActive: Boolean read FAggregatesActive write SetAggregatesActive;
  620. property Aggregates: TgdcAggregates read FAggregates;
  621. property AggregatesObsolete: Boolean read FAggregatesObsolete;
  622. property OpenCounter: Integer read FOpenCounter;
  623. property OnCalcAggregates: TFilterRecordEvent read FOnCalcAggregates write FOnCalcAggregates;
  624. //!!!e
  625. published
  626. property Database: TIBDatabase read GetDatabase write SetDatabase;
  627. property Transaction: TIBTransaction read GetTransaction
  628. write SetTransaction;
  629. property ForcedRefresh: Boolean read FForcedRefresh
  630. write FForcedRefresh default False;
  631. property AutoCalcFields;
  632. property ObjectView default False;
  633. property AfterCancel;
  634. property AfterClose;
  635. property AfterDelete;
  636. property AfterEdit;
  637. property AfterInsert;
  638. property AfterOpen;
  639. property AfterPost;
  640. property AfterRefresh;
  641. property AfterScroll;
  642. property BeforeCancel;
  643. property BeforeClose;
  644. property BeforeDelete;
  645. property BeforeEdit;
  646. property BeforeInsert;
  647. property BeforeOpen;
  648. property BeforePost;
  649. property BeforeRefresh;
  650. property BeforeScroll;
  651. property OnCalcFields;
  652. property OnDeleteError;
  653. property OnEditError;
  654. property OnNewRecord;
  655. property OnPostError;
  656. property OnUpdateError: TIBUpdateErrorEvent read FOnUpdateError
  657. write FOnUpdateError;
  658. property OnUpdateRecord: TIBUpdateRecordEvent read FOnUpdateRecord
  659. write FOnUpdateRecord;
  660. //!!!
  661. property BeforeInternalPostRecord: TDataSetNotifyEvent read FBeforeInternalPostRecord
  662. write FBeforeInternalPostRecord;
  663. property AfterInternalPostRecord: TDataSetNotifyEvent read FAfterInternalPostRecord
  664. write FAfterInternalPostRecord;
  665. property BeforeInternalDeleteRecord: TDataSetNotifyEvent read FBeforeInternalDeleteRecord
  666. write FBeforeInternalDeleteRecord;
  667. property AfterInternalDeleteRecord: TDataSetNotifyEvent read FAfterInternalDeleteRecord
  668. write FAfterInternalDeleteRecord;
  669. //!!!
  670. //!!!
  671. property AllowStreamedActive: Boolean read FAllowStreamedActive write FAllowStreamedActive
  672. default False;
  673. //!!!
  674. end;
  675. TIBDataSet = class(TIBCustomDataSet)
  676. private
  677. function GetPrepared: Boolean;
  678. protected
  679. procedure PSSetCommandText(const CommandText: string); override;
  680. procedure SetFiltered(Value: Boolean); override;
  681. procedure InternalOpen; override;
  682. public
  683. procedure Prepare;
  684. procedure UnPrepare;
  685. procedure BatchInput(InputObject: TIBBatchInput);
  686. procedure BatchOutput(OutputObject: TIBBatchOutput);
  687. procedure ExecSQL;
  688. public
  689. function ParamByName(Idx : String) : TIBXSQLVAR;
  690. property Params;
  691. property Prepared : Boolean read GetPrepared;
  692. property StatementType;
  693. property SelectStmtHandle;
  694. property LiveMode;
  695. { by andreik!!! }
  696. public
  697. property QDelete;
  698. property QInsert;
  699. property QRefresh;
  700. property QSelect;
  701. property QModify;
  702. published
  703. { TIBCustomDataSet }
  704. property BufferChunks;
  705. property CachedUpdates;
  706. property DeleteSQL;
  707. property InsertSQL;
  708. property RefreshSQL;
  709. property SelectSQL;
  710. property ModifySQL;
  711. property ParamCheck;
  712. property UniDirectional;
  713. property Filtered;
  714. property GeneratorField;
  715. property BeforeDatabaseDisconnect;
  716. property AfterDatabaseDisconnect;
  717. property DatabaseFree;
  718. property BeforeTransactionEnd;
  719. property AfterTransactionEnd;
  720. property TransactionFree;
  721. property UpdateObject;
  722. ///!!!!b
  723. property OnCalcAggregates;
  724. //!!!!e
  725. { TIBDataSet }
  726. property Active;
  727. property AutoCalcFields;
  728. property DataSource read GetDataSource write SetDataSource;
  729. property AfterCancel;
  730. property AfterClose;
  731. property AfterDelete;
  732. property AfterEdit;
  733. property AfterInsert;
  734. property AfterOpen;
  735. property AfterPost;
  736. property AfterScroll;
  737. property BeforeCancel;
  738. property BeforeClose;
  739. property BeforeDelete;
  740. property BeforeEdit;
  741. property BeforeInsert;
  742. property BeforeOpen;
  743. property BeforePost;
  744. property BeforeScroll;
  745. property OnCalcFields;
  746. property OnDeleteError;
  747. property OnEditError;
  748. property OnFilterRecord;
  749. property OnNewRecord;
  750. property OnPostError;
  751. end;
  752. { TIBDSBlobStream }
  753. TIBDSBlobStream = class(TStream)
  754. protected
  755. FField: TField;
  756. FBlobStream: TIBBlobStream;
  757. FModified : Boolean;
  758. public
  759. constructor Create(AField: TField; ABlobStream: TIBBlobStream;
  760. Mode: TBlobStreamMode);
  761. destructor Destroy; override;
  762. function Read(var Buffer; Count: Longint): Longint; override;
  763. function Seek(Offset: Longint; Origin: Word): Longint; override;
  764. procedure SetSize(NewSize: Longint); override;
  765. function Write(const Buffer; Count: Longint): Longint; override;
  766. end;
  767. //!!!b
  768. { TgsMemoField }
  769. TgsMemoField = class(TMemoField)
  770. private
  771. //??????????? ?????????? OnSetText
  772. procedure InsideSetText(Sender: TField; const Text: string);
  773. protected
  774. procedure SetText(const Value: string); override;
  775. public
  776. constructor Create(AOwner: TComponent); override;
  777. end;
  778. //!!!e
  779. const
  780. DefaultFieldClasses: array[TFieldType] of TFieldClass = (
  781. nil, { ftUnknown }
  782. TIBStringField, { ftString }
  783. TSmallintField, { ftSmallint }
  784. TIntegerField, { ftInteger }
  785. TWordField, { ftWord }
  786. TBooleanField, { ftBoolean }
  787. TFloatField, { ftFloat }
  788. TCurrencyField, { ftCurrency }
  789. TIBBCDField, { ftBCD }
  790. TDateField, { ftDate }
  791. TTimeField, { ftTime }
  792. TDateTimeField, { ftDateTime }
  793. TBytesField, { ftBytes }
  794. TVarBytesField, { ftVarBytes }
  795. TAutoIncField, { ftAutoInc }
  796. TBlobField, { ftBlob }
  797. TgsMemoField, { ftMemo }
  798. //TMemoField, { ftMemo }
  799. TGraphicField, { ftGraphic }
  800. TBlobField, { ftFmtMemo }
  801. TBlobField, { ftParadoxOle }
  802. TBlobField, { ftDBaseOle }
  803. TBlobField, { ftTypedBinary }
  804. nil, { ftCursor }
  805. TStringField, { ftFixedChar }
  806. nil, {TWideStringField } { ftWideString }
  807. TLargeIntField, { ftLargeInt }
  808. TADTField, { ftADT }
  809. TArrayField, { ftArray }
  810. TReferenceField, { ftReference }
  811. TDataSetField, { ftDataSet }
  812. TBlobField, { ftOraBlob }
  813. TgsMemoField, { ftOraClob }
  814. //TMemoField, { ftOraClob }
  815. TVariantField, { ftVariant }
  816. TInterfaceField, { ftInterface }
  817. TIDispatchField, { ftIDispatch }
  818. TGuidField); { ftGuid }
  819. var
  820. CreateProviderProc: function(DataSet: TIBCustomDataSet): IProvider = nil;
  821. implementation
  822. uses
  823. IBIntf, DBConsts,
  824. dlgRecordFetch_unit, Forms, flt_sql_parser; //!!! added by Andreik
  825. { TIBStringField}
  826. constructor TIBStringField.Create(AOwner: TComponent);
  827. begin
  828. inherited Create(AOwner);
  829. end;
  830. class procedure TIBStringField.CheckTypeSize(Value: Integer);
  831. begin
  832. { don't check string size. all sizes valid }
  833. end;
  834. function TIBStringField.GetAsString: string;
  835. begin
  836. if not GetValue(Result) then Result := '';
  837. end;
  838. function TIBStringField.GetAsVariant: Variant;
  839. var
  840. S: string;
  841. begin
  842. if GetValue(S) then Result := S else Result := Null;
  843. end;
  844. function TIBStringField.GetValue(var Value: string): Boolean;
  845. var
  846. Buffer: PChar;
  847. begin
  848. Buffer := nil;
  849. IBAlloc(Buffer, 0, Size + 1);
  850. try
  851. Result := GetData(Buffer);
  852. if Result then
  853. begin
  854. Value := string(Buffer);
  855. if Transliterate and (Value <> '') then
  856. DataSet.Translate(PChar(Value), PChar(Value), False);
  857. end
  858. finally
  859. FreeMem(Buffer);
  860. end;
  861. end;
  862. procedure TIBStringField.SetAsString(const Value: string);
  863. var
  864. Buffer: PChar;
  865. begin
  866. Buffer := nil;
  867. IBAlloc(Buffer, 0, Size + 1);
  868. try
  869. StrLCopy(Buffer, PChar(Value), Size);
  870. if Transliterate then
  871. DataSet.Translate(Buffer, Buffer, True);
  872. SetData(Buffer);
  873. finally
  874. FreeMem(Buffer);
  875. end;
  876. end;
  877. { TIBBCDField }
  878. constructor TIBBCDField.Create(AOwner: TComponent);
  879. begin
  880. inherited Create(AOwner);
  881. SetDataType(ftBCD);
  882. Size := 8;
  883. end;
  884. class procedure TIBBCDField.CheckTypeSize(Value: Integer);
  885. begin
  886. { No need to check as the base type is currency, not BCD }
  887. end;
  888. function TIBBCDField.GetAsCurrency: Currency;
  889. begin
  890. if not GetValue(Result) then
  891. Result := 0;
  892. end;
  893. function TIBBCDField.GetAsString: string;
  894. var
  895. C: System.Currency;
  896. begin
  897. if GetValue(C) then
  898. Result := CurrToStr(C)
  899. else
  900. Result := '';
  901. end;
  902. function TIBBCDField.GetAsVariant: Variant;
  903. var
  904. C: System.Currency;
  905. begin
  906. if GetValue(C) then
  907. Result := C
  908. else
  909. Result := Null;
  910. end;
  911. function TIBBCDField.GetDataSize: Integer;
  912. begin
  913. Result := 8;
  914. end;
  915. { TIBDataLink }
  916. constructor TIBDataLink.Create(ADataSet: TIBCustomDataSet);
  917. begin
  918. inherited Create;
  919. FDataSet := ADataSet;
  920. end;
  921. destructor TIBDataLink.Destroy;
  922. begin
  923. FDataSet.FDataLink := nil;
  924. inherited Destroy;
  925. end;
  926. procedure TIBDataLink.ActiveChanged;
  927. begin
  928. if FDataSet.Active then
  929. FDataSet.RefreshParams;
  930. end;
  931. function TIBDataLink.GetDetailDataSet: TDataSet;
  932. begin
  933. Result := FDataSet;
  934. end;
  935. procedure TIBDataLink.RecordChanged(Field: TField);
  936. begin
  937. if (Field = nil) and FDataSet.Active then
  938. FDataSet.RefreshParams;
  939. end;
  940. procedure TIBDataLink.CheckBrowseMode;
  941. begin
  942. if FDataSet.Active then
  943. FDataSet.CheckBrowseMode;
  944. end;
  945. { TIBCustomDataSet }
  946. constructor TIBCustomDataSet.Create(AOwner: TComponent);
  947. begin
  948. inherited Create(AOwner);
  949. FIBLoaded := False;
  950. CheckIBLoaded;
  951. FIBLoaded := True;
  952. FBase := TIBBase.Create(Self);
  953. //!!!
  954. FReadBase := TIBBase.Create(Self);
  955. FReadTransactionSet := False;
  956. FDataTransfer := False;
  957. FAggregatesObsolete := True;
  958. FAllowStreamedActive := False;
  959. FSavedRecordCount := -1;
  960. //!!!
  961. FCurrentRecord := -1;
  962. FDeletedRecords := 0;
  963. FUniDirectional := False;
  964. FBufferChunks := BufferCacheSize;
  965. FBlobStreamList := TList.Create;
  966. FDataLink := TIBDataLink.Create(Self);
  967. FQDelete := TIBSQL.Create(Self);
  968. FQDelete.OnSQLChanging := SQLChanging;
  969. FQDelete.GoToFirstRecordOnExecute := False;
  970. FQInsert := TIBSQL.Create(Self);
  971. FQInsert.OnSQLChanging := SQLChanging;
  972. FQInsert.GoToFirstRecordOnExecute := False;
  973. FQRefresh := TIBSQL.Create(Self);
  974. FQRefresh.OnSQLChanging := SQLChanging;
  975. FQRefresh.GoToFirstRecordOnExecute := False;
  976. FQSelect := TIBSQL.Create(Self);
  977. FQSelect.OnSQLChanging := SQLChanging;
  978. FQSelect.GoToFirstRecordOnExecute := False;
  979. FQModify := TIBSQL.Create(Self);
  980. FQModify.OnSQLChanging := SQLChanging;
  981. FQModify.GoToFirstRecordOnExecute := False;
  982. FUpdateRecordTypes := [cusUnmodified, cusModified, cusInserted];
  983. FParamCheck := True;
  984. FForcedRefresh := False;
  985. FGeneratorField := TIBGeneratorField.Create(Self);
  986. {Bookmark Size is Integer for IBX}
  987. BookmarkSize := SizeOf(Integer);
  988. FBase.BeforeDatabaseDisconnect := DoBeforeDatabaseDisconnect;
  989. FBase.AfterDatabaseDisconnect := DoAfterDatabaseDisconnect;
  990. FBase.OnDatabaseFree := DoDatabaseFree;
  991. FBase.BeforeTransactionEnd := DoBeforeTransactionEnd;
  992. FBase.AfterTransactionEnd := DoAfterTransactionEnd;
  993. FBase.OnTransactionFree := DoTransactionFree;
  994. //!!!b
  995. FReadBase.BeforeDatabaseDisconnect := DoBeforeReadDatabaseDisconnect;
  996. FReadBase.AfterDatabaseDisconnect := DoAfterReadDatabaseDisconnect;
  997. FReadBase.OnDatabaseFree := DoReadDatabaseFree;
  998. FReadBase.BeforeTransactionEnd := DoBeforeReadTransactionEnd;
  999. FReadBase.AfterTransactionEnd := DoAfterReadTransactionEnd;
  1000. FReadBase.OnTransactionFree := DoReadTransactionFree;
  1001. FAggregates := TgdcAggregates.Create(Self);
  1002. FAggregatesActive := False;
  1003. FOpenCounter := 0;
  1004. //!!!e
  1005. FLiveMode := [];
  1006. FRowsAffected := 0;
  1007. FStreamedActive := false;
  1008. if AOwner is TIBDatabase then
  1009. Database := TIBDatabase(AOwner)
  1010. else
  1011. if AOwner is TIBTransaction then
  1012. Transaction := TIBTransaction(AOwner);
  1013. end;
  1014. destructor TIBCustomDataSet.Destroy;
  1015. begin
  1016. if FIBLoaded then
  1017. begin
  1018. Close;
  1019. FreeAndNil(FDataLink);
  1020. FreeAndNil(FBase);
  1021. //!!!b
  1022. FreeAndNil(FReadBase);
  1023. FreeAndNil(FAggregates);
  1024. //!!!e
  1025. ClearBlobCache;
  1026. FreeAndNil(FBlobStreamList);
  1027. {$IFDEF HEAP_STRING_FIELD}
  1028. FinalizeCacheBuffer(FBufferCache, FCacheSize);
  1029. {$ENDIF}
  1030. FreeMem(FBufferCache, 0);
  1031. FBufferCache := nil;
  1032. {$IFDEF HEAP_STRING_FIELD}
  1033. FinalizeCacheBuffer(FOldBufferCache, FOldCacheSize);
  1034. {$ENDIF}
  1035. FreeMem(FOldBufferCache, 0);
  1036. FreeAndNil(FGeneratorField);
  1037. FOldBufferCache := nil;
  1038. FCacheSize := 0;
  1039. FOldCacheSize := 0;
  1040. FMappedFieldPosition := nil;
  1041. end;
  1042. inherited Destroy;
  1043. end;
  1044. function TIBCustomDataSet.AdjustCurrentRecord(Buffer: Pointer; GetMode: TGetMode):
  1045. TGetResult;
  1046. begin
  1047. while not IsVisible(Buffer) do
  1048. begin
  1049. if GetMode = gmPrior then
  1050. begin
  1051. Dec(FCurrentRecord);
  1052. if FCurrentRecord = -1 then
  1053. begin
  1054. result := grBOF;
  1055. exit;
  1056. end;
  1057. ReadRecordCache(FCurrentRecord, Buffer, False);
  1058. end
  1059. else
  1060. begin
  1061. Inc(FCurrentRecord);
  1062. if (FCurrentRecord = FRecordCount) then
  1063. begin
  1064. if (not FQSelect.EOF) and (FQSelect.Next <> nil) then
  1065. begin
  1066. FetchCurrentRecordToBuffer(FQSelect, FCurrentRecord, Buffer);
  1067. Inc(FRecordCount);
  1068. end
  1069. else
  1070. begin
  1071. //!!!
  1072. //FAggregatesObsolete := True;
  1073. //!!!
  1074. result := grEOF;
  1075. exit;
  1076. end;
  1077. end
  1078. else
  1079. ReadRecordCache(FCurrentRecord, Buffer, False);
  1080. end;
  1081. end;
  1082. result := grOK;
  1083. end;
  1084. procedure TIBCustomDataSet.ApplyUpdates;
  1085. var
  1086. CurBookmark: string;
  1087. Buffer: PRecordData;
  1088. CurUpdateTypes: TIBUpdateRecordTypes;
  1089. UpdateAction: TIBUpdateAction;
  1090. UpdateKind: TUpdateKind;
  1091. bRecordsSkipped: Boolean;
  1092. R: Boolean;
  1093. //TempCurrent: Integer;
  1094. Buff: PChar;
  1095. procedure GetUpdateKind;
  1096. begin
  1097. case Buffer^.rdCachedUpdateStatus of
  1098. cusModified:
  1099. UpdateKind := ukModify;
  1100. cusInserted:
  1101. UpdateKind := ukInsert;
  1102. else
  1103. UpdateKind := ukDelete;
  1104. end;
  1105. end;
  1106. procedure ResetBufferUpdateStatus;
  1107. begin
  1108. case Buffer^.rdCachedUpdateStatus of
  1109. cusModified:
  1110. begin
  1111. PRecordData(Buffer)^.rdUpdateStatus := usUnmodified;
  1112. PRecordData(Buffer)^.rdCachedUpdateStatus := cusUnmodified;
  1113. end;
  1114. cusInserted:
  1115. begin
  1116. PRecordData(Buffer)^.rdUpdateStatus := usUnmodified;
  1117. PRecordData(Buffer)^.rdCachedUpdateStatus := cusUnmodified;
  1118. end;
  1119. cusDeleted:
  1120. begin
  1121. PRecordData(Buffer)^.rdUpdateStatus := usDeleted;
  1122. PRecordData(Buffer)^.rdCachedUpdateStatus := cusUnmodified;
  1123. end;
  1124. end;
  1125. WriteRecordCache(PRecordData(Buffer)^.rdRecordNumber, Pointer(Buffer));
  1126. end;
  1127. procedure UpdateUsingOnUpdateRecord;
  1128. begin
  1129. UpdateAction := uaFail;
  1130. try
  1131. FOnUpdateRecord(Self, UpdateKind, UpdateAction);
  1132. except
  1133. on E: Exception do
  1134. begin
  1135. if (E is EDatabaseError) and Assigned(FOnUpdateError) then
  1136. FOnUpdateError(Self, EIBError(E), UpdateKind, UpdateAction);
  1137. if UpdateAction = uaFail then
  1138. raise;
  1139. end;
  1140. end;
  1141. end;
  1142. procedure UpdateUsingUpdateObject;
  1143. begin
  1144. UpdateAction := uaApply;
  1145. try
  1146. FUpdateObject.Apply(UpdateKind);
  1147. ResetBufferUpdateStatus;
  1148. except
  1149. on E: Exception do
  1150. begin
  1151. UpdateAction := uaFail;
  1152. if (E is EDatabaseError) and Assigned(FOnUpdateError) then
  1153. FOnUpdateError(Self, EIBError(E), UpdateKind, UpdateAction);
  1154. if UpdateAction = uaFail then
  1155. raise;
  1156. end;
  1157. end;
  1158. end;
  1159. procedure UpdateUsingInternalquery;
  1160. begin
  1161. try
  1162. case Buffer^.rdCachedUpdateStatus of
  1163. cusModified:
  1164. InternalPostRecord(FQModify, Buffer);
  1165. cusInserted:
  1166. InternalPostRecord(FQInsert, Buffer);
  1167. cusDeleted:
  1168. InternalDeleteRecord(FQDelete, Buffer);
  1169. end;
  1170. except
  1171. on E: EIBError do begin
  1172. UpdateAction := uaFail;
  1173. if Assigned(FOnUpdateError) then
  1174. FOnUpdateError(Self, E, UpdateKind, UpdateAction);
  1175. case UpdateAction of
  1176. uaFail: raise;
  1177. uaAbort: SysUtils.Abort;
  1178. uaSkip: bRecordsSkipped := True;
  1179. end;
  1180. end;
  1181. end;
  1182. end;
  1183. begin
  1184. if State in [dsEdit, dsInsert] then
  1185. Post;
  1186. FBase.CheckDatabase;
  1187. //!!!
  1188. //FBase.CheckTransaction;
  1189. //!!!
  1190. DisableControls;
  1191. CurBookmark := Bookmark;
  1192. CurUpdateTypes := FUpdateRecordTypes;
  1193. FUpdateRecordTypes := [cusModified, cusInserted, cusDeleted];
  1194. try
  1195. First;
  1196. bRecordsSkipped := False;
  1197. while not EOF do
  1198. begin
  1199. Buffer := PRecordData(GetActiveBuf);
  1200. GetUpdateKind;
  1201. UpdateAction := uaApply;
  1202. if Assigned(FUpdateObject) or Assigned(FOnUpdateRecord) then
  1203. begin
  1204. if (Assigned(FOnUpdateRecord)) then
  1205. UpdateUsingOnUpdateRecord
  1206. else
  1207. if Assigned(FUpdateObject) then
  1208. UpdateUsingUpdateObject;
  1209. case UpdateAction of
  1210. uaFail:
  1211. IBError(ibxeUserAbort, [nil]);
  1212. uaAbort:
  1213. SysUtils.Abort;
  1214. uaApplied:
  1215. ResetBufferUpdateStatus;
  1216. uaSkip:
  1217. bRecordsSkipped := True;
  1218. uaRetry:
  1219. Continue;
  1220. end;
  1221. end;
  1222. if (not Assigned(FUpdateObject)) and (UpdateAction = UaApply) then
  1223. begin
  1224. UpdateUsingInternalquery;
  1225. UpdateAction := uaApplied;
  1226. end;
  1227. Next;
  1228. end;
  1229. FUpdatesPending := bRecordsSkipped;
  1230. finally
  1231. FUpdateRecordTypes := CurUpdateTypes;
  1232. if BookmarkValid(Pointer(CurBookmark)) then
  1233. begin
  1234. {TempCurrent := FCurrentRecord;
  1235. FCurrentRecord := PInteger(CurBookmark)^;
  1236. Buff := ActiveBuffer;}
  1237. Buff := FBufferCache + _RecordBufferSize * PInteger(CurBookmark)^;
  1238. R := PRecordData(Buff)^.rdCachedUpdateStatus <> cusDeleted;
  1239. {FCurrentRecord := TempCurrent;}
  1240. if R then
  1241. Bookmark := CurBookmark
  1242. else
  1243. First;
  1244. end else
  1245. First;
  1246. EnableControls;
  1247. end;
  1248. end;
  1249. procedure TIBCustomDataSet.InternalBatchInput(InputObject: TIBBatchInput);
  1250. begin
  1251. FQSelect.BatchInput(InputObject);
  1252. end;
  1253. procedure TIBCustomDataSet.InternalBatchOutput(OutputObject: TIBBatchOutput);
  1254. var
  1255. Qry: TIBSQL;
  1256. begin
  1257. Qry := TIBSQL.Create(Self);
  1258. try
  1259. Qry.Database := FBase.Database;
  1260. Qry.Transaction := FBase.Transaction;
  1261. Qry.SQL.Assign(FQSelect.SQL);
  1262. Qry.BatchOutput(OutputObject);
  1263. finally
  1264. Qry.Free;
  1265. end;
  1266. end;
  1267. procedure TIBCustomDataSet.CancelUpdates;
  1268. var
  1269. CurUpdateTypes: TIBUpdateRecordTypes;
  1270. begin
  1271. if State in [dsEdit, dsInsert] then
  1272. Cancel;
  1273. if FCachedUpdates and FUpdatesPending then
  1274. begin
  1275. DisableControls;
  1276. CurUpdateTypes := UpdateRecordTypes;
  1277. UpdateRecordTypes := [cusModified, cusInserted, cusDeleted];
  1278. try
  1279. First;
  1280. while not EOF do
  1281. begin
  1282. if UpdateStatus = usInserted then
  1283. //!!!
  1284. begin
  1285. //!!!
  1286. RevertRecord;
  1287. //!!!
  1288. First;
  1289. end
  1290. //!!!
  1291. else
  1292. begin
  1293. RevertRecord;
  1294. Next;
  1295. end;
  1296. end;
  1297. finally
  1298. UpdateRecordTypes := CurUpdateTypes;
  1299. First;
  1300. FUpdatesPending := False;
  1301. EnableControls;
  1302. end;
  1303. end;
  1304. end;
  1305. procedure TIBCustomDataSet.ActivateConnection;
  1306. begin
  1307. if not Assigned(Database) then
  1308. IBError(ibxeDatabaseNotAssigned, [nil]);
  1309. if not Assigned(Transaction) then
  1310. IBError(ibxeTransactionNotAssigned, [nil]);
  1311. if not Database.Connected then Database.Open;
  1312. end;
  1313. function TIBCustomDataSet.ActivateTransaction: Boolean;
  1314. begin
  1315. Result := False;
  1316. if not Assigned(Transaction) then
  1317. IBError(ibxeTransactionNotAssigned, [nil]);
  1318. if not Transaction.Active then
  1319. begin
  1320. Result := True;
  1321. Transaction.StartTransaction;
  1322. end;
  1323. end;
  1324. procedure TIBCustomDataSet.DeactivateTransaction;
  1325. begin
  1326. if not Assigned(Transaction) then
  1327. IBError(ibxeTransactionNotAssigned, [nil]);
  1328. Transaction.CheckAutoStop;
  1329. end;
  1330. procedure TIBCustomDataSet.CheckDatasetClosed;
  1331. begin
  1332. if FOpen then
  1333. IBError(ibxeDatasetOpen, [nil]);
  1334. end;
  1335. procedure TIBCustomDataSet.CheckDatasetOpen;
  1336. begin
  1337. if not FOpen then
  1338. IBError(ibxeDatasetClosed, [nil]);
  1339. end;
  1340. procedure TIBCustomDataSet.CheckNotUniDirectional;
  1341. begin
  1342. if UniDirectional then
  1343. IBError(ibxeDataSetUniDirectional, [nil]);
  1344. end;
  1345. procedure TIBCustomDataSet.AdjustRecordOnInsert(Buffer: Pointer);
  1346. begin
  1347. with PRecordData(Buffer)^ do
  1348. if (State = dsInsert) and (not Modified) then
  1349. begin
  1350. rdRecordNumber := FRecordCount;
  1351. FCurrentRecord := FRecordCount;
  1352. end;
  1353. end;
  1354. function TIBCustomDataSet.CanEdit: Boolean;
  1355. var
  1356. Buff: PRecordData;
  1357. begin
  1358. Buff := PRecordData(GetActiveBuf);
  1359. result := ((FQModify.SQL.Text <> '') and (lmModify in FLiveMode)) or
  1360. (Assigned(FUpdateObject) and (FUpdateObject.GetSQL(ukModify).Text <> '')) or
  1361. ((Buff <> nil) and (Buff^.rdCachedUpdateStatus = cusInserted) and
  1362. (FCachedUpdates));
  1363. end;
  1364. function TIBCustomDataSet.CanInsert: Boolean;
  1365. begin
  1366. result := ((FQInsert.SQL.Text <> '') and (lmInsert in FLiveMode)) or
  1367. (Assigned(FUpdateObject) and (FUpdateObject.GetSQL(ukInsert).Text <> ''));
  1368. end;
  1369. function TIBCustomDataSet.CanDelete: Boolean;
  1370. begin
  1371. if ((FQDelete.SQL.Text <> '') and (lmDelete in FLiveMode)) or
  1372. (Assigned(FUpdateObject) and (FUpdateObject.GetSQL(ukDelete).Text <> '')) then
  1373. result := True
  1374. else
  1375. result := False;
  1376. end;
  1377. function TIBCustomDataSet.CanRefresh: Boolean;
  1378. begin
  1379. result := ((FQRefresh.SQL.Text <> '') and (lmRefresh in FLiveMode)) or
  1380. (Assigned(FUpdateObject) and (FUpdateObject.RefreshSQL.Text <> ''));
  1381. end;
  1382. procedure TIBCustomDataSet.CheckEditState;
  1383. begin
  1384. case State of
  1385. { Check all the wsEditMode types }
  1386. dsEdit, dsInsert, dsSetKey, dsCalcFields, dsFilter,
  1387. dsNewValue, dsInternalCalc :
  1388. begin
  1389. if (State in [dsEdit]) and (not CanEdit) then
  1390. IBError(ibxeCannotUpdate, [nil]);
  1391. if (State in [dsInsert]) and (not CanInsert) then
  1392. IBError(ibxeCannotInsert, [nil]);
  1393. end;
  1394. else
  1395. IBError(ibxeNotEditing, [])
  1396. end;
  1397. end;
  1398. procedure TIBCustomDataSet.ClearBlobCache;
  1399. var
  1400. i: Integer;
  1401. begin
  1402. for i := 0 to FBlobStreamList.Count - 1 do
  1403. begin
  1404. TIBBlobStream(FBlobStreamList[i]).Free;
  1405. FBlobStreamList[i] := nil;
  1406. end;
  1407. FBlobStreamList.Pack;
  1408. end;
  1409. procedure TIBCustomDataSet.CopyRecordBuffer(Source, Dest: Pointer);
  1410. begin
  1411. {$IFDEF HEAP_STRING_FIELD}
  1412. if Source <> Dest then
  1413. FinalizeRecordBuffer(Dest);
  1414. {$ENDIF}
  1415. Move(Source^, Dest^, FRecordBufferSize);
  1416. {$IFDEF HEAP_STRING_FIELD}
  1417. InitializeRecordBuffer(Source, Dest);
  1418. {$ENDIF}
  1419. end;
  1420. procedure TIBCustomDataSet.DoBeforeDatabaseDisconnect(Sender: TObject);
  1421. begin
  1422. if Active then
  1423. Active := False;
  1424. FInternalPrepared := False;
  1425. if Assigned(FBeforeDatabaseDisconnect) then
  1426. FBeforeDatabaseDisconnect(Sender);
  1427. end;
  1428. procedure TIBCustomDataSet.DoAfterDatabaseDisconnect(Sender: TObject);
  1429. begin
  1430. if Assigned(FAfterDatabaseDisconnect) then
  1431. FAfterDatabaseDisconnect(Sender);
  1432. end;
  1433. procedure TIBCustomDataSet.DoDatabaseFree(Sender: TObject);
  1434. begin
  1435. if Assigned(FDatabaseFree) then
  1436. FDatabaseFree(Sender);
  1437. end;
  1438. procedure TIBCustomDataSet.DoBeforeTransactionEnd(Sender: TObject);
  1439. begin
  1440. {if Active then
  1441. Active := False;}
  1442. {if FQSelect <> nil then
  1443. FQSelect.FreeHandle;}
  1444. if FQDelete <> nil then
  1445. try
  1446. FQDelete.FreeHandle;
  1447. except
  1448. end;
  1449. if FQInsert <> nil then
  1450. try
  1451. FQInsert.FreeHandle;
  1452. except
  1453. end;
  1454. if FQModify <> nil then
  1455. try
  1456. FQModify.FreeHandle;
  1457. except
  1458. end;
  1459. {if FQRefresh <> nil then
  1460. FQRefresh.FreeHandle;}
  1461. {FInternalPrepared := false;}
  1462. if Assigned(FBeforeTransactionEnd) then
  1463. FBeforeTransactionEnd(Sender);
  1464. end;
  1465. procedure TIBCustomDataSet.DoAfterTransactionEnd(Sender: TObject);
  1466. begin
  1467. if Assigned(FAfterTransactionEnd) then
  1468. FAfterTransactionEnd(Sender);
  1469. end;
  1470. procedure TIBCustomDataSet.DoTransactionFree(Sender: TObject);
  1471. begin
  1472. if Assigned(FTransactionFree) then
  1473. FTransactionFree(Sender);
  1474. end;
  1475. { Read the record from FQSelect.Current into the record buffer
  1476. Then write the buffer to in memory cache }
  1477. procedure TIBCustomDataSet.FetchCurrentRecordToBuffer(Qry: TIBSQL;
  1478. RecordNumber: Integer; Buffer: PChar);
  1479. var
  1480. p: PRecordData;
  1481. pbd: PBlobDataArray;
  1482. i, j: Integer;
  1483. LocalData: Pointer;
  1484. LocalDate, LocalDouble: Double;
  1485. LocalInt: Integer;
  1486. LocalInt64: Int64;
  1487. LocalCurrency: Currency;
  1488. FieldsLoaded: Integer;
  1489. begin
  1490. {$IFDEF HEAP_STRING_FIELD}
  1491. FinalizeRecordBuffer(Buffer);
  1492. {$ENDIF}
  1493. p := PRecordData(Buffer);
  1494. { Make sure blob cache is empty }
  1495. pbd := PBlobDataArray(Buffer + FBlobCacheOffset);
  1496. if RecordNumber > -1 then
  1497. for i := 0 to BlobFieldCount - 1 do
  1498. pbd^[i] := nil;
  1499. { Get record information }
  1500. p^.rdBookmarkFlag := bfCurrent;
  1501. p^.rdFieldCount := Qry.Current.Count;
  1502. p^.rdRecordNumber := RecordNumber;
  1503. p^.rdUpdateStatus := usUnmodified;
  1504. p^.rdCachedUpdateStatus := cusUnmodified;
  1505. p^.rdSavedOffset := $FFFFFFFF;
  1506. { Load up the fields }
  1507. FieldsLoaded := FQSelect.Current.Count;
  1508. j := 1;
  1509. for i := 0 to Qry.Current.Count - 1 do
  1510. begin
  1511. if (Qry = FQSelect) then
  1512. j := i + 1
  1513. else begin
  1514. if FieldsLoaded = 0 then
  1515. break;
  1516. j := FQSelect.FieldIndex[Qry.Current[i].Name] + 1;
  1517. if j < 1 then
  1518. continue
  1519. else
  1520. Dec(FieldsLoaded);
  1521. end;
  1522. with FQSelect.Current[j - 1].Data^ do
  1523. if aliasname = 'IBX_INTERNAL_DBKEY' then {do not localize}
  1524. begin
  1525. if sqllen <= 8 then
  1526. p^.rdDBKey := PIBDBKEY(Qry.Current[i].AsPointer)^;
  1527. continue;
  1528. end;
  1529. if j > 0 then with p^ do
  1530. begin
  1531. rdFields[j].fdDataType :=
  1532. Qry.Current[i].Data^.sqltype and (not 1);
  1533. rdFields[j].fdDataScale :=
  1534. Qry.Current[i].Data^.sqlscale;
  1535. rdFields[j].fdNullable :=
  1536. (Qry.Current[i].Data^.sqltype and 1 = 1);
  1537. rdFields[j].fdIsNull :=
  1538. (rdFields[j].fdNullable and (Qry.Current[i].Data^.sqlind^ = -1));
  1539. LocalData := Qry.Current[i].Data^.sqldata;
  1540. case rdFields[j].fdDataType of
  1541. SQL_TIMESTAMP:
  1542. begin
  1543. rdFields[j].fdDataSize := SizeOf(TDateTime);
  1544. if RecordNumber >= 0 then
  1545. LocalDate := TimeStampToMSecs(DateTimeToTimeStamp(Qry.Current[i].AsDateTime));
  1546. LocalData := PChar(@LocalDate);
  1547. end;
  1548. SQL_TYPE_DATE:
  1549. begin
  1550. rdFields[j].fdDataSize := SizeOf(TDateTime);
  1551. if RecordNumber >= 0 then
  1552. LocalInt := DateTimeToTimeStamp(Qry.Current[i].AsDateTime).Date;
  1553. LocalData := PChar(@LocalInt);
  1554. end;
  1555. SQL_TYPE_TIME:
  1556. begin
  1557. rdFields[j].fdDataSize := SizeOf(TDateTime);
  1558. if RecordNumber >= 0 then
  1559. LocalInt := DateTimeToTimeStamp(Qry.Current[i].AsDateTime).Time;
  1560. LocalData := PChar(@LocalInt);
  1561. end;
  1562. SQL_SHORT, SQL_LONG:
  1563. begin
  1564. if (rdFields[j].fdDataScale = 0) then
  1565. begin
  1566. rdFields[j].fdDataSize := SizeOf(Integer);
  1567. if RecordNumber >= 0 then
  1568. LocalInt := Qry.Current[i].AsLong;
  1569. LocalData := PChar(@LocalInt);
  1570. end
  1571. else if (rdFields[j].fdDataScale >= (-4)) then
  1572. begin
  1573. rdFields[j].fdDataSize := SizeOf(Currency);
  1574. if RecordNumber >= 0 then
  1575. LocalCurrency := Qry.Current[i].AsCurrency;
  1576. LocalData := PChar(@LocalCurrency);
  1577. end
  1578. else begin
  1579. rdFields[j].fdDataSize := SizeOf(Double);
  1580. if RecordNumber >= 0 then
  1581. LocalDouble := Qry.Current[i].AsDouble;
  1582. LocalData := PChar(@LocalDouble);
  1583. end;
  1584. end;
  1585. SQL_INT64:
  1586. begin
  1587. if (rdFields[j].fdDataScale = 0) then
  1588. begin
  1589. rdFields[j].fdDataSize := SizeOf(Int64);
  1590. if RecordNumber >= 0 then
  1591. LocalInt64 := Qry.Current[i].AsInt64;
  1592. LocalData := PChar(@LocalInt64);
  1593. end
  1594. else if (rdFields[j].fdDataScale >= (-4)) then
  1595. begin
  1596. rdFields[j].fdDataSize := SizeOf(Currency);
  1597. if RecordNumber >= 0 then
  1598. LocalCurrency := Qry.Current[i].AsCurrency;
  1599. LocalData := PChar(@LocalCurrency);
  1600. end
  1601. else begin
  1602. rdFields[j].fdDataSize := SizeOf(Double);
  1603. if RecordNumber >= 0 then
  1604. LocalDouble := Qry.Current[i].AsDouble;
  1605. LocalData := PChar(@LocalDouble);
  1606. end
  1607. end;
  1608. SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT:
  1609. begin
  1610. rdFields[j].fdDataSize := SizeOf(Double);
  1611. if RecordNumber >= 0 then
  1612. LocalDouble := Qry.Current[i].AsDouble;
  1613. LocalData := PChar(@LocalDouble);
  1614. end;
  1615. SQL_VARYING:
  1616. begin
  1617. rdFields[j].fdDataSize := Qry.Current[i].Data^.sqllen;
  1618. rdFields[j].fdDataLength := isc_vax_integer(Qry.Current[i].Data^.sqldata, 2);
  1619. if RecordNumber >= 0 then
  1620. begin
  1621. if (rdFields[j].fdDataLength = 0) then
  1622. LocalData := nil
  1623. else
  1624. LocalData := @Qry.Current[i].Data^.sqldata[2];
  1625. end;
  1626. end;
  1627. else { SQL_TEXT, SQL_BLOB, SQL_ARRAY, SQL_QUAD }
  1628. begin
  1629. rdFields[j].fdDataSize := Qry.Current[i].Data^.sqllen;
  1630. if (rdFields[j].fdDataType = SQL_TEXT) then
  1631. rdFields[j].fdDataLength := rdFields[j].fdDataSize;
  1632. end;
  1633. end;
  1634. if RecordNumber < 0 then
  1635. begin
  1636. {$IFDEF HEAP_STRING_FIELD}
  1637. rdFields[j].fdIsNull := True;
  1638. if IsHeapField(rdFields[j]) then
  1639. begin
  1640. rdFields[j].fdDataOfs := 0;
  1641. rdFields[j].fdDataLength := 0;
  1642. end else begin
  1643. rdFields[j].fdDataOfs := FRecordSize;
  1644. Inc(FRecordSize, rdFields[j].fdDataSize);
  1645. end;
  1646. {$ELSE}
  1647. rdFields[j].fdIsNull := True;
  1648. rdFields[j].fdDataOfs := FRecordSize;
  1649. Inc(FRecordSize, rdFields[j].fdDataSize);
  1650. {$ENDIF}
  1651. end
  1652. else begin
  1653. if rdFields[j].fdDataType = SQL_VARYING then
  1654. begin
  1655. {$IFDEF HEAP_STRING_FIELD}
  1656. if IsHeapField(rdFields[j]) then
  1657. begin
  1658. if LocalData <> nil then
  1659. begin
  1660. GetMem(Pointer(rdFields[j].fdDataOfs), rdFields[j].fdDataLength);
  1661. Move(LocalData^, Pointer(rdFields[j].fdDataOfs)^, rdFields[j].fdDataLength);
  1662. end else
  1663. rdFields[j].fdDataOfs := 0;
  1664. end else
  1665. {$ENDIF}
  1666. if LocalData <> nil then
  1667. Move(LocalData^, Buffer[rdFields[j].fdDataOfs], rdFields[j].fdDataLength)
  1668. end
  1669. else
  1670. Move(LocalData^, Buffer[rdFields[j].fdDataOfs], rdFields[j].fdDataSize)
  1671. end;
  1672. end;
  1673. end;
  1674. WriteRecordCache(RecordNumber, PChar(p));
  1675. end;
  1676. function TIBCustomDataSet.GetActiveBuf: PChar;
  1677. begin
  1678. //!!!
  1679. if FPeekBuffer <> nil then
  1680. Result := FPeekBuffer
  1681. else
  1682. //!!!
  1683. case State of
  1684. dsBrowse:
  1685. if IsEmpty then
  1686. result := nil
  1687. else
  1688. result := ActiveBuffer;
  1689. dsEdit, dsInsert:
  1690. result := ActiveBuffer;
  1691. dsCalcFields:
  1692. result := CalcBuffer;
  1693. dsFilter:
  1694. result := FFilterBuffer;
  1695. dsNewValue:
  1696. result := ActiveBuffer;
  1697. dsOldValue:
  1698. if (PRecordData(ActiveBuffer)^.rdRecordNumber =
  1699. PRecordData(FOldBuffer)^.rdRecordNumber) then
  1700. result := FOldBuffer
  1701. else
  1702. result := ActiveBuffer;
  1703. else if not FOpen then
  1704. result := nil
  1705. else
  1706. result := ActiveBuffer;
  1707. end;
  1708. end;
  1709. function TIBCustomDataSet.CachedUpdateStatus: TCachedUpdateStatus;
  1710. begin
  1711. if Active then
  1712. result := PRecordData(GetActiveBuf)^.rdCachedUpdateStatus
  1713. else
  1714. result := cusUnmodified;
  1715. end;
  1716. function TIBCustomDataSet.GetDatabase: TIBDatabase;
  1717. begin
  1718. result := FBase.Database;
  1719. end;
  1720. function TIBCustomDataSet.GetDBHandle: PISC_DB_HANDLE;
  1721. begin
  1722. result := FBase.DBHandle;
  1723. end;
  1724. function TIBCustomDataSet.GetDeleteSQL: TStrings;
  1725. begin
  1726. result := FQDelete.SQL;
  1727. end;
  1728. function TIBCustomDataSet.GetInsertSQL: TStrings;
  1729. begin
  1730. result := FQInsert.SQL;
  1731. end;
  1732. function TIBCustomDataSet.GetSQLParams: TIBXSQLDA;
  1733. begin
  1734. if not FInternalPrepared then
  1735. InternalPrepare;
  1736. result := FQSelect.Params;
  1737. end;
  1738. function TIBCustomDataSet.GetRefreshSQL: TStrings;
  1739. begin
  1740. result := FQRefresh.SQL;
  1741. end;
  1742. function TIBCustomDataSet.GetSelectSQL: TStrings;
  1743. begin
  1744. result := FQSelect.SQL;
  1745. end;
  1746. function TIBCustomDataSet.GetStatementType: TIBSQLTypes;
  1747. begin
  1748. result := FQSelect.SQLType;
  1749. end;
  1750. function TIBCustomDataSet.GetModifySQL: TStrings;
  1751. begin
  1752. result := FQModify.SQL;
  1753. end;
  1754. function TIBCustomDataSet.GetTransaction: TIBTransaction;
  1755. begin
  1756. result := FBase.Transaction;
  1757. end;
  1758. function TIBCustomDataSet.GetTRHandle: PISC_TR_HANDLE;
  1759. begin
  1760. result := FBase.TRHandle;
  1761. end;
  1762. procedure TIBCustomDataSet.InternalDeleteRecord(Qry: TIBSQL; Buff: Pointer);
  1763. //!!!
  1764. var
  1765. DidActivate: Boolean;
  1766. //!!!
  1767. begin
  1768. //!!!
  1769. if not FDataTransfer then
  1770. begin
  1771. //!!!
  1772. if (Assigned(FUpdateObject) and (FUpdateObject.GetSQL(ukDelete).Text <> '')) then
  1773. FUpdateObject.Apply(ukDelete)
  1774. else
  1775. begin
  1776. //!!!
  1777. DidActivate := False;
  1778. try
  1779. DidActivate := ActivateTransaction;
  1780. try
  1781. if Assigned(FBeforeInternalDeleteRecord) then
  1782. FBeforeInternalDeleteRecord(Self);
  1783. //!!!
  1784. SetInternalSQLParams(FQDelete, Buff);
  1785. FQDelete.ExecQuery;
  1786. FRowsAffected := FQDelete.RowsAffected;
  1787. //!!!
  1788. if Assigned(FAfterInternalDeleteRecord) then
  1789. FAfterInternalDeleteRecord(Self);
  1790. except
  1791. if DidActivate and AllowCloseTransaction then
  1792. Transaction.Rollback;
  1793. raise;
  1794. end;
  1795. finally
  1796. if DidActivate and AllowCloseTransaction then
  1797. Transaction.Commit;
  1798. end;
  1799. //!!!
  1800. end;
  1801. //!!!
  1802. end;
  1803. //!!!
  1804. with PRecordData(Buff)^ do
  1805. begin
  1806. rdUpdateStatus := usDeleted;
  1807. rdCachedUpdateStatus := cusUnmodified;
  1808. end;
  1809. WriteRecordCache(PRecordData(Buff)^.rdRecordNumber, Buff);
  1810. end;
  1811. function TIBCustomDataSet.InternalLocate(const KeyFields: string;
  1812. const KeyValues: Variant; Options: TLocateOptions): Boolean;
  1813. var
  1814. fl: TList;
  1815. CurBookmark: string;
  1816. fld : Variant;
  1817. val : Array of Variant;
  1818. i, fld_cnt: Integer;
  1819. fld_str : String;
  1820. begin
  1821. fl := TList.Create;
  1822. try
  1823. GetFieldList(fl, KeyFields);
  1824. fld_cnt := fl.Count;
  1825. CurBookmark := Bookmark;
  1826. result := False;
  1827. SetLength(val, fld_cnt);
  1828. if not Eof then
  1829. for i := 0 to fld_cnt - 1 do
  1830. begin
  1831. if VarIsArray(KeyValues) then
  1832. val[i] := KeyValues[i]
  1833. else
  1834. val[i] := KeyValues;
  1835. if (TField(fl[i]).DataType = ftString) and
  1836. not VarIsNull(val[i]) then
  1837. begin
  1838. if (loCaseInsensitive in Options) then
  1839. val[i] := AnsiUpperCase(val[i]);
  1840. end;
  1841. end;
  1842. while ((not result) and (not Eof)) do
  1843. begin
  1844. i := 0;
  1845. result := True;
  1846. while (result and (i < fld_cnt)) do
  1847. begin
  1848. fld := TField(fl[i]).Value;
  1849. if VarIsNull(fld) then
  1850. result := result and VarIsNull(val[i])
  1851. else
  1852. begin
  1853. // We know the Field is not null so if the passed value is null we are
  1854. // done with this record
  1855. result := result and not VarIsNull(val[i]);
  1856. if result then
  1857. begin
  1858. try
  1859. fld := VarAsType(fld, VarType(val[i]));
  1860. except
  1861. on E: EVariantError do result := False;
  1862. end;
  1863. if TField(fl[i]).DataType = ftString then
  1864. begin
  1865. fld_str := TField(fl[i]).AsString;
  1866. if (loCaseInsensitive in Options) then
  1867. fld_str := AnsiUpperCase(fld_str);
  1868. if (loPartialKey in Options) then
  1869. result := result and (AnsiPos(val[i], fld_str) = 1)
  1870. else
  1871. result := result and (f