bufdataset.inc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Michael Van Canneyt, member of the
  5. Free Pascal development team
  6. BufDataset implementation
  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. { ---------------------------------------------------------------------
  14. TBufDataSet
  15. ---------------------------------------------------------------------}
  16. constructor TBufDataset.Create(AOwner : TComponent);
  17. begin
  18. Inherited Create(AOwner);
  19. SetLength(FUpdateBuffer,0);
  20. BookmarkSize := sizeof(TBufBookmark);
  21. // temporary set it here
  22. FPacketRecords := 10;
  23. end;
  24. destructor TBufDataset.Destroy;
  25. begin
  26. inherited destroy;
  27. end;
  28. Function TBufDataset.GetCanModify: Boolean;
  29. begin
  30. Result:= False;
  31. end;
  32. function TBufDataset.AllocRecordBuffer: PChar;
  33. begin
  34. result := AllocMem(FRecordsize + sizeof(TBufBookmark));
  35. result^ := #1; // this 'deletes' the record
  36. end;
  37. procedure TBufDataset.FreeRecordBuffer(var Buffer: PChar);
  38. begin
  39. ReAllocMem(Buffer,0);
  40. end;
  41. procedure TBufDataset.InternalOpen;
  42. begin
  43. CalcRecordSize;
  44. FBRecordcount := 0;
  45. FBDeletedRecords := 0;
  46. FBBuffercount := 0;
  47. FBCurrentrecord := -1;
  48. FOpen:=True;
  49. FIsEOF := false;
  50. FIsbOF := true;
  51. end;
  52. procedure TBufDataset.InternalClose;
  53. var i : integer;
  54. begin
  55. FOpen:=False;
  56. CancelUpdates;
  57. for i := 0 to FBRecordCount-1 do FreeRecordBuffer(FBBuffers[i]);
  58. If FBRecordCount > 0 then ReAllocMem(FBBuffers,0);
  59. FBRecordcount := 0;
  60. FBBuffercount := 0;
  61. FBCurrentrecord := -1;
  62. FIsEOF := true;
  63. FIsbOF := true;
  64. end;
  65. procedure TBufDataset.InternalFirst;
  66. begin
  67. FBCurrentRecord := -1;
  68. FIsEOF := false;
  69. end;
  70. procedure TBufDataset.InternalLast;
  71. begin
  72. repeat
  73. until getnextpacket < FPacketRecords;
  74. FIsBOF := false;
  75. FBCurrentRecord := FBRecordcount;
  76. end;
  77. procedure unSetDeleted(NullMask : pbyte); //inline;
  78. begin
  79. NullMask[0] := NullMask[0] and not 1;
  80. end;
  81. procedure SetDeleted(NullMask : pbyte); //inline;
  82. begin
  83. NullMask[0] := NullMask[0] or 1;
  84. end;
  85. function GetDeleted(NullMask : pbyte) : boolean; //inline;
  86. begin
  87. result := (NullMask[0] and 1) = 1;
  88. end;
  89. procedure unSetFieldIsNull(NullMask : pbyte;x : longint); //inline;
  90. begin
  91. inc(x);
  92. NullMask[x div 8] := (NullMask[x div 8]) and not (1 shl (x mod 8));
  93. end;
  94. procedure SetFieldIsNull(NullMask : pbyte;x : longint); //inline;
  95. begin
  96. inc(x);
  97. NullMask[x div 8] := (NullMask[x div 8]) or (1 shl (x mod 8));
  98. end;
  99. function GetFieldIsNull(NullMask : pbyte;x : longint) : boolean; //inline;
  100. begin
  101. inc(x);
  102. result := ord(NullMask[x div 8]) and (1 shl (x mod 8)) > 0
  103. end;
  104. function TBufDataset.GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
  105. var x : longint;
  106. RecUpdBuf : PRecUpdateBuffer;
  107. FieldUpdBuf : PFieldUpdateBuffer;
  108. NullMask : pbyte;
  109. begin
  110. Result := grOK;
  111. case GetMode of
  112. gmPrior :
  113. if FIsBOF then
  114. result := grBOF
  115. else if FBCurrentRecord <= 0 then
  116. begin
  117. Result := grBOF;
  118. FBCurrentRecord := -1;
  119. end
  120. else
  121. begin
  122. Dec(FBCurrentRecord);
  123. FIsEof := false;
  124. end;
  125. gmCurrent :
  126. if (FBCurrentRecord < 0) or (FBCurrentRecord >= FBRecordCount) then
  127. Result := grError;
  128. gmNext :
  129. if FIsEOF then
  130. result := grEOF
  131. else if FBCurrentRecord >= (FBRecordCount - 1) then
  132. begin
  133. if getnextpacket > 0 then
  134. begin
  135. Inc(FBCurrentRecord);
  136. FIsBof := false;
  137. end
  138. else
  139. begin
  140. FIsEOF := true;
  141. result:=grEOF;
  142. end
  143. end
  144. else
  145. begin
  146. Inc(FBCurrentRecord);
  147. FIsBof := false;
  148. end;
  149. end;
  150. if Result = grOK then
  151. begin
  152. if GetDeleted(pbyte(FBBuffers[FBCurrentRecord])) then
  153. begin
  154. if getmode = gmCurrent then
  155. if DoCheck then
  156. begin
  157. Result := grError;
  158. DatabaseError(SDeletedRecord);
  159. exit;
  160. end
  161. else
  162. getmode := gmnext;
  163. Result := GetRecord(Buffer,getmode,DoCheck);
  164. exit
  165. end;
  166. with PBufBookmark(Buffer + RecordSize)^ do
  167. begin
  168. BookmarkData := FBCurrentRecord;
  169. BookmarkFlag := bfCurrent;
  170. end;
  171. move(FBBuffers[FBCurrentRecord]^,buffer^,RecordSize);
  172. // Cached Updates:
  173. If GetRecordUpdateBuffer(FBCurrentRecord,RecUpdBuf) then
  174. begin
  175. NullMask := pbyte(buffer);
  176. inc(buffer,FNullmaskSize);
  177. for x := 0 to FieldDefs.count-1 do
  178. begin
  179. if GetFieldUpdateBuffer(x,RecUpdBuf,FieldUpdBuf) then
  180. If not FieldUpdBuf^.IsNull then
  181. begin
  182. unSetFieldIsNull(NullMask,x);
  183. move(FieldUpdBuf^.NewValue^,buffer^,GetFieldSize(FieldDefs[x]));
  184. end
  185. else
  186. SetFieldIsNull(NullMask,x);
  187. Inc(Buffer, GetFieldSize(FieldDefs[x]));
  188. end;
  189. end;
  190. end
  191. else if (Result = grError) and doCheck then
  192. DatabaseError('No record');
  193. end;
  194. function TBufDataset.GetRecordUpdateBuffer(rno : integer;var RecUpdBuf : PRecUpdateBuffer) : boolean;
  195. var r : integer;
  196. begin
  197. Result := False;
  198. for r := 0 to high(FUpdateBuffer) do
  199. if (FUpdateBuffer[r].RecordNo = rno) and (@FUpdateBuffer[r] <> FEditBuf) then // Neglect the edit-buffer
  200. begin
  201. RecUpdBuf := @FUpdateBuffer[r];
  202. Result := True;
  203. Break;
  204. end;
  205. end;
  206. function TBufDataset.GetFieldUpdateBuffer(fieldno : integer;RecUpdBuf : PRecUpdateBuffer;var FieldUpdBuf : pFieldUpdateBuffer) : boolean;
  207. var f : integer;
  208. begin
  209. Result := False;
  210. for f := 0 to High(RecUpdBuf^.FieldsUpdateBuffer) do
  211. if RecUpdBuf^.FieldsUpdateBuffer[f].FieldNo = fieldno then
  212. begin
  213. FieldUpdBuf := @RecUpdBuf^.FieldsUpdateBuffer[f];
  214. Result := True;
  215. Break;
  216. end;
  217. end;
  218. procedure TBufDataset.InternalSetToRecord(Buffer: PChar);
  219. begin
  220. FBCurrentRecord := PBufBookmark(Buffer + RecordSize)^.BookmarkData;
  221. FIsEOF := False;
  222. FIsBOF := False;
  223. end;
  224. procedure TBufDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
  225. begin
  226. PBufBookmark(Buffer + RecordSize)^.BookmarkData := PInteger(Data)^;
  227. end;
  228. procedure TBufDataset.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
  229. begin
  230. PBufBookmark(Buffer + RecordSize)^.BookmarkFlag := Value;
  231. end;
  232. procedure TBufDataset.GetBookmarkData(Buffer: PChar; Data: Pointer);
  233. begin
  234. PInteger(Data)^ := PBufBookmark(Buffer + RecordSize)^.BookmarkData;
  235. end;
  236. function TBufDataset.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
  237. begin
  238. Result := PBufBookmark(Buffer + RecordSize)^.BookmarkFlag;
  239. end;
  240. procedure TBufDataset.InternalGotoBookmark(ABookmark: Pointer);
  241. begin
  242. FBCurrentRecord := Plongint(ABookmark)^;
  243. FIsEOF := False;
  244. FIsBOF := False;
  245. end;
  246. function TBufDataset.getnextpacket : integer;
  247. var i : integer;
  248. b : boolean;
  249. begin
  250. i := 0;
  251. if FPacketRecords > 0 then
  252. begin
  253. if FBBufferCount < FBRecordCount+FPacketRecords then
  254. begin
  255. FBBufferCount := FBBuffercount + FPacketRecords;
  256. ReAllocMem(FBBuffers,FBBuffercount*SizeOf(PChar));
  257. end;
  258. repeat
  259. FBBuffers[FBRecordCount+i] := AllocRecordBuffer;
  260. b := (loadbuffer(FBBuffers[FBRecordCount+i])<>grOk);
  261. inc(i);
  262. until (i = FPacketRecords) or b;
  263. if b then
  264. begin
  265. dec(i);
  266. FreeRecordBuffer(FBBuffers[FBRecordCount+i]);
  267. end;
  268. FBRecordCount := FBRecordCount + i;
  269. end;
  270. result := i;
  271. end;
  272. function TBufDataset.GetFieldSize(FieldDef : TFieldDef) : longint;
  273. begin
  274. case FieldDef.DataType of
  275. ftString : result := FieldDef.Size + 1;
  276. ftSmallint,
  277. ftInteger,
  278. ftword : result := sizeof(longint);
  279. ftBoolean : result := sizeof(boolean);
  280. ftBCD : result := sizeof(currency);
  281. ftFloat : result := sizeof(double);
  282. ftTime,
  283. ftDate,
  284. ftDateTime : result := sizeof(TDateTime)
  285. else Result := 10
  286. end;
  287. end;
  288. function TBufDataset.LoadBuffer(Buffer : PChar): TGetResult;
  289. var NullMask : pbyte;
  290. x : longint;
  291. begin
  292. if not Fetch then
  293. begin
  294. Result := grEOF;
  295. Exit;
  296. end;
  297. NullMask := pointer(buffer);
  298. fillchar(Nullmask^,FNullmaskSize,0);
  299. inc(buffer,FNullmaskSize);
  300. for x := 0 to FieldDefs.count-1 do
  301. begin
  302. if not LoadField(FieldDefs[x],buffer) then
  303. SetFieldIsNull(NullMask,x);
  304. inc(buffer,GetFieldSize(FieldDefs[x]));
  305. end;
  306. Result := grOK;
  307. end;
  308. function TBufDataset.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
  309. var
  310. x : longint;
  311. CurrBuff : pchar;
  312. begin
  313. Result := False;
  314. If Field.Fieldno > 0 then // If = 0, then calculated field or something similar
  315. begin
  316. if state = dsOldValue then
  317. begin
  318. if FApplyingUpdates then
  319. CurrBuff := FBBuffers[fbcurrentrecord] // This makes it possible for ApplyUpdates to get values from deleted records
  320. else
  321. CurrBuff := FBBuffers[GetRecNo];
  322. end
  323. else
  324. begin
  325. CurrBuff := ActiveBuffer;
  326. if not assigned(CurrBuff) or GetDeleted(pbyte(CurrBuff)) then
  327. begin
  328. result := false;
  329. exit;
  330. end;
  331. end;
  332. if GetFieldIsnull(pbyte(CurrBuff),Field.Fieldno-1) then
  333. begin
  334. result := false;
  335. exit;
  336. end;
  337. inc(Currbuff,FNullmaskSize);
  338. for x := 0 to FieldDefs.count-1 do
  339. begin
  340. if (Field.FieldName = FieldDefs[x].Name) then
  341. begin
  342. // a nil-buffer is allowed for the fields.isNull function
  343. if assigned(buffer) then Move(CurrBuff^, Buffer^, GetFieldSize(FieldDefs[x]));
  344. Result := True;
  345. Break;
  346. end
  347. else Inc(CurrBuff, GetFieldSize(FieldDefs[x]));
  348. end;
  349. end;
  350. end;
  351. procedure TBufDataset.SetFieldData(Field: TField; Buffer: Pointer);
  352. var
  353. x : longint;
  354. CurrBuff : pointer;
  355. NullMask : pbyte;
  356. FieldUpdBuf : PFieldUpdateBuffer;
  357. begin
  358. If Field.Fieldno > 0 then // If = 0, then calculated field or something
  359. begin
  360. CurrBuff := ActiveBuffer;
  361. NullMask := CurrBuff;
  362. inc(Currbuff,FNullmaskSize);
  363. for x := 0 to FieldDefs.count-1 do
  364. begin
  365. if (Field.FieldName = FieldDefs[x].Name) then
  366. begin
  367. if assigned(buffer) then
  368. begin
  369. Move(Buffer^, CurrBuff^, GetFieldSize(FieldDefs[x]));
  370. unSetFieldIsNull(NullMask,x);
  371. end
  372. else
  373. SetFieldIsNull(NullMask,x);
  374. // cached updates
  375. with FEditBuf^ do
  376. begin
  377. if not GetFieldUpdateBuffer(x,FEditBuf,FieldUpdBuf) then
  378. begin
  379. SetLength(FieldsUpdateBuffer,length(FieldsUpdateBuffer)+1);
  380. FieldUpdBuf := @FieldsUpdateBuffer[high(FieldsUpdateBuffer)];
  381. GetMem(FieldUpdBuf^.NewValue,GetFieldSize(FieldDefs[x]));
  382. FieldUpdBuf^.FieldNo := x;
  383. end;
  384. if assigned(buffer) then
  385. begin
  386. Move(Buffer^, FieldUpdBuf^.NewValue^, GetFieldSize(FieldDefs[x]));
  387. FieldUpdBuf^.IsNull := False;
  388. end
  389. else FieldUpdBuf^.IsNull := True;
  390. end;
  391. Break;
  392. end
  393. else Inc(CurrBuff, GetFieldSize(FieldDefs[x]));
  394. end;
  395. if not (State in [dsCalcFields, dsFilter, dsNewValue]) then
  396. DataEvent(deFieldChange, Ptrint(Field));
  397. end;
  398. end;
  399. procedure TBufDataset.InternalEdit;
  400. begin
  401. if not GetRecordUpdateBuffer(recno,FEditBuf) then
  402. begin
  403. If not assigned(FEditBuf) then
  404. begin
  405. SetLength(FUpdateBuffer,length(FUpdateBuffer)+1);
  406. FEditBuf := @FUpdateBuffer[high(FUpdateBuffer)];
  407. end;
  408. FEditBuf^.UpdateKind := ukModify;
  409. FEditBuf^.RecordNo := getrecno;
  410. end;
  411. end;
  412. procedure TBufDataset.InternalInsert;
  413. begin
  414. if FBRecordCount > FBBufferCount-1 then
  415. begin
  416. inc(FBBufferCount);
  417. ReAllocMem(FBBuffers,FBBuffercount*SizeOf(PChar));
  418. end;
  419. inc(FBRecordCount);
  420. FBCurrentRecord := FBRecordCount -1;
  421. FBBuffers[FBCurrentRecord] := AllocRecordBuffer;
  422. fillchar(FBBuffers[FBCurrentRecord]^,FNullmaskSize,255);
  423. unSetDeleted(pbyte(FBBuffers[FBCurrentRecord]));
  424. fillchar(ActiveBuffer^,FNullmaskSize,255);
  425. unSetDeleted(pbyte(ActiveBuffer));
  426. // cached updates:
  427. If not assigned(FEditBuf) then
  428. begin
  429. SetLength(FUpdateBuffer,length(FUpdateBuffer)+1);
  430. FEditBuf := @FUpdateBuffer[high(FUpdateBuffer)];
  431. end;
  432. FEditBuf^.RecordNo := FBCurrentRecord;
  433. FEditBuf^.UpdateKind := ukInsert;
  434. with PBufBookmark(ActiveBuffer + RecordSize)^ do
  435. begin
  436. BookmarkData := FBCurrentRecord;
  437. BookmarkFlag := bfInserted;
  438. end;
  439. end;
  440. procedure TBufDataset.InternalDelete;
  441. var tel : integer;
  442. begin
  443. SetDeleted(pbyte(FBBuffers[FBCurrentRecord]));
  444. SetDeleted(pbyte(ActiveBuffer));
  445. inc(FBDeletedRecords);
  446. if GetRecordUpdateBuffer(recno,FEditBuf) and (FEditBuf^.UpdateKind = ukInsert) then
  447. begin
  448. if assigned(FEditBuf^.FieldsUpdateBuffer) then
  449. for tel := 0 to high(FEditBuf^.FieldsUpdateBuffer) do
  450. if not FEditBuf^.FieldsUpdateBuffer[tel].IsNull then
  451. freemem(FEditBuf^.FieldsUpdateBuffer[tel].NewValue);
  452. setlength(FEditBuf^.FieldsUpdateBuffer,0);
  453. FEditBuf^.RecordNo := -1;
  454. end
  455. else
  456. begin
  457. If not assigned(FEditBuf) then
  458. begin
  459. SetLength(FUpdateBuffer,length(FUpdateBuffer)+1);
  460. FEditBuf := @FUpdateBuffer[high(FUpdateBuffer)];
  461. end;
  462. FEditBuf^.RecordNo := FBCurrentRecord;
  463. FEditBuf^.UpdateKind := ukDelete;
  464. end;
  465. FEditBuf := nil;
  466. end;
  467. function TBufDataset.ApplyRecUpdate(UpdateKind : TUpdateKind) : boolean;
  468. begin
  469. Result := False;
  470. end;
  471. procedure TBufDataset.CancelUpdates;
  472. var r,f : integer;
  473. begin
  474. for r := 0 to high(FUpdateBuffer) do
  475. begin
  476. if FUpdateBuffer[r].RecordNo > -1 then
  477. if FUpdateBuffer[r].UpdateKind = ukDelete then
  478. begin
  479. dec(FBDeletedRecords);
  480. unSetDeleted(pbyte(FBBuffers[FUpdateBuffer[r].RecordNo]));
  481. end
  482. else if FUpdateBuffer[r].UpdateKind = ukInsert then
  483. begin
  484. inc(FBDeletedRecords);
  485. SetDeleted(pbyte(FBBuffers[FUpdateBuffer[r].RecordNo]));
  486. end;
  487. for f := 0 to high(FUpdateBuffer[r].FieldsUpdateBuffer) do
  488. FreeMem(FUpdateBuffer[r].FieldsUpdateBuffer[f].newvalue);
  489. end;
  490. SetLength(FUpdateBuffer,0);
  491. if FOpen then Resync([]);
  492. end;
  493. procedure TBufDataset.ApplyUpdates;
  494. var SaveBookmark : Integer;
  495. r,i : Integer;
  496. buffer : PChar;
  497. x : integer;
  498. FieldUpdBuf : PFieldUpdateBuffer;
  499. NullMask : pbyte;
  500. begin
  501. CheckBrowseMode;
  502. SaveBookMark := GetRecNo;
  503. r := 0;
  504. while r < Length(FUpdateBuffer) do
  505. begin
  506. if (@FUpdateBuffer[r] <> FEditBuf) and // Neglect edit-buffer
  507. (FUpdateBuffer[r].RecordNo <> -1) then // And the 'deleted' buffers
  508. begin
  509. FApplyingUpdates := true;
  510. if FUpdateBuffer[r].UpdateKind = ukDelete then
  511. InternalGotoBookmark(@(FUpdateBuffer[r].RecordNo))
  512. else
  513. SetRecNo(FUpdateBuffer[r].RecordNo);
  514. if ApplyRecUpdate(FUpdateBuffer[r].UpdateKind) then
  515. begin
  516. buffer := FBBuffers[FUpdateBuffer[r].RecordNo];
  517. NullMask := pbyte(buffer);
  518. inc(buffer,FNullmaskSize);
  519. for x := 0 to FieldDefs.count-1 do
  520. begin
  521. if GetFieldUpdateBuffer(x,@FUpdateBuffer[r],FieldUpdBuf) then
  522. If not FieldUpdBuf^.IsNull then
  523. begin
  524. unSetFieldIsNull(NullMask,x);
  525. move(FieldUpdBuf^.NewValue^,buffer^,GetFieldSize(FieldDefs[x]));
  526. FreeMem(FieldUpdBuf^.NewValue);
  527. end
  528. else
  529. SetFieldIsNull(NullMask,x);
  530. Inc(Buffer, GetFieldSize(FieldDefs[x]));
  531. end;
  532. for i := r to high(FUpdateBuffer)-1 do
  533. FUpdateBuffer[i] := FupdateBuffer[i+1];
  534. dec(r);
  535. SetLength(FUpdateBuffer,high(FUpdateBuffer));
  536. end;
  537. FApplyingUpdates := False;
  538. end;
  539. inc(r);
  540. end;
  541. Refresh;
  542. if not GetDeleted(pbyte(FBBuffers[savebookmark])) then
  543. SetRecNo(SaveBookMark);
  544. end;
  545. procedure TBufDataset.InternalPost;
  546. begin
  547. if state in [dsEdit, dsInsert] then
  548. begin
  549. if Length(FUpdateBuffer[High(FUpdateBuffer)].FieldsUpdateBuffer) > 0 then
  550. FEditBuf := nil;
  551. end;
  552. end;
  553. procedure TBufDataset.InternalCancel;
  554. var tel : integer;
  555. begin
  556. if state in [dsEdit, dsInsert] then
  557. begin
  558. if state = dsInsert then
  559. begin
  560. SetDeleted(pbyte(FBBuffers[FBCurrentRecord]));
  561. SetDeleted(pbyte(ActiveBuffer));
  562. inc(FBDeletedRecords);
  563. end;
  564. FEditBuf^.RecordNo := -1;
  565. // clear the fieldbuffers
  566. if assigned(FEditBuf^.FieldsUpdateBuffer) then
  567. for tel := 0 to high(FEditBuf^.FieldsUpdateBuffer) do
  568. if not FEditBuf^.FieldsUpdateBuffer[tel].IsNull then
  569. freemem(FEditBuf^.FieldsUpdateBuffer[tel].NewValue);
  570. setlength(FEditBuf^.FieldsUpdateBuffer,0);
  571. end;
  572. end;
  573. procedure TBufDataset.CalcRecordSize;
  574. var x : longint;
  575. begin
  576. FNullmaskSize := 1+((FieldDefs.count) div 8);
  577. FRecordSize := FNullmaskSize;
  578. for x := 0 to FieldDefs.count-1 do
  579. inc(FRecordSize, GetFieldSize(FieldDefs[x]));
  580. end;
  581. function TBufDataset.GetRecordSize : Word;
  582. begin
  583. result := FRecordSize;
  584. end;
  585. procedure TBufDataset.InternalInitRecord(Buffer: PChar);
  586. begin
  587. FillChar(Buffer^, FRecordSize, #0);
  588. end;
  589. procedure TBufDataset.SetRecNo(Value: Longint);
  590. begin
  591. GotoBookmark(@value);
  592. end;
  593. function TBufDataset.GetRecNo: Longint;
  594. begin
  595. GetBookmarkData(ActiveBuffer,@Result);
  596. end;
  597. function TBufDataset.IsCursorOpen: Boolean;
  598. begin
  599. Result := FOpen;
  600. end;
  601. Function TBufDataset.GetRecordCount: Longint;
  602. begin
  603. Result := FBRecordCount-FBDeletedRecords;
  604. end;