interbase.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. {
  2. $Id$
  3. Copyright (c) 2000 by Pavel Stingl
  4. Interbase database & dataset
  5. Roughly based on work of FPC development team,
  6. especially Michael Van Canneyt
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit interbase;
  14. {$H+}
  15. interface
  16. uses SysUtils, Classes, ibase60, Db;
  17. type
  18. PInteger = ^integer;
  19. TIBDatabase = class (TDatabase)
  20. private
  21. FIBDatabaseHandle : pointer;
  22. FIBTransactionHandle : pointer;
  23. FPassword : string;
  24. FStatus : array [0..19] of ISC_STATUS;
  25. FUserName : string;
  26. procedure CheckError(ProcName : string);
  27. protected
  28. procedure DoInternalConnect; override;
  29. procedure DoInternalDisconnect; override;
  30. public
  31. constructor Create(AOwner : TComponent); override;
  32. procedure CommitTransaction; virtual;
  33. procedure RollbackTransaction; virtual;
  34. procedure StartTransaction; override;
  35. procedure EndTransaction; override;
  36. property DatabaseHandle: pointer read FIBDatabaseHandle;
  37. property TransactionHandle: pointer read FIBTransactionHandle;
  38. published
  39. property Password: string read FPassword write FPassword;
  40. property UserName: string read FUserName write FUserName;
  41. property Connected;
  42. property DatabaseName;
  43. property KeepConnection;
  44. property LoginPrompt;
  45. property Params;
  46. property OnLogin;
  47. end;
  48. PIBBookmark = ^TIBBookmark;
  49. TIBBookmark = record
  50. BookmarkData: Integer;
  51. BookmarkFlag: TBookmarkFlag;
  52. end;
  53. // TStatementType indicates if SQL statement returns
  54. // result set.
  55. TStatementType = (stResult, stNoResult, stDDL);
  56. TIBDataset = class (TDataset)
  57. private
  58. FBufferSize : longint;
  59. FCurrentRecord : longint;
  60. FCurrStmtType : TStatementType;
  61. FDatabase : TIBDatabase;
  62. FFlag : array [0..1024] of shortint;
  63. FIsEOF : boolean;
  64. FLoadingFieldDefs : boolean;
  65. FSQLPrepared : boolean;
  66. FRecordSize : word;
  67. FRecordCount : integer;
  68. FSQL : TStrings;
  69. FSQLDA : PXSQLDA;
  70. FSQLDAAllocated : longint;
  71. FStatementHandle : pointer;
  72. FStatus : array [0..19] of ISC_STATUS;
  73. FDBHandle : pointer;
  74. FTRHandle : pointer;
  75. procedure CheckError(ProcName : string);
  76. procedure DoAssignBuffers;
  77. procedure DoExecSQL;
  78. procedure DoFetch;
  79. procedure DoFreeBuffers;
  80. procedure DoParseSQL;
  81. procedure DoSQLDAAlloc(Count : longint);
  82. procedure DoStmtAlloc;
  83. procedure DoStmtDealloc;
  84. procedure SetBufExtended(Field : TField; CurrBuff,Buffer : pointer);
  85. procedure SetBufInteger(Field : TField; CurrBuff,Buffer : pointer);
  86. procedure SetBufDateTime(Field : TField; CurrBuff,Buffer : pointer; AType : integer);
  87. procedure SetBufString(Field : TField; CurrBuff,Buffer : pointer);
  88. function GetStmtType: TStatementType;
  89. function LoadBufferFromData(Buffer : PChar): TGetResult;
  90. procedure SetDatabase(Value : TIBDatabase);
  91. procedure SetSizes;
  92. procedure TranslateFieldType(AType, AScale: longint;
  93. var XType: TFieldType; var XScale: word);
  94. protected
  95. function AllocRecordBuffer: PChar; override;
  96. procedure FreeRecordBuffer(var Buffer: PChar); override;
  97. procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
  98. function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
  99. function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
  100. function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult; override;
  101. function GetRecordSize: Word; override;
  102. function GetRecordCount: integer; override;
  103. procedure InternalAddRecord(Buffer: Pointer; AAppend: Boolean); override;
  104. procedure InternalClose; override;
  105. procedure InternalDelete; override;
  106. procedure InternalFirst; override;
  107. procedure InternalGotoBookmark(ABookmark: Pointer); override;
  108. procedure InternalHandleException; override;
  109. procedure InternalInitFieldDefs; override;
  110. procedure InternalInitRecord(Buffer: PChar); override;
  111. procedure InternalLast; override;
  112. procedure InternalOpen; override;
  113. procedure InternalPost; override;
  114. procedure InternalSetToRecord(Buffer: PChar); override;
  115. function IsCursorOpen: Boolean; override;
  116. procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
  117. procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
  118. procedure SetFieldData(Field: TField; Buffer: Pointer); override;
  119. public
  120. constructor Create(AOwner : TComponent); override;
  121. destructor Destroy; override;
  122. published
  123. property SQL : TStrings read FSQL write FSQL;
  124. property Database : TIBDatabase read FDatabase write SetDatabase;
  125. end;
  126. implementation
  127. type
  128. TTm = packed record
  129. tm_sec : longint;
  130. tm_min : longint;
  131. tm_hour : longint;
  132. tm_mday : longint;
  133. tm_mon : longint;
  134. tm_year : longint;
  135. tm_wday : longint;
  136. tm_yday : longint;
  137. tm_isdst : longint;
  138. __tm_gmtoff : longint;
  139. __tm_zone : Pchar;
  140. end;
  141. ///////////////////////////////////////////////////////////////////////
  142. // TIBDatabase implementation
  143. //
  144. // PRIVATE PART of TIBDatabase
  145. {---------------------------------------------------------------------}
  146. { CheckError }
  147. { This procedure checks IB status vector and, if found some error }
  148. { condition, raises exception with IB error text }
  149. {---------------------------------------------------------------------}
  150. procedure TIBDatabase.CheckError(ProcName:string);
  151. var
  152. buf : array [0..1024] of char;
  153. P : pointer;
  154. x : integer;
  155. begin
  156. if ((FStatus[0] = 1) and (FStatus[1] <> 0)) then
  157. begin
  158. p := @FStatus;
  159. isc_interprete(Buf, @p);
  160. raise Exception.Create(ProcName + ': ' + StrPas(buf));
  161. end;
  162. end;
  163. // PROTECTED PART of TIBDatabase
  164. procedure TIBDatabase.DoInternalConnect;
  165. var
  166. DPB : string;
  167. begin
  168. if Connected then
  169. Close;
  170. DPB := chr(isc_dpb_version1);
  171. if (FUserName <> '') then
  172. begin
  173. DPB := DPB + chr(isc_dpb_user_name) + chr(Length(FUserName)) + FUserName;
  174. if (FPassword <> '') then
  175. DPB := DPB + chr(isc_dpb_password) + chr(Length(FPassword)) + FPassword;
  176. end;
  177. if (DatabaseName = '') then
  178. raise Exception.Create('TIBDatabase.Open: Database connect string not filled in!');
  179. FIBDatabaseHandle := nil;
  180. if isc_attach_database(@FStatus, Length(DatabaseName), @DatabaseName[1], @FIBDatabaseHandle,
  181. Length(DPB), @DPB[1]) <> 0 then
  182. CheckError('TIBDatabase.Open');
  183. end;
  184. procedure TIBDatabase.DoInternalDisconnect;
  185. begin
  186. if not Connected then
  187. begin
  188. FIBDatabaseHandle := nil;
  189. Exit;
  190. end;
  191. isc_detach_database(@FStatus[0], @FIBDatabaseHandle);
  192. CheckError('TIBDatabase.Close');
  193. end;
  194. // PUBLIC PART of TIBDatabase
  195. constructor TIBDatabase.Create(AOwner : TComponent);
  196. begin
  197. inherited Create(AOwner);
  198. FIBDatabaseHandle := nil;
  199. FIBTransactionHandle := nil;
  200. FUserName := '';
  201. FPassword := '';
  202. end;
  203. procedure TIBDatabase.CommitTransaction;
  204. begin
  205. if FIBTransactionHandle <> nil then
  206. if isc_commit_retaining(@FStatus, @FIBTransactionHandle) <> 0 then
  207. CheckError('TIBDatabase.CommitTransaction');
  208. end;
  209. procedure TIBDatabase.RollbackTransaction;
  210. begin
  211. if FIBTransactionHandle <> nil then
  212. if isc_rollback_retaining(@FStatus, FIBTransactionHandle) <> 0 then
  213. CheckError('TIBDatabase.RollbackTransaction');
  214. end;
  215. procedure TIBDatabase.StartTransaction;
  216. begin
  217. if FIBTransactionHandle = nil then
  218. begin
  219. if isc_start_transaction(@FStatus, @FIBTransactionHandle, 1, [@FIBDatabaseHandle, 0, nil]) <> 0 then
  220. CheckError('TIBDatabase.StartTransaction');
  221. end;
  222. end;
  223. procedure TIBDatabase.EndTransaction;
  224. begin
  225. if FIBTransactionHandle <> nil then
  226. begin
  227. if isc_commit_transaction(@FStatus, @FIBTransactionHandle) <> 0 then
  228. CheckError('TIBDatabase.EndTransaction');
  229. FIBTransactionHandle := nil;
  230. end;
  231. end;
  232. ///////////////////////////////////////////////////////////////////////
  233. // TIBDataset implementation
  234. //
  235. // PRIVATE PART
  236. procedure TIBDataset.CheckError(ProcName : string);
  237. var
  238. buf : array [0..1024] of char;
  239. P : pointer;
  240. Msg : string;
  241. x : integer;
  242. begin
  243. if ((FStatus[0] = 1) and (FStatus[1] <> 0)) then
  244. begin
  245. p := @FStatus;
  246. while isc_interprete(Buf, @p) > 0 do
  247. Msg := Msg + #10' -' + StrPas(Buf);
  248. raise Exception.Create(ProcName + ': ' + Msg);
  249. end;
  250. end;
  251. procedure TIBDataset.DoAssignBuffers;
  252. var
  253. Buf : PChar;
  254. x : longint;
  255. begin
  256. for x := 0 to FSQLDA^.SQLD - 1 do
  257. begin
  258. Buf := AllocMem(FSQLDA^.SQLVar[x].SQLLen);
  259. FSQLDA^.SQLVar[x].SQLData := Buf;
  260. FSQLDA^.SQLVar[x].SQLInd := @FFlag[x];
  261. end;
  262. end;
  263. procedure TIBDataset.DoExecSQL;
  264. begin
  265. if isc_dsql_execute(@FStatus, @FTrHandle, @FStatementHandle, 1, nil) <> 0 then
  266. CheckError('TIBDataset.DoExecSQL');
  267. end;
  268. procedure TIBDataset.DoFetch;
  269. var
  270. Res : longint;
  271. begin
  272. if FCurrStmtType <> stResult then Exit;
  273. Res := isc_dsql_fetch(@FStatus, @FStatementHandle, 1, FSQLDA);
  274. if (Res <> 100) then
  275. CheckError('TIBDataset.DoFetch');
  276. FIsEOF := (Res = 100);
  277. end;
  278. procedure TIBDataset.DoFreeBuffers;
  279. var
  280. x : longint;
  281. begin
  282. for x := 0 to FSQLDA^.SQLD - 1 do
  283. if (FSQLDA^.SQLVar[x].SQLData <> nil) then
  284. FreeMem(FSQLDA^.SQLVar[x].SQLData);
  285. end;
  286. procedure TIBDataset.DoParseSQL;
  287. var
  288. Buf : string;
  289. x : longint;
  290. begin
  291. if FSQL.Count < 1 then
  292. raise Exception.Create('TIBDataset.DoParseSQL: Empty SQL statement');
  293. Buf := '';
  294. for x := 0 to FSQL.Count - 1 do
  295. Buf := Buf + FSQL[x] + ' ';
  296. if isc_dsql_prepare(@FStatus, @FTrHandle, @FStatementHandle, 0, @Buf[1], 1, nil) <> 0 then CheckError('TIBDataset.DoParseSQL - Prepare');
  297. if isc_dsql_describe(@FStatus, @FStatementHandle, 1, FSQLDA) <> 0 then
  298. CheckError('TIBDataset.DoParseSQL - Describe');
  299. if FSQLDA^.SQLN < FSQLDA^.SQLD then
  300. begin
  301. x := FSQLDA^.SQLD;
  302. DoSQLDAAlloc(x);
  303. if isc_dsql_describe(@FStatus, @FStatementHandle, 1, FSQLDA) <> 0 then
  304. CheckError('TIBDataset.DoParseSQL - Describe');
  305. end;
  306. FCurrStmtType := GetStmtType;
  307. FSQLPrepared := True;
  308. end;
  309. procedure TIBDataset.DoSQLDAAlloc(Count : longint);
  310. begin
  311. if FSQLDAAllocated > 0 then
  312. FreeMem(FSQLDA, XSQLDA_Length * FSQLDAAllocated);
  313. GetMem(FSQLDA, XSQLDA_Length * Count);
  314. FSQLDAAllocated := Count;
  315. FSQLDA^.Version := SQLDA_VERSION1;
  316. FSQLDA^.SQLN := Count;
  317. end;
  318. procedure TIBDataset.DoStmtAlloc;
  319. begin
  320. if not FDatabase.Connected then
  321. FDatabase.Open;
  322. if FDatabase.TransactionHandle = nil then
  323. FDatabase.StartTransaction;
  324. FDBHandle := FDatabase.DatabaseHandle;
  325. FTRHandle := FDatabase.TransactionHandle;
  326. if isc_dsql_allocate_statement(@FStatus, @FDBHandle, @FStatementHandle) <> 0 then
  327. CheckError('TIBDataset.DoStmtAlloc');
  328. end;
  329. procedure TIBDataset.DoStmtDealloc;
  330. begin
  331. if isc_dsql_free_statement(@FStatus, @FStatementHandle, DSQL_Drop) <> 0 then
  332. CheckError('TIBDataset.DoStmtDealloc');
  333. FStatementHandle := nil;
  334. end;
  335. function TIBDataset.GetStmtType: TStatementType;
  336. var
  337. ResBuf : array [0..7] of char;
  338. x : integer;
  339. SType : integer;
  340. begin
  341. x := isc_info_sql_stmt_type;
  342. isc_dsql_sql_info(@FStatus, @FStatementHandle, SizeOf(x),
  343. @x, SizeOf(ResBuf), @ResBuf);
  344. if Ord(ResBuf[0]) = isc_info_sql_stmt_type then
  345. begin
  346. x := isc_vax_integer(@ResBuf[1], 2);
  347. SType := isc_vax_integer(@ResBuf[3], x);
  348. end;
  349. case SType of
  350. isc_info_sql_stmt_select:
  351. Result := stResult;
  352. isc_info_sql_stmt_insert, isc_info_sql_stmt_update,
  353. isc_info_sql_stmt_delete:
  354. Result := stNoResult;
  355. else Result := stDDL;
  356. end;
  357. end;
  358. function TIBDataset.LoadBufferFromData(Buffer : PChar): TGetResult;
  359. var
  360. x : integer;
  361. p : word;
  362. T : TISC_TIMESTAMP;
  363. begin
  364. DoFetch;
  365. if FIsEOF then
  366. Result := grEOF
  367. else begin
  368. for x := 0 to FSQLDA^.SQLD - 1 do
  369. begin
  370. if (FSQLDA^.SQLVar[x].SQLType = SQL_VARYING) or
  371. (FSQLDA^.SQLVar[x].SQLType = SQL_VARYING + 1) then
  372. begin
  373. Move(FSQLDA^.SQLVar[x].SQLData^, P, 2);
  374. Move((FSQLDA^.SQLVar[x].SQLData + 2)^, Buffer^, P);
  375. PChar(Buffer+P)^ := #0;
  376. end
  377. else
  378. Move(FSQLDA^.SQLVar[x].SQLData^, Buffer^, FSQLDA^.SQLVar[x].SQLLen);
  379. Inc(Buffer,FSQLDA^.SQLVar[x].SQLLen);
  380. end;
  381. Result := grOK;
  382. end;
  383. end;
  384. procedure TIBDataset.SetDatabase(Value : TIBDatabase);
  385. begin
  386. CheckInactive;
  387. If Value<>FDatabase then
  388. begin
  389. if Value<>Nil Then
  390. FDatabase:=Value;
  391. end;
  392. end;
  393. procedure TIBDataset.SetSizes;
  394. var
  395. x : integer;
  396. begin
  397. FRecordSize := 0;
  398. FBufferSize := 0;
  399. for x := 0 to FSQLDA^.SQLD - 1 do
  400. begin
  401. Inc(FRecordSize, FSQLDA^.SQLVar[x].SQLLen);
  402. end;
  403. FBufferSize := FRecordSize + SizeOf(TIBBookmark);
  404. end;
  405. procedure TIBDataset.TranslateFieldType(AType, AScale: longint;
  406. var XType: TFieldType; var XScale: word);
  407. begin
  408. case AType of
  409. SQL_TEXT, SQL_VARYING, SQL_TEXT+1, SQL_VARYING+1:
  410. begin
  411. XType := ftString;
  412. XScale := AScale;
  413. end;
  414. SQL_DOUBLE, SQL_DOUBLE+1:
  415. begin
  416. XType := ftFloat;
  417. XScale := AScale;
  418. end;
  419. SQL_LONG, SQL_LONG+1, SQL_SHORT, SQL_SHORT+1:
  420. begin
  421. XType := ftInteger;
  422. XScale := AScale;
  423. end;
  424. { SQL_DATE, SQL_DATE+1, SQL_TIME, SQL_TIME+1,}
  425. SQL_TYPE_TIME:
  426. begin
  427. XType := ftTime;
  428. XScale := AScale;
  429. end;
  430. SQL_TYPE_DATE:
  431. begin
  432. XType := ftDate;
  433. XScale := AScale;
  434. end;
  435. SQL_FLOAT,SQL_FLOAT+1:
  436. begin
  437. XType := ftFloat;
  438. XScale := AScale;
  439. end;
  440. SQL_TIMESTAMP, SQL_TIMESTAMP+1:
  441. begin
  442. XType := ftDateTime;
  443. XScale := AScale;
  444. end;
  445. end;
  446. end;
  447. // PROTECTED PART
  448. function TIBDataset.AllocRecordBuffer: PChar;
  449. begin
  450. Result := AllocMem(FBufferSize);
  451. end;
  452. procedure TIBDataset.FreeRecordBuffer(var Buffer: PChar);
  453. begin
  454. FreeMem(Buffer);
  455. end;
  456. procedure TIBDataset.GetBookmarkData(Buffer: PChar; Data: Pointer);
  457. begin
  458. PInteger(Data)^ := PIBBookmark(Buffer + FRecordSize)^.BookmarkData;
  459. end;
  460. function TIBDataset.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
  461. begin
  462. Result := PIBBookmark(Buffer + FRecordSize)^.BookmarkFlag;
  463. end;
  464. procedure TIBDataset.SetBufExtended(Field : TField; CurrBuff,Buffer : pointer);
  465. var
  466. E : extended;
  467. D : double;
  468. S : single;
  469. begin
  470. case Field.Size of
  471. 4 :
  472. begin
  473. Move(CurrBuff^,S,4);
  474. E := S;
  475. end;
  476. 8 :
  477. begin
  478. Move(CurrBuff^,D,8);
  479. E := D;
  480. end;
  481. 10 : Move(CurrBuff^,E,10);
  482. end;
  483. Move(E, Buffer^, 10);
  484. end;
  485. procedure TIBDataset.SetBufInteger(Field : TField; CurrBuff,Buffer : pointer);
  486. var
  487. I : integer;
  488. begin
  489. I := 0;
  490. Move(I, Buffer^, SizeOf(Integer));
  491. Move(CurrBuff^, Buffer^, Field.Size);
  492. end;
  493. procedure TIBDataset.SetBufDateTime(Field : TField; CurrBuff,Buffer : pointer; AType : integer);
  494. var
  495. D : TDateTime;
  496. S : TSystemTime;
  497. TM : TTm;
  498. TT : TIsc_timestamp;
  499. begin
  500. case AType of
  501. SQL_TYPE_DATE:
  502. isc_decode_sql_date(PISC_DATE(CurrBuff), @TM);
  503. SQL_TYPE_TIME:
  504. isc_decode_sql_time(PISC_TIME(CurrBuff), @TM);
  505. SQL_TIMESTAMP, SQL_TIMESTAMP+1:
  506. isc_decode_timestamp(PISC_TIMESTAMP(CurrBuff), @TM);
  507. end;
  508. S.Year := TM.tm_year + 1900;
  509. S.Month := TM.tm_mon + 1;
  510. S.Day := TM.tm_mday;
  511. S.Hour := TM.tm_hour;
  512. S.Minute := TM.tm_min;
  513. S.Second := TM.tm_sec;
  514. S.Millisecond := 0;
  515. D := SystemTimeToDateTime(S);
  516. {$warning !!! D is okay, but Field.AsDateTime returns wrong value !!! }
  517. // WriteLn(DateTimeToStr(D));
  518. Move(D, Buffer^, SizeOf(D));
  519. end;
  520. procedure TIBDataset.SetBufString(Field : TField; CurrBuff,Buffer : pointer);
  521. begin
  522. Move(CurrBuff^, Buffer^, Field.Size);
  523. PChar(Buffer + Field.Size)^ := #0;
  524. end;
  525. function TIBDataset.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
  526. var
  527. x : longint;
  528. CurrBuff : PChar;
  529. begin
  530. Result := False;
  531. CurrBuff := ActiveBuffer;
  532. for x := 0 to FSQLDA^.SQLD - 1 do
  533. begin
  534. if (Field.FieldName = FSQLDA^.SQLVar[x].SQLName) then
  535. begin
  536. case Field.DataType of
  537. ftFloat:
  538. SetBufExtended(Field, CurrBuff, Buffer);
  539. ftString:
  540. SetBufString(Field, CurrBuff, Buffer);
  541. ftDate,ftTime,ftDateTime:
  542. SetBufDateTime(Field, CurrBuff, Buffer, FSQLDA^.SQLVar[x].SQLType);
  543. ftInteger:
  544. SetBufInteger(Field, CurrBuff, Buffer);
  545. end;
  546. Result := True;
  547. break;
  548. end
  549. else Inc(CurrBuff, FSQLDA^.SQLVar[x].SQLLen);
  550. end;
  551. end;
  552. function TIBDataset.GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
  553. begin
  554. if FCurrStmtType <> stResult then Exit;
  555. if FIsEOF then
  556. Result := grEOF
  557. else begin
  558. Result := grOk;
  559. case GetMode of
  560. gmPrior:
  561. if FCurrentRecord <= 0 then
  562. begin
  563. Result := grBOF;
  564. FCurrentRecord := -1;
  565. end
  566. else Dec(FCurrentRecord);
  567. gmCurrent:
  568. if (FCurrentRecord < 0) or (FCurrentRecord >= RecordCount) then
  569. Result := grError;
  570. gmNext:
  571. if FCurrentRecord >= (RecordCount - 1) then
  572. begin
  573. Result := LoadBufferFromData(Buffer);
  574. if Result = grOk then
  575. begin
  576. Inc(FCurrentRecord);
  577. Inc(FRecordCount);
  578. end;
  579. end
  580. else Inc(FCurrentRecord);
  581. end;
  582. if Result = grOK then
  583. begin
  584. with PIBBookmark(Buffer + FRecordSize)^ do
  585. begin
  586. BookmarkData := FCurrentRecord;
  587. BookmarkFlag := bfCurrent;
  588. end;
  589. end
  590. else if (Result = grError) {and (DoCheck)} then
  591. DatabaseError('No record');
  592. end;
  593. end;
  594. function TIBDataset.GetRecordCount: integer;
  595. begin
  596. Result := FRecordCount;
  597. end;
  598. function TIBDataset.GetRecordSize: Word;
  599. begin
  600. Result := FRecordSize;
  601. end;
  602. procedure TIBDataset.InternalAddRecord(Buffer: Pointer; AAppend: Boolean);
  603. begin
  604. end;
  605. procedure TIBDataset.InternalClose;
  606. begin
  607. DoFreeBuffers;
  608. DoStmtDealloc;
  609. if DefaultFields then
  610. DestroyFields;
  611. FIsEOF := False;
  612. FCurrentRecord := -1;
  613. FBufferSize := 0;
  614. FRecordSize := 0;
  615. FRecordCount := 0;
  616. // DoSQLDAAlloc(50);
  617. end;
  618. procedure TIBDataset.InternalDelete;
  619. begin
  620. end;
  621. procedure TIBDataset.InternalFirst;
  622. begin
  623. FCurrentRecord := -1;
  624. end;
  625. procedure TIBDataset.InternalGotoBookmark(ABookmark: Pointer);
  626. begin
  627. FCurrentRecord := PInteger(ABookmark)^;
  628. end;
  629. procedure TIBDataset.InternalHandleException;
  630. begin
  631. // not implemented
  632. end;
  633. procedure TIBDataset.InternalInitFieldDefs;
  634. var
  635. x : longint;
  636. TransFt : TFieldType;
  637. TransSz : word;
  638. begin
  639. if FLoadingFieldDefs then
  640. begin
  641. WriteLn('Loading FieldDefs...');
  642. Exit;
  643. end;
  644. FLoadingFieldDefs := True;
  645. try
  646. try
  647. FieldDefs.Clear;
  648. for x := 0 to FSQLDA^.SQLD - 1 do
  649. begin
  650. TranslateFieldType(FSQLDA^.SQLVar[x].SQLType, FSQLDA^.SQLVar[x].SQLLen,
  651. TransFt, TransSz);
  652. TFieldDef.Create(FieldDefs,
  653. FSQLDA^.SQLVar[x].SQLName,
  654. TransFt, TransSz, False, (x+1));
  655. end;
  656. finally
  657. end;
  658. finally
  659. FLoadingFieldDefs := False;
  660. end;
  661. end;
  662. procedure TIBDataset.InternalInitRecord(Buffer: PChar);
  663. begin
  664. FillChar(Buffer^, FBufferSize, #0);
  665. end;
  666. procedure TIBDataset.InternalLast;
  667. begin
  668. FCurrentRecord := RecordCount;
  669. end;
  670. procedure TIBDataset.InternalOpen;
  671. begin
  672. try
  673. DoStmtAlloc;
  674. DoParseSQL;
  675. if FCurrStmtType = stResult then
  676. begin
  677. DoAssignBuffers;
  678. DoExecSQL;
  679. InternalInitFieldDefs;
  680. if DefaultFields then
  681. CreateFields;
  682. SetSizes;
  683. BindFields(True);
  684. end
  685. else DoExecSQL;
  686. except
  687. raise;
  688. end;
  689. end;
  690. procedure TIBDataset.InternalPost;
  691. begin
  692. end;
  693. procedure TIBDataset.InternalSetToRecord(Buffer: PChar);
  694. begin
  695. FCurrentRecord := PIBBookmark(Buffer + FRecordSize)^.BookmarkData;
  696. end;
  697. function TIBDataset.IsCursorOpen: Boolean;
  698. begin
  699. Result := FStatementHandle <> nil; //??
  700. end;
  701. procedure TIBDataset.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
  702. begin
  703. PIBBookmark(Buffer + FRecordSize)^.BookmarkFlag := Value;
  704. end;
  705. procedure TIBDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
  706. begin
  707. PIBBookmark(Buffer + FRecordSize)^.BookmarkData := PInteger(Data)^;
  708. end;
  709. procedure TIBDataset.SetFieldData(Field: TField; Buffer: Pointer);
  710. begin
  711. end;
  712. // PUBLIC PART
  713. constructor TIBDataset.Create(AOwner : TComponent);
  714. begin
  715. inherited Create(AOwner);
  716. FSQL := TStringList.Create;
  717. FIsEOF := False;
  718. FCurrentRecord := -1;
  719. FBufferSize := 0;
  720. FRecordSize := 0;
  721. FRecordCount := 0;
  722. DoSQLDAAlloc(50);
  723. end;
  724. destructor TIBDataset.Destroy;
  725. begin
  726. FSQL.Free;
  727. inherited Destroy;
  728. FreeMem(FSQLDA, XSQLDA_Length * FSQLDAAllocated);
  729. end;
  730. end.
  731. {
  732. $Log$
  733. Revision 1.1 2000-07-13 06:31:28 michael
  734. + Initial import
  735. Revision 1.1 2000/06/04 08:15:42 michael
  736. + Initial implementation in FCL
  737. Revision 1.1.1.1 2000/06/02 06:56:37 stingp1
  738. Initial release
  739. }