bufdataset.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  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): 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 not (state in [dsEdit, dsInsert]) then
  359. begin
  360. DatabaseErrorFmt(SNotInEditState,[NAme],self);
  361. exit;
  362. end;
  363. If Field.Fieldno > 0 then // If = 0, then calculated field or something
  364. begin
  365. CurrBuff := ActiveBuffer;
  366. NullMask := CurrBuff;
  367. inc(Currbuff,FNullmaskSize);
  368. for x := 0 to FieldDefs.count-1 do
  369. begin
  370. if (Field.FieldName = FieldDefs[x].Name) then
  371. begin
  372. if assigned(buffer) then
  373. begin
  374. Move(Buffer^, CurrBuff^, GetFieldSize(FieldDefs[x]));
  375. unSetFieldIsNull(NullMask,x);
  376. end
  377. else
  378. SetFieldIsNull(NullMask,x);
  379. // cached updates
  380. with FEditBuf^ do
  381. begin
  382. if not GetFieldUpdateBuffer(x,FEditBuf,FieldUpdBuf) then
  383. begin
  384. SetLength(FieldsUpdateBuffer,length(FieldsUpdateBuffer)+1);
  385. FieldUpdBuf := @FieldsUpdateBuffer[high(FieldsUpdateBuffer)];
  386. GetMem(FieldUpdBuf^.NewValue,GetFieldSize(FieldDefs[x]));
  387. FieldUpdBuf^.FieldNo := x;
  388. end;
  389. if assigned(buffer) then
  390. begin
  391. Move(Buffer^, FieldUpdBuf^.NewValue^, GetFieldSize(FieldDefs[x]));
  392. FieldUpdBuf^.IsNull := False;
  393. end
  394. else FieldUpdBuf^.IsNull := True;
  395. end;
  396. Break;
  397. end
  398. else Inc(CurrBuff, GetFieldSize(FieldDefs[x]));
  399. end;
  400. if not (State in [dsCalcFields, dsFilter, dsNewValue]) then
  401. DataEvent(deFieldChange, Ptrint(Field));
  402. end;
  403. end;
  404. procedure TBufDataset.InternalEdit;
  405. begin
  406. if not GetRecordUpdateBuffer(recno,FEditBuf) then
  407. begin
  408. If not assigned(FEditBuf) then
  409. begin
  410. SetLength(FUpdateBuffer,length(FUpdateBuffer)+1);
  411. FEditBuf := @FUpdateBuffer[high(FUpdateBuffer)];
  412. end;
  413. FEditBuf^.UpdateKind := ukModify;
  414. FEditBuf^.RecordNo := getrecno;
  415. end;
  416. end;
  417. procedure TBufDataset.InternalInsert;
  418. begin
  419. if FBRecordCount > FBBufferCount-1 then
  420. begin
  421. inc(FBBufferCount);
  422. ReAllocMem(FBBuffers,FBBuffercount*SizeOf(PChar));
  423. end;
  424. inc(FBRecordCount);
  425. FBCurrentRecord := FBRecordCount -1;
  426. FBBuffers[FBCurrentRecord] := AllocRecordBuffer;
  427. fillchar(FBBuffers[FBCurrentRecord]^,FNullmaskSize,255);
  428. unSetDeleted(pbyte(FBBuffers[FBCurrentRecord]));
  429. fillchar(ActiveBuffer^,FNullmaskSize,255);
  430. unSetDeleted(pbyte(ActiveBuffer));
  431. // cached updates:
  432. If not assigned(FEditBuf) then
  433. begin
  434. SetLength(FUpdateBuffer,length(FUpdateBuffer)+1);
  435. FEditBuf := @FUpdateBuffer[high(FUpdateBuffer)];
  436. end;
  437. FEditBuf^.RecordNo := FBCurrentRecord;
  438. FEditBuf^.UpdateKind := ukInsert;
  439. with PBufBookmark(ActiveBuffer + RecordSize)^ do
  440. begin
  441. BookmarkData := FBCurrentRecord;
  442. BookmarkFlag := bfInserted;
  443. end;
  444. end;
  445. procedure TBufDataset.InternalDelete;
  446. var tel : integer;
  447. begin
  448. SetDeleted(pbyte(FBBuffers[FBCurrentRecord]));
  449. SetDeleted(pbyte(ActiveBuffer));
  450. inc(FBDeletedRecords);
  451. if GetRecordUpdateBuffer(recno,FEditBuf) and (FEditBuf^.UpdateKind = ukInsert) then
  452. begin
  453. if assigned(FEditBuf^.FieldsUpdateBuffer) then
  454. for tel := 0 to high(FEditBuf^.FieldsUpdateBuffer) do
  455. if not FEditBuf^.FieldsUpdateBuffer[tel].IsNull then
  456. freemem(FEditBuf^.FieldsUpdateBuffer[tel].NewValue);
  457. setlength(FEditBuf^.FieldsUpdateBuffer,0);
  458. FEditBuf^.RecordNo := -1;
  459. end
  460. else
  461. begin
  462. If not assigned(FEditBuf) then
  463. begin
  464. SetLength(FUpdateBuffer,length(FUpdateBuffer)+1);
  465. FEditBuf := @FUpdateBuffer[high(FUpdateBuffer)];
  466. end;
  467. FEditBuf^.RecordNo := FBCurrentRecord;
  468. FEditBuf^.UpdateKind := ukDelete;
  469. end;
  470. FEditBuf := nil;
  471. end;
  472. function TBufDataset.ApplyRecUpdate(UpdateKind : TUpdateKind) : boolean;
  473. begin
  474. Result := False;
  475. end;
  476. procedure TBufDataset.CancelUpdates;
  477. var r,f : integer;
  478. begin
  479. for r := 0 to high(FUpdateBuffer) do
  480. begin
  481. if FUpdateBuffer[r].RecordNo > -1 then
  482. if FUpdateBuffer[r].UpdateKind = ukDelete then
  483. begin
  484. dec(FBDeletedRecords);
  485. unSetDeleted(pbyte(FBBuffers[FUpdateBuffer[r].RecordNo]));
  486. end
  487. else if FUpdateBuffer[r].UpdateKind = ukInsert then
  488. begin
  489. inc(FBDeletedRecords);
  490. SetDeleted(pbyte(FBBuffers[FUpdateBuffer[r].RecordNo]));
  491. end;
  492. for f := 0 to high(FUpdateBuffer[r].FieldsUpdateBuffer) do
  493. FreeMem(FUpdateBuffer[r].FieldsUpdateBuffer[f].newvalue);
  494. end;
  495. SetLength(FUpdateBuffer,0);
  496. if FOpen then Resync([]);
  497. end;
  498. procedure TBufDataset.ApplyUpdates;
  499. var SaveBookmark : Integer;
  500. r,i : Integer;
  501. buffer : PChar;
  502. x : integer;
  503. FieldUpdBuf : PFieldUpdateBuffer;
  504. NullMask : pbyte;
  505. begin
  506. CheckBrowseMode;
  507. if IsEmpty then exit;
  508. SaveBookMark := GetRecNo;
  509. r := 0;
  510. while r < Length(FUpdateBuffer) do
  511. begin
  512. if (@FUpdateBuffer[r] <> FEditBuf) and // Neglect edit-buffer
  513. (FUpdateBuffer[r].RecordNo <> -1) then // And the 'deleted' buffers
  514. begin
  515. FApplyingUpdates := true;
  516. if FUpdateBuffer[r].UpdateKind = ukDelete then
  517. InternalGotoBookmark(@(FUpdateBuffer[r].RecordNo))
  518. else
  519. begin
  520. InternalGotoBookMark(@FUpdateBuffer[r].RecordNo);
  521. Resync([rmExact,rmCenter]);
  522. end;
  523. if ApplyRecUpdate(FUpdateBuffer[r].UpdateKind) then
  524. begin
  525. buffer := FBBuffers[FUpdateBuffer[r].RecordNo];
  526. NullMask := pbyte(buffer);
  527. inc(buffer,FNullmaskSize);
  528. for x := 0 to FieldDefs.count-1 do
  529. begin
  530. if GetFieldUpdateBuffer(x,@FUpdateBuffer[r],FieldUpdBuf) then
  531. If not FieldUpdBuf^.IsNull then
  532. begin
  533. unSetFieldIsNull(NullMask,x);
  534. move(FieldUpdBuf^.NewValue^,buffer^,GetFieldSize(FieldDefs[x]));
  535. FreeMem(FieldUpdBuf^.NewValue);
  536. end
  537. else
  538. SetFieldIsNull(NullMask,x);
  539. Inc(Buffer, GetFieldSize(FieldDefs[x]));
  540. end;
  541. for i := r to high(FUpdateBuffer)-1 do
  542. FUpdateBuffer[i] := FupdateBuffer[i+1];
  543. dec(r);
  544. SetLength(FUpdateBuffer,high(FUpdateBuffer));
  545. end;
  546. FApplyingUpdates := False;
  547. end;
  548. inc(r);
  549. end;
  550. if not GetDeleted(pbyte(FBBuffers[savebookmark])) then
  551. begin
  552. InternalGotoBookMark(@SaveBookMark);
  553. Resync([rmExact,rmCenter]);
  554. end;
  555. end;
  556. procedure TBufDataset.InternalPost;
  557. begin
  558. if state in [dsEdit, dsInsert] then
  559. begin
  560. if Length(FUpdateBuffer[High(FUpdateBuffer)].FieldsUpdateBuffer) > 0 then
  561. FEditBuf := nil;
  562. end;
  563. end;
  564. procedure TBufDataset.InternalCancel;
  565. var tel : integer;
  566. begin
  567. if state in [dsEdit, dsInsert] then
  568. begin
  569. if state = dsInsert then
  570. begin
  571. SetDeleted(pbyte(FBBuffers[FBCurrentRecord]));
  572. SetDeleted(pbyte(ActiveBuffer));
  573. inc(FBDeletedRecords);
  574. end;
  575. FEditBuf^.RecordNo := -1;
  576. // clear the fieldbuffers
  577. if assigned(FEditBuf^.FieldsUpdateBuffer) then
  578. for tel := 0 to high(FEditBuf^.FieldsUpdateBuffer) do
  579. if not FEditBuf^.FieldsUpdateBuffer[tel].IsNull then
  580. freemem(FEditBuf^.FieldsUpdateBuffer[tel].NewValue);
  581. setlength(FEditBuf^.FieldsUpdateBuffer,0);
  582. end;
  583. end;
  584. procedure TBufDataset.CalcRecordSize;
  585. var x : longint;
  586. begin
  587. FNullmaskSize := 1+((FieldDefs.count) div 8);
  588. FRecordSize := FNullmaskSize;
  589. for x := 0 to FieldDefs.count-1 do
  590. inc(FRecordSize, GetFieldSize(FieldDefs[x]));
  591. end;
  592. function TBufDataset.GetRecordSize : Word;
  593. begin
  594. result := FRecordSize;
  595. end;
  596. procedure TBufDataset.InternalInitRecord(Buffer: PChar);
  597. begin
  598. FillChar(Buffer^, FRecordSize, #0);
  599. end;
  600. procedure TBufDataset.SetRecNo(Value: Longint);
  601. begin
  602. GotoBookmark(@value);
  603. end;
  604. function TBufDataset.GetRecNo: Longint;
  605. begin
  606. GetBookmarkData(ActiveBuffer,@Result);
  607. end;
  608. function TBufDataset.IsCursorOpen: Boolean;
  609. begin
  610. Result := FOpen;
  611. end;
  612. Function TBufDataset.GetRecordCount: Longint;
  613. begin
  614. Result := FBRecordCount-FBDeletedRecords;
  615. end;