bufdataset.inc 18 KB

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