dataset.inc 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027
  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. Dataset 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. TDataSet
  14. ---------------------------------------------------------------------}
  15. Const
  16. DefaultBufferCount = 10;
  17. constructor TDataSet.Create(AOwner: TComponent);
  18. begin
  19. Inherited Create(AOwner);
  20. FFieldDefs:=TFieldDefs.Create(Self);
  21. FFieldList:=TFields.Create(Self);
  22. FDataSources:=TList.Create;
  23. // FBuffer must be allocated on create, to make Activebuffer return nil
  24. ReAllocMem(FBuffers,SizeOf(PChar));
  25. // pointer(FBuffers^) := nil;
  26. FBuffers[0] := nil;
  27. FActiveRecord := 0;
  28. FBufferCount := 0;
  29. FEOF := True;
  30. FBOF := True;
  31. end;
  32. destructor TDataSet.Destroy;
  33. var
  34. i: Integer;
  35. begin
  36. Active:=False;
  37. FFieldDefs.Free;
  38. FFieldList.Free;
  39. With FDatasources do
  40. begin
  41. While Count>0 do
  42. TDatasource(Items[Count - 1]).DataSet:=Nil;
  43. Free;
  44. end;
  45. for i := 0 to FBufferCount do
  46. FreeRecordBuffer(FBuffers[i]);
  47. FreeMem(FBuffers);
  48. Inherited Destroy;
  49. end;
  50. // This procedure must be called when the first record is made/read
  51. Procedure TDataset.ActivateBuffers;
  52. begin
  53. FBOF:=False;
  54. FEOF:=False;
  55. FActiveRecord:=0;
  56. end;
  57. Procedure TDataset.UpdateFieldDefs;
  58. begin
  59. //!! To be implemented
  60. end;
  61. Procedure TDataset.BindFields(Binding: Boolean);
  62. var i, FieldIndex: Integer;
  63. FieldDef: TFieldDef;
  64. begin
  65. {
  66. Here some magic will be needed later; for now just simply set
  67. Just set fieldno from listindex...
  68. Later we should take it from the fielddefs.
  69. // ATM Set by CreateField ...
  70. For I:=0 to FFieldList.Count-1 do
  71. FFieldList[i].FFieldNo:=I;
  72. }
  73. FCalcFieldsSize := 0;
  74. FBlobFieldCount := 0;
  75. for i := 0 to Fields.Count - 1 do
  76. with Fields[i] do begin
  77. if Binding then begin
  78. if FieldKind in [fkCalculated, fkLookup] then begin
  79. FFieldNo := -1;
  80. FOffset := FCalcFieldsSize;
  81. Inc(FCalcFieldsSize, DataSize + 1);
  82. if FieldKind in [fkLookup] then begin
  83. if ((FLookupDataSet = nil) or (FLookupKeyFields = '') or
  84. (FLookupResultField = '') or (FKeyFields = '')) then
  85. DatabaseErrorFmt(SLookupInfoError, [DisplayName]);
  86. FFields.CheckFieldNames(FKeyFields);
  87. FLookupDataSet.Fields.CheckFieldNames(FLookupKeyFields);
  88. FLookupDataSet.FieldByName(FLookupResultField);
  89. if FLookupCache then RefreshLookupList;
  90. end
  91. end else begin
  92. FieldDef := nil;
  93. FieldIndex := FieldDefs.IndexOf(Fields[i].FieldName);
  94. if FieldIndex <> -1 then begin
  95. FieldDef := FieldDefs[FieldIndex];
  96. FFieldNo := FieldDef.FieldNo;
  97. if IsBlob then begin
  98. FSize := FieldDef.Size;
  99. FOffset := FBlobFieldCount;
  100. Inc(FBlobFieldCount);
  101. end;
  102. end else FFieldNo := FieldIndex;
  103. end;
  104. end else FFieldNo := 0;;
  105. end;
  106. end;
  107. Function TDataset.BookmarkAvailable: Boolean;
  108. Const BookmarkStates = [dsBrowse,dsEdit,dsInsert];
  109. begin
  110. Result:=(Not IsEmpty) and (State in BookmarkStates)
  111. and (getBookMarkFlag(ActiveBuffer)=bfCurrent);
  112. end;
  113. Procedure TDataset.CalculateFields(Buffer: PChar);
  114. var
  115. I: Integer;
  116. begin
  117. FCalcBuffer := Buffer;
  118. if (State <> dsInternalCalc) and (IsUniDirectional = False) then
  119. begin
  120. ClearCalcFields(CalcBuffer);
  121. for I := 0 to Fields.Count - 1 do
  122. with Fields[I] do
  123. if FieldKind = fkLookup then CalcLookupValue;
  124. end;
  125. DoOnCalcFields;
  126. end;
  127. Procedure TDataset.CheckActive;
  128. begin
  129. If Not Active then
  130. DataBaseError(SInactiveDataset);
  131. end;
  132. Procedure TDataset.CheckInactive;
  133. begin
  134. If Active then
  135. DataBaseError(SActiveDataset);
  136. end;
  137. Procedure TDataset.ClearBuffers;
  138. begin
  139. FRecordCount:=0;
  140. FactiveRecord:=0;
  141. FCurrentRecord:=-1;
  142. FBOF:=True;
  143. FEOF:=True;
  144. end;
  145. Procedure TDataset.ClearCalcFields(Buffer: PChar);
  146. begin
  147. //!! To be implemented
  148. end;
  149. Procedure TDataset.CloseBlob(Field: TField);
  150. begin
  151. //!! To be implemented
  152. end;
  153. Procedure TDataset.CloseCursor;
  154. begin
  155. //!! To be implemented
  156. end;
  157. Procedure TDataset.CreateFields;
  158. Var I : longint;
  159. begin
  160. {$ifdef DSDebug}
  161. Writeln ('Creating fields');
  162. Writeln ('Count : ',fielddefs.Count);
  163. For I:=0 to FieldDefs.Count-1 do
  164. Writeln('Def ',I,' : ',Fielddefs.items[i].Name,'(',Fielddefs.items[i].FieldNo,')');
  165. {$endif}
  166. For I:=0 to fielddefs.Count-1 do
  167. With Fielddefs.Items[I] do
  168. If DataType<>ftUnknown then
  169. begin
  170. {$ifdef DSDebug}
  171. Writeln('About to create field',FieldDefs.Items[i].Name);
  172. {$endif}
  173. CreateField(self);
  174. end;
  175. end;
  176. Procedure TDataset.DataEvent(Event: TDataEvent; Info: Ptrint);
  177. Var
  178. i : longint;
  179. begin
  180. // Do some bookkeeping;
  181. case Event of
  182. deFieldChange: begin
  183. if TField(Info).FieldKind in [fkData,fkInternalCalc] then
  184. SetModified(True);
  185. if State <> dsSetKey then begin
  186. if FInternalCalcFields and (TField(Info).FieldKind = fkData) then
  187. RefreshInternalCalcFields(ActiveBuffer)
  188. else if (FCalcFieldsSize <> 0) and FAutoCalcFields and
  189. (TField(Info).FieldKind = fkData) then
  190. CalculateFields(ActiveBuffer);
  191. TField(Info).Change;
  192. end;
  193. end;
  194. deDataSetChange, deDataSetScroll:
  195. if State <> dsInsert then UpdateCursorPos;
  196. end;
  197. // Distribute event to datasets;
  198. if FDisableControlsCount = 0 then
  199. for I := 0 to FDataSources.Count - 1 do
  200. TDataSource(FDataSources[I]).ProcessEvent(Event, Info);
  201. end;
  202. Procedure TDataset.DestroyFields;
  203. begin
  204. FFieldList.Clear;
  205. end;
  206. Procedure TDataset.DoAfterCancel;
  207. begin
  208. If assigned(FAfterCancel) then
  209. FAfterCancel(Self);
  210. end;
  211. Procedure TDataset.DoAfterClose;
  212. begin
  213. If assigned(FAfterClose) then
  214. FAfterClose(Self);
  215. end;
  216. Procedure TDataset.DoAfterDelete;
  217. begin
  218. If assigned(FAfterDelete) then
  219. FAfterDelete(Self);
  220. end;
  221. Procedure TDataset.DoAfterEdit;
  222. begin
  223. If assigned(FAfterEdit) then
  224. FAfterEdit(Self);
  225. end;
  226. Procedure TDataset.DoAfterInsert;
  227. begin
  228. If assigned(FAfterInsert) then
  229. FAfterInsert(Self);
  230. end;
  231. Procedure TDataset.DoAfterOpen;
  232. begin
  233. If assigned(FAfterOpen) then
  234. FAfterOpen(Self);
  235. end;
  236. Procedure TDataset.DoAfterPost;
  237. begin
  238. If assigned(FAfterPost) then
  239. FAfterPost(Self);
  240. end;
  241. Procedure TDataset.DoAfterScroll;
  242. begin
  243. If assigned(FAfterScroll) then
  244. FAfterScroll(Self);
  245. end;
  246. Procedure TDataset.DoAfterRefresh;
  247. begin
  248. If assigned(FAfterRefresh) then
  249. FAfterRefresh(Self);
  250. end;
  251. Procedure TDataset.DoBeforeCancel;
  252. begin
  253. If assigned(FBeforeCancel) then
  254. FBeforeCancel(Self);
  255. end;
  256. Procedure TDataset.DoBeforeClose;
  257. begin
  258. If assigned(FBeforeClose) then
  259. FBeforeClose(Self);
  260. end;
  261. Procedure TDataset.DoBeforeDelete;
  262. begin
  263. If assigned(FBeforeDelete) then
  264. FBeforeDelete(Self);
  265. end;
  266. Procedure TDataset.DoBeforeEdit;
  267. begin
  268. If assigned(FBeforeEdit) then
  269. FBeforeEdit(Self);
  270. end;
  271. Procedure TDataset.DoBeforeInsert;
  272. begin
  273. If assigned(FBeforeInsert) then
  274. FBeforeInsert(Self);
  275. end;
  276. Procedure TDataset.DoBeforeOpen;
  277. begin
  278. If assigned(FBeforeOpen) then
  279. FBeforeOpen(Self);
  280. end;
  281. Procedure TDataset.DoBeforePost;
  282. begin
  283. If assigned(FBeforePost) then
  284. FBeforePost(Self);
  285. end;
  286. Procedure TDataset.DoBeforeScroll;
  287. begin
  288. If assigned(FBeforeScroll) then
  289. FBeforeScroll(Self);
  290. end;
  291. Procedure TDataset.DoBeforeRefresh;
  292. begin
  293. If assigned(FBeforeRefresh) then
  294. FBeforeRefresh(Self);
  295. end;
  296. Procedure TDataset.DoInternalOpen;
  297. begin
  298. FDefaultFields:=FieldCount=0;
  299. DoBeforeOpen;
  300. Try
  301. {$ifdef dsdebug}
  302. Writeln ('Calling internal open');
  303. {$endif}
  304. InternalOpen;
  305. FBOF:=True;
  306. {$ifdef dsdebug}
  307. Writeln ('Calling RecalcBufListSize');
  308. {$endif}
  309. FRecordcount := 0;
  310. RecalcBufListSize;
  311. FEOF := (FRecordcount = 0);
  312. {$ifdef dsdebug}
  313. Writeln ('Setting state to browse');
  314. {$endif}
  315. SetState(dsBrowse);
  316. DoAfterOpen;
  317. DoAfterScroll;
  318. except
  319. DoInternalClose;
  320. raise;
  321. end;
  322. end;
  323. Procedure TDataset.DoInternalClose;
  324. begin
  325. DoBeforeScroll;
  326. DoBeforeClose;
  327. FreeFieldBuffers;
  328. ClearBuffers;
  329. SetBufListSize(-1);
  330. SetState(dsInactive);
  331. InternalClose;
  332. DoAfterClose;
  333. end;
  334. Procedure TDataset.DoOnCalcFields;
  335. begin
  336. If assigned(FOnCalcfields) then
  337. FOnCalcFields(Self);
  338. end;
  339. Procedure TDataset.DoOnNewRecord;
  340. begin
  341. If assigned(FOnNewRecord) then
  342. FOnNewRecord(Self);
  343. end;
  344. Function TDataset.FieldByNumber(FieldNo: Longint): TField;
  345. begin
  346. Result:=FFieldList.FieldByNumber(FieldNo);
  347. end;
  348. Function TDataset.FindRecord(Restart, GoForward: Boolean): Boolean;
  349. begin
  350. //!! To be implemented
  351. end;
  352. Procedure TDataset.FreeFieldBuffers;
  353. Var I : longint;
  354. begin
  355. For I:=0 to FFieldList.Count-1 do
  356. FFieldList[i].FreeBuffers;
  357. end;
  358. Function TDataset.GetBookmarkStr: TBookmarkStr;
  359. begin
  360. Result:='';
  361. If BookMarkAvailable then
  362. begin
  363. SetLength(Result,FBookMarkSize);
  364. GetBookMarkData(ActiveBuffer,Pointer(Result));
  365. end
  366. end;
  367. Function TDataset.GetBuffer (Index : longint) : Pchar;
  368. begin
  369. Result:=FBuffers[Index];
  370. end;
  371. Procedure TDataset.GetCalcFields(Buffer: PChar);
  372. var
  373. dss: TDataSetState;
  374. begin
  375. if (FCalcFieldsSize > 0) or FInternalCalcFields then
  376. begin
  377. dss := FState;
  378. FState := dsCalcFields;
  379. try
  380. CalculateFields(Buffer);
  381. finally
  382. FState := dss;
  383. end;
  384. end;
  385. end;
  386. Function TDataset.GetCanModify: Boolean;
  387. begin
  388. Result:= not FIsUnidirectional;
  389. end;
  390. Procedure TDataset.GetChildren(Proc: TGetChildProc; Root: TComponent);
  391. var
  392. I: Integer;
  393. Field: TField;
  394. begin
  395. for I := 0 to Fields.Count - 1 do begin
  396. Field := Fields[I];
  397. if (Field.Owner = Root) then
  398. Proc(Field);
  399. end;
  400. end;
  401. Function TDataset.GetDataSource: TDataSource;
  402. begin
  403. Result:=nil;
  404. end;
  405. function TDataSet.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
  406. begin
  407. Result := False;
  408. end;
  409. function TDataSet.GetFieldData(Field: TField; Buffer: Pointer;
  410. NativeFormat: Boolean): Boolean;
  411. Var
  412. DT : TFieldType;
  413. DTRBuffer : TDateTimeRec;
  414. begin
  415. If NativeFormat then
  416. Result:=GetFieldData(Field, Buffer)
  417. else
  418. begin
  419. DT := Field.DataType;
  420. case DT of
  421. ftDate, ftTime, ftDateTime: begin
  422. Result := GetfieldData(Field, @DTRBuffer);
  423. TDateTime(buffer^) := DateTimeRecToDateTime(DT, DTRBuffer);
  424. end
  425. else
  426. Result:=GetFieldData(Field, Buffer)
  427. end;
  428. end;
  429. end;
  430. Function DateTimeRecToDateTime(DT: TFieldType; Data: TDateTimeRec): TDateTime;
  431. var
  432. TS: TTimeStamp;
  433. begin
  434. TS.Date:=0;
  435. TS.Time:=0;
  436. case DT of
  437. ftDate: TS.Date := Data.Date;
  438. ftTime: With TS do
  439. begin
  440. Time := Data.Time;
  441. Date := DateDelta;
  442. end;
  443. else
  444. try
  445. TS:=MSecsToTimeStamp(trunc(Data.DateTime));
  446. except
  447. end;
  448. end;
  449. Result:=TimeStampToDateTime(TS);
  450. end;
  451. Function DateTimeToDateTimeRec(DT: TFieldType; Data: TDateTime): TDateTimeRec;
  452. var
  453. TS : TTimeStamp;
  454. begin
  455. TS:=DateTimeToTimeStamp(Data);
  456. With Result do
  457. case DT of
  458. ftDate:
  459. Date:=TS.Date;
  460. ftTime:
  461. Time:=TS.Time;
  462. else
  463. DateTime:=TimeStampToMSecs(TS);
  464. end;
  465. end;
  466. procedure TDataSet.SetFieldData(Field: TField; Buffer: Pointer);
  467. begin
  468. // empty procedure
  469. end;
  470. procedure TDataSet.SetFieldData(Field: TField; Buffer: Pointer;
  471. NativeFormat: Boolean);
  472. Var
  473. DT : TFieldType;
  474. DTRBuffer : TDateTimeRec;
  475. begin
  476. if NativeFormat then
  477. SetFieldData(Field, Buffer)
  478. else
  479. begin
  480. DT := Field.DataType;
  481. case DT of
  482. ftDate, ftTime, ftDateTime: begin
  483. DTRBuffer := DateTimeToDateTimeRec(DT,TDateTime(buffer^));
  484. SetFieldData(Field,@DTRBuffer);
  485. end
  486. else
  487. SetFieldData(Field, Buffer);
  488. end; {case};
  489. end;
  490. end;
  491. Function TDataset.GetField (Index : Longint) : TField;
  492. begin
  493. Result:=FFIeldList[index];
  494. end;
  495. Function TDataset.GetFieldClass(FieldType: TFieldType): TFieldClass;
  496. begin
  497. Result := DefaultFieldClasses[FieldType];
  498. end;
  499. Function TDataset.GetIsIndexField(Field: TField): Boolean;
  500. begin
  501. //!! To be implemented
  502. end;
  503. Function TDataset.GetNextRecord: Boolean;
  504. procedure ExchangeBuffers(var buf1,buf2 : pointer);
  505. var tempbuf : pointer;
  506. begin
  507. tempbuf := buf1;
  508. buf1 := buf2;
  509. buf2 := tempbuf;
  510. end;
  511. begin
  512. {$ifdef dsdebug}
  513. Writeln ('Getting next record. Internal RecordCount : ',FRecordCount);
  514. {$endif}
  515. If FRecordCount>0 Then SetCurrentRecord(FRecordCount-1);
  516. Result:=GetRecord(FBuffers[FBuffercount],gmNext,True)=grOK;
  517. if result then
  518. begin
  519. If FRecordCount=0 then ActivateBuffers;
  520. if FRecordcount=FBuffercount then
  521. shiftbuffersbackward
  522. else
  523. begin
  524. inc(FRecordCount);
  525. FCurrentRecord:=FRecordCount - 1;
  526. ExchangeBuffers(Fbuffers[FCurrentRecord],FBuffers[FBuffercount]);
  527. end;
  528. end
  529. else
  530. cursorposchanged;
  531. {$ifdef dsdebug}
  532. Writeln ('Result getting next record : ',Result);
  533. {$endif}
  534. end;
  535. Function TDataset.GetNextRecords: Longint;
  536. begin
  537. Result:=0;
  538. {$ifdef dsdebug}
  539. Writeln ('Getting next record(s), need :',FBufferCount);
  540. {$endif}
  541. While (FRecordCount<FBufferCount) and GetNextRecord do
  542. Inc(Result);
  543. {$ifdef dsdebug}
  544. Writeln ('Result Getting next record(S), GOT :',RESULT);
  545. {$endif}
  546. end;
  547. Function TDataset.GetPriorRecord: Boolean;
  548. begin
  549. {$ifdef dsdebug}
  550. Writeln ('GetPriorRecord: Getting previous record');
  551. {$endif}
  552. If FRecordCount>0 Then SetCurrentRecord(0);
  553. Result:=GetRecord(FBuffers[FBuffercount],gmPrior,True)=grOK;
  554. if result then
  555. begin
  556. If FRecordCount=0 then ActivateBuffers;
  557. shiftbuffersforward;
  558. if FRecordcount<FBuffercount then
  559. inc(FRecordCount);
  560. end
  561. else
  562. cursorposchanged;
  563. {$ifdef dsdebug}
  564. Writeln ('Result getting prior record : ',Result);
  565. {$endif}
  566. end;
  567. Function TDataset.GetPriorRecords: Longint;
  568. begin
  569. Result:=0;
  570. {$ifdef dsdebug}
  571. Writeln ('Getting previous record(s), need :',FBufferCount);
  572. {$endif}
  573. While (FRecordCount<FbufferCount) and GetPriorRecord do
  574. Inc(Result);
  575. end;
  576. Function TDataset.GetRecNo: Longint;
  577. begin
  578. Result := -1;
  579. end;
  580. Function TDataset.GetRecordCount: Longint;
  581. begin
  582. Result := -1;
  583. end;
  584. Procedure TDataset.InitFieldDefs;
  585. begin
  586. if IsCursorOpen then InternalInitFieldDefs
  587. else
  588. try
  589. OpenCursor(True);
  590. finally
  591. CloseCursor;
  592. end;
  593. end;
  594. Procedure TDataset.InitRecord(Buffer: PChar);
  595. begin
  596. InternalInitRecord(Buffer);
  597. ClearCalcFields(Buffer);
  598. end;
  599. Procedure TDataset.InternalCancel;
  600. begin
  601. //!! To be implemented
  602. end;
  603. Procedure TDataset.InternalEdit;
  604. begin
  605. //!! To be implemented
  606. end;
  607. Procedure TDataset.InternalRefresh;
  608. begin
  609. //!! To be implemented
  610. end;
  611. Procedure TDataset.OpenCursor(InfoQuery: Boolean);
  612. begin
  613. //!! To be implemented
  614. end;
  615. Procedure TDataset.RefreshInternalCalcFields(Buffer: PChar);
  616. begin
  617. //!! To be implemented
  618. end;
  619. Function TDataset.SetTempState(const Value: TDataSetState): TDataSetState;
  620. begin
  621. result := FState;
  622. FState := value;
  623. inc(FDisableControlsCount);
  624. end;
  625. Procedure TDataset.RestoreState(const Value: TDataSetState);
  626. begin
  627. FState := value;
  628. dec(FDisableControlsCount);
  629. end;
  630. function TDataset.GetActive : boolean;
  631. begin
  632. result := FState <> dsInactive;
  633. end;
  634. Procedure TDataset.InternalHandleException;
  635. begin
  636. if assigned(classes.ApplicationHandleException) then
  637. classes.ApplicationHandleException(self)
  638. else
  639. ShowException(ExceptObject,ExceptAddr);
  640. end;
  641. Procedure TDataset.SetActive (Value : Boolean);
  642. begin
  643. if value and (Fstate = dsInactive) then
  644. begin
  645. if csLoading in ComponentState then
  646. begin
  647. FOpenAfterRead := true;
  648. exit;
  649. end
  650. else
  651. DoInternalOpen;
  652. end
  653. else if not value and (Fstate <> dsinactive) then
  654. DoInternalClose;
  655. end;
  656. procedure TDataset.Loaded;
  657. begin
  658. inherited;
  659. try
  660. if FOpenAfterRead then SetActive(true);
  661. except
  662. if csDesigning in Componentstate then
  663. InternalHandleException
  664. else
  665. raise;
  666. end;
  667. end;
  668. procedure TDataSet.RecalcBufListSize;
  669. var
  670. i, j, ABufferCount: Integer;
  671. DataLink: TDataLink;
  672. begin
  673. {$ifdef dsdebug}
  674. Writeln('Recalculating buffer list size - check cursor');
  675. {$endif}
  676. If Not IsCursorOpen Then
  677. Exit;
  678. {$ifdef dsdebug}
  679. Writeln('Recalculating buffer list size');
  680. {$endif}
  681. ABufferCount := DefaultBufferCount;
  682. for i := 0 to FDataSources.Count - 1 do
  683. for j := 0 to TDataSource(FDataSources[i]).DataLinks.Count - 1 do
  684. begin
  685. DataLink:=TDataLink(TDataSource(FDataSources[i]).DataLinks[j]);
  686. if DataLink.BufferCount>ABufferCount then
  687. ABufferCount:=DataLink.BufferCount;
  688. end;
  689. If (FBufferCount=ABufferCount) Then
  690. exit;
  691. {$ifdef dsdebug}
  692. Writeln('Setting buffer list size');
  693. {$endif}
  694. SetBufListSize(ABufferCount);
  695. {$ifdef dsdebug}
  696. Writeln('Getting next buffers');
  697. {$endif}
  698. GetNextRecords;
  699. {$Ifdef dsDebug}
  700. WriteLn(
  701. 'SetBufferCount: FActiveRecord=',FActiveRecord,
  702. ' FCurrentRecord=',FCurrentRecord,
  703. ' FBufferCount= ',FBufferCount,
  704. ' FRecordCount=',FRecordCount);
  705. {$Endif}
  706. end;
  707. Procedure TDataset.SetBookmarkStr(const Value: TBookmarkStr);
  708. begin
  709. GotoBookMark(Pointer(Value))
  710. end;
  711. Procedure TDataset.SetBufListSize(Value: Longint);
  712. Var I : longint;
  713. begin
  714. {$ifdef dsdebug}
  715. Writeln ('SetBufListSize: ',Value);
  716. {$endif}
  717. If Value=FBufferCount Then
  718. exit;
  719. If Value>FBufferCount then
  720. begin
  721. {$ifdef dsdebug}
  722. Writeln (' Reallocating memory :',(Value+1)*SizeOf(PChar));
  723. {$endif}
  724. ReAllocMem(FBuffers,(Value+1)*SizeOf(PChar));
  725. {$ifdef dsdebug}
  726. Writeln (' Filling memory :',(Value+1-FBufferCount)*SizeOf(PChar));
  727. {$endif}
  728. if FBufferCount > 0 then inc(FBufferCount); // Cause FBuffers[FBufferCount] is already allocated
  729. FillChar(FBuffers[FBufferCount],(Value+1-FBufferCount)*SizeOF(Pchar),#0);
  730. {$ifdef dsdebug}
  731. Writeln (' Filled memory :');
  732. {$endif}
  733. Try
  734. {$ifdef dsdebug}
  735. Writeln (' Assigning buffers :',(Value)*SizeOf(PChar));
  736. {$endif}
  737. For I:=FBufferCount to Value do
  738. FBuffers[i]:=AllocRecordBuffer;
  739. {$ifdef dsdebug}
  740. Writeln (' Assigned buffers ',FBufferCount,' :',(Value)*SizeOf(PChar));
  741. {$endif}
  742. except
  743. I:=FBufferCount;
  744. While (I<(Value+1)) do
  745. begin
  746. FreeRecordBuffer(FBuffers[i]);
  747. Inc(i);
  748. end;
  749. raise;
  750. end;
  751. end
  752. else
  753. begin
  754. {$ifdef dsdebug}
  755. Writeln (' Freeing buffers :',FBufferCount-Value);
  756. {$endif}
  757. if (value > -1) and (FActiveRecord>Value-1) then
  758. begin
  759. for i := 0 to (FActiveRecord-Value) do
  760. shiftbuffersbackward;
  761. FActiverecord := Value -1;
  762. end;
  763. If Assigned(FBuffers) then
  764. begin
  765. For I:=Value+1 to FBufferCount do
  766. FreeRecordBuffer(FBuffers[i]);
  767. // FBuffer must stay allocated, to make sure that Activebuffer returns nil
  768. if Value = -1 then
  769. begin
  770. ReAllocMem(FBuffers,SizeOf(Pchar));
  771. FBuffers[0] := nil;
  772. end
  773. else
  774. ReAllocMem(FBuffers,(Value+1)*SizeOf(Pchar));
  775. end;
  776. if FRecordcount > Value then FRecordcount := Value;
  777. end;
  778. If Value=-1 then
  779. Value:=0;
  780. FBufferCount:=Value;
  781. {$ifdef dsdebug}
  782. Writeln (' SetBufListSize: Final FBufferCount=',FBufferCount);
  783. {$endif}
  784. end;
  785. Procedure TDataset.SetChildOrder(Component: TComponent; Order: Longint);
  786. var
  787. Field: TField;
  788. begin
  789. Field := Component as TField;
  790. if Fields.IndexOf(Field) >= 0 then
  791. Field.Index := Order;
  792. end;
  793. Procedure TDataset.SetCurrentRecord(Index: Longint);
  794. begin
  795. If FCurrentRecord<>Index then
  796. begin
  797. {$ifdef DSdebug}
  798. Writeln ('Setting current record to',index);
  799. {$endif}
  800. Case GetBookMarkFlag(FBuffers[Index]) of
  801. bfCurrent : InternalSetToRecord(FBuffers[Index]);
  802. bfBOF : InternalFirst;
  803. bfEOF : InternalLast;
  804. end;
  805. FCurrentRecord:=index;
  806. end;
  807. end;
  808. Procedure TDataset.SetField (Index : Longint;Value : TField);
  809. begin
  810. //!! To be implemented
  811. end;
  812. Procedure TDataset.CheckBiDirectional;
  813. begin
  814. if FIsUniDirectional then DataBaseError(SUniDirectional);
  815. end;
  816. Procedure TDataset.SetFilterOptions(Value: TFilterOptions);
  817. begin
  818. CheckBiDirectional;
  819. FFilterOptions := Value;
  820. end;
  821. Procedure TDataset.SetFilterText(const Value: string);
  822. begin
  823. FFilterText := value;
  824. end;
  825. Procedure TDataset.SetFiltered(Value: Boolean);
  826. begin
  827. FFiltered := value;
  828. end;
  829. Procedure TDataset.SetFound(const Value: Boolean);
  830. begin
  831. FFound := Value;
  832. end;
  833. Procedure TDataset.SetModified(Value: Boolean);
  834. begin
  835. FModified := value;
  836. end;
  837. Procedure TDataset.SetName(const Value: TComponentName);
  838. function CheckName(FieldName: string): string;
  839. var i,j: integer;
  840. begin
  841. Result := FieldName;
  842. i := 0;
  843. j := 0;
  844. while (i < Fields.Count) do begin
  845. if Result = Fields[i].FieldName then begin
  846. inc(j);
  847. Result := FieldName + IntToStr(j);
  848. end else Inc(i);
  849. end;
  850. end;
  851. var i: integer;
  852. nm: string;
  853. old: string;
  854. begin
  855. if Self.Name = Value then Exit;
  856. old := Self.Name;
  857. inherited SetName(Value);
  858. if (csDesigning in ComponentState) then
  859. for i := 0 to Fields.Count - 1 do begin
  860. nm := old + Fields[i].FieldName;
  861. if Copy(Fields[i].Name, 1, Length(nm)) = nm then
  862. Fields[i].Name := CheckName(Value + Fields[i].FieldName);
  863. end;
  864. end;
  865. Procedure TDataset.SetOnFilterRecord(const Value: TFilterRecordEvent);
  866. begin
  867. CheckBiDirectional;
  868. FOnFilterRecord := Value;
  869. end;
  870. Procedure TDataset.SetRecNo(Value: Longint);
  871. begin
  872. //!! To be implemented
  873. end;
  874. Procedure TDataset.SetState(Value: TDataSetState);
  875. begin
  876. If Value<>FState then
  877. begin
  878. FState:=Value;
  879. DataEvent(deUpdateState,0);
  880. end;
  881. end;
  882. Function TDataset.Tempbuffer: PChar;
  883. begin
  884. Result := FBuffers[FRecordCount];
  885. end;
  886. Procedure TDataset.UpdateIndexDefs;
  887. begin
  888. // Empty Abstract
  889. end;
  890. Function TDataset.ControlsDisabled: Boolean;
  891. begin
  892. Result := (FDisableControlsCount > 0);
  893. end;
  894. Function TDataset.ActiveBuffer: PChar;
  895. begin
  896. {$ifdef dsdebug}
  897. Writeln ('Active buffer requested. Returning:',ActiveRecord);
  898. {$endif}
  899. Result:=FBuffers[FActiveRecord];
  900. end;
  901. Procedure TDataset.Append;
  902. begin
  903. DoInsertAppend(True);
  904. end;
  905. Procedure TDataset.InternalInsert;
  906. begin
  907. //!! To be implemented
  908. end;
  909. Procedure TDataset.AppendRecord(const Values: array of const);
  910. begin
  911. //!! To be implemented
  912. end;
  913. Function TDataset.BookmarkValid(ABookmark: TBookmark): Boolean;
  914. {
  915. Should be overridden by descendant objects.
  916. }
  917. begin
  918. Result:=False
  919. end;
  920. Procedure TDataset.Cancel;
  921. begin
  922. If State in [dsEdit,dsInsert] then
  923. begin
  924. DataEvent(deCheckBrowseMode,0);
  925. DoBeforeCancel;
  926. UpdateCursorPos;
  927. InternalCancel;
  928. FreeFieldBuffers;
  929. if (state = dsInsert) and (FRecordcount = 1) then
  930. begin
  931. FEOF := true;
  932. FBOF := true;
  933. FRecordcount := 0;
  934. SetState(dsBrowse);
  935. DataEvent(deDatasetChange,0);
  936. end
  937. else
  938. begin
  939. SetState(dsBrowse);
  940. SetCurrentRecord(FActiverecord);
  941. resync([]);
  942. end;
  943. DoAfterCancel;
  944. end;
  945. end;
  946. Procedure TDataset.CheckBrowseMode;
  947. begin
  948. CheckActive;
  949. DataEvent(deCheckBrowseMode,0);
  950. Case State of
  951. dsedit,dsinsert: begin
  952. UpdateRecord;
  953. If Modified then Post else Cancel;
  954. end;
  955. dsSetKey: Post;
  956. end;
  957. end;
  958. Procedure TDataset.ClearFields;
  959. begin
  960. DataEvent(deCheckBrowseMode, 0);
  961. FreeFieldBuffers;
  962. InternalInitRecord(ActiveBuffer);
  963. if State <> dsSetKey then GetCalcFields(ActiveBuffer);
  964. DataEvent(deRecordChange, 0);
  965. end;
  966. Procedure TDataset.Close;
  967. begin
  968. Active:=False;
  969. end;
  970. Function TDataset.CompareBookmarks(Bookmark1, Bookmark2: TBookmark): Longint;
  971. begin
  972. Result:=0;
  973. end;
  974. Function TDataset.CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream;
  975. begin
  976. Result:=Nil;
  977. end;
  978. Procedure TDataset.CursorPosChanged;
  979. begin
  980. FCurrentRecord:=-1;
  981. end;
  982. Procedure TDataset.Delete;
  983. begin
  984. If Not CanModify then
  985. DatabaseError(SDatasetReadOnly,Self);
  986. If IsEmpty then
  987. DatabaseError(SDatasetEmpty,Self);
  988. if State in [dsInsert] then
  989. begin
  990. Cancel;
  991. end else begin
  992. DataEvent(deCheckBrowseMode,0);
  993. {$ifdef dsdebug}
  994. writeln ('Delete: checking required fields');
  995. {$endif}
  996. DoBeforeDelete;
  997. DoBeforeScroll;
  998. If Not TryDoing(@InternalDelete,OnPostError) then exit;
  999. {$ifdef dsdebug}
  1000. writeln ('Delete: Internaldelete succeeded');
  1001. {$endif}
  1002. FreeFieldBuffers;
  1003. SetState(dsBrowse);
  1004. {$ifdef dsdebug}
  1005. writeln ('Delete: Browse mode set');
  1006. {$endif}
  1007. SetCurrentRecord(FActiverecord);
  1008. Resync([]);
  1009. DoAfterDelete;
  1010. DoAfterScroll;
  1011. end;
  1012. end;
  1013. Procedure TDataset.DisableControls;
  1014. begin
  1015. If FDisableControlsCount=0 then
  1016. begin
  1017. { Save current state,
  1018. needed to detect change of state when enabling controls.
  1019. }
  1020. FDisableControlsState:=FState;
  1021. FEnableControlsEvent:=deDatasetChange;
  1022. end;
  1023. Inc(FDisableControlsCount);
  1024. end;
  1025. Procedure TDataset.DoInsertAppend(DoAppend : Boolean);
  1026. procedure DoInsert(DoAppend : Boolean);
  1027. Var BookBeforeInsert : TBookmarkStr;
  1028. TempBuf : pointer;
  1029. begin
  1030. // need to scroll up al buffers after current one,
  1031. // but copy current bookmark to insert buffer.
  1032. If FRecordcount > 0 then
  1033. BookBeforeInsert:=Bookmark;
  1034. if not DoAppend then
  1035. begin
  1036. if FRecordCount > 0 then
  1037. begin
  1038. TempBuf := FBuffers[FBuffercount];
  1039. move(FBuffers[FActiveRecord],FBuffers[FActiveRecord+1],(Fbuffercount-FActiveRecord)*sizeof(FBuffers[0]));
  1040. FBuffers[FActiveRecord]:=TempBuf;
  1041. end;
  1042. end
  1043. else if FRecordcount=FBuffercount then
  1044. shiftbuffersbackward
  1045. else
  1046. begin
  1047. if FRecordCount>0 then
  1048. inc(FActiveRecord);
  1049. end;
  1050. // Active buffer is now edit buffer. Initialize.
  1051. InitRecord(FBuffers[FActiveRecord]);
  1052. cursorposchanged;
  1053. // Put bookmark in edit buffer.
  1054. if FRecordCount=0 then
  1055. begin
  1056. fEOF := false;
  1057. SetBookmarkFlag(ActiveBuffer,bfBOF)
  1058. end
  1059. else
  1060. begin
  1061. fBOF := false;
  1062. // 29:01:05, JvdS: Why is this here?!? It can result in records with the same bookmark-data?
  1063. // I would say that the 'internalinsert' should do this. But I don't know how Tdbf handles it
  1064. // 1-apr-06, JvdS: It just sets the bookmark of the newly inserted record to the place
  1065. // where the record should be inserted. So it is ok.
  1066. if FRecordcount > 0 then
  1067. SetBookMarkData(ActiveBuffer,pointer(BookBeforeInsert));
  1068. end;
  1069. InternalInsert;
  1070. // update buffer count.
  1071. If FRecordCount<FBufferCount then
  1072. Inc(FRecordCount);
  1073. end;
  1074. begin
  1075. If Not CanModify then
  1076. DatabaseError(SDatasetReadOnly,Self);
  1077. CheckBrowseMode;
  1078. DoBeforeInsert;
  1079. DoBeforeScroll;
  1080. If Not DoAppend then
  1081. begin
  1082. {$ifdef dsdebug}
  1083. Writeln ('going to insert mode');
  1084. {$endif}
  1085. DoInsert(false);
  1086. end
  1087. else
  1088. begin
  1089. {$ifdef dsdebug}
  1090. Writeln ('going to append mode');
  1091. {$endif}
  1092. ClearBuffers;
  1093. InternalLast;
  1094. GetPriorRecords;
  1095. if FRecordCount>0 then
  1096. FActiveRecord:=FRecordCount-1;
  1097. DoInsert(True);
  1098. SetBookmarkFlag(ActiveBuffer,bfEOF);
  1099. FBOF :=False;
  1100. FEOF := true;
  1101. end;
  1102. SetState(dsInsert);
  1103. try
  1104. DoOnNewRecord;
  1105. except
  1106. SetCurrentRecord(FActiverecord);
  1107. resync([]);
  1108. raise;
  1109. end;
  1110. // mark as not modified.
  1111. FModified:=False;
  1112. // Final events.
  1113. DataEvent(deDatasetChange,0);
  1114. DoAfterInsert;
  1115. DoAfterScroll;
  1116. {$ifdef dsdebug}
  1117. Writeln ('Done with append');
  1118. {$endif}
  1119. end;
  1120. Procedure TDataset.Edit;
  1121. begin
  1122. If Not CanModify then
  1123. DatabaseError(SDatasetReadOnly,Self);
  1124. If State in [dsedit,dsinsert] then exit;
  1125. If FRecordCount = 0 then
  1126. begin
  1127. Append;
  1128. Exit;
  1129. end;
  1130. CheckBrowseMode;
  1131. DoBeforeEdit;
  1132. If Not TryDoing(@InternalEdit,OnEditError) then
  1133. exit;
  1134. GetCalcFields(ActiveBuffer);
  1135. SetState(dsedit);
  1136. DataEvent(deRecordChange,0);
  1137. DoAfterEdit;
  1138. end;
  1139. Procedure TDataset.EnableControls;
  1140. begin
  1141. If FDisableControlsCount>0 then
  1142. begin
  1143. Dec(FDisableControlsCount);
  1144. If FDisableControlsCount=0 then
  1145. begin
  1146. // State changed since disablecontrols ?
  1147. If FDisableControlsState<>FState then
  1148. DataEvent(deUpdateState,0);
  1149. If (FDisableControlsState<>dsInactive) and (FState<>dsInactive) then
  1150. DataEvent(FEnableControlsEvent,0);
  1151. end;
  1152. end;
  1153. end;
  1154. Function TDataset.FieldByName(const FieldName: string): TField;
  1155. begin
  1156. Result:=FindField(FieldName);
  1157. If Result=Nil then
  1158. DatabaseErrorFmt(SFieldNotFound,[FieldName],Self);
  1159. end;
  1160. Function TDataset.FindField(const FieldName: string): TField;
  1161. begin
  1162. Result:=FFieldList.FindField(FieldName);
  1163. end;
  1164. Function TDataset.FindFirst: Boolean;
  1165. begin
  1166. //!! To be implemented
  1167. end;
  1168. Function TDataset.FindLast: Boolean;
  1169. begin
  1170. //!! To be implemented
  1171. end;
  1172. Function TDataset.FindNext: Boolean;
  1173. begin
  1174. //!! To be implemented
  1175. end;
  1176. Function TDataset.FindPrior: Boolean;
  1177. begin
  1178. //!! To be implemented
  1179. end;
  1180. Procedure TDataset.First;
  1181. begin
  1182. CheckBrowseMode;
  1183. DoBeforeScroll;
  1184. ClearBuffers;
  1185. try
  1186. InternalFirst;
  1187. GetNextRecords;
  1188. finally
  1189. FBOF:=True;
  1190. DataEvent(deDatasetChange,0);
  1191. DoAfterScroll;
  1192. end;
  1193. end;
  1194. Procedure TDataset.FreeBookmark(ABookmark: TBookmark);
  1195. begin
  1196. FreeMem(ABookMark,FBookMarkSize);
  1197. end;
  1198. Function TDataset.GetBookmark: TBookmark;
  1199. begin
  1200. if BookmarkAvailable then
  1201. begin
  1202. GetMem (Result,FBookMarkSize);
  1203. GetBookMarkdata(ActiveBuffer,Result);
  1204. end
  1205. else
  1206. Result:=Nil;
  1207. end;
  1208. Function TDataset.GetCurrentRecord(Buffer: PChar): Boolean;
  1209. begin
  1210. Result:=False;
  1211. end;
  1212. Procedure TDataset.GetFieldList(List: TList; const FieldNames: string);
  1213. Function NextName(Var S : String) : String;
  1214. Var
  1215. P : integer;
  1216. begin
  1217. P:=Pos(';',S);
  1218. If (P=0) then
  1219. P:=Length(S)+1;
  1220. Result:=Copy(S,1,P-1);
  1221. system.Delete(S,1,P);
  1222. end;
  1223. var
  1224. F: TField;
  1225. Names,N : String;
  1226. begin
  1227. Names:=FieldNames;
  1228. N:=Nextname(Names);
  1229. while (N<>'') do
  1230. begin
  1231. F:=FieldByName(N);
  1232. If Assigned(List) then
  1233. List.Add(F);
  1234. N:=NextName(Names);
  1235. end;
  1236. end;
  1237. Procedure TDataset.GetFieldNames(List: TStrings);
  1238. begin
  1239. FFieldList.GetFieldNames(List);
  1240. end;
  1241. Procedure TDataset.GotoBookmark(ABookmark: TBookmark);
  1242. begin
  1243. If Assigned(ABookMark) then
  1244. begin
  1245. CheckBrowseMode;
  1246. DoBeforeScroll;
  1247. InternalGotoBookMark(ABookMark);
  1248. Resync([rmExact,rmCenter]);
  1249. DoAfterScroll;
  1250. end;
  1251. end;
  1252. Procedure TDataset.Insert;
  1253. begin
  1254. DoInsertAppend(False);
  1255. end;
  1256. Procedure TDataset.InsertRecord(const Values: array of const);
  1257. begin
  1258. //!! To be implemented
  1259. end;
  1260. Function TDataset.IsEmpty: Boolean;
  1261. begin
  1262. Result:=(Bof and Eof);
  1263. end;
  1264. Function TDataset.IsLinkedTo(ADataSource: TDataSource): Boolean;
  1265. begin
  1266. //!! Not tested, I never used nested DS
  1267. if (ADataSource = nil) or (ADataSource.Dataset = nil) then begin
  1268. Result := False
  1269. end else if ADataSource.Dataset = Self then begin
  1270. Result := True;
  1271. end else begin
  1272. Result := ADataSource.Dataset.IsLinkedTo(ADataSource.Dataset.DataSource);
  1273. end;
  1274. //!! DataSetField not implemented
  1275. end;
  1276. Function TDataset.IsSequenced: Boolean;
  1277. begin
  1278. Result := True;
  1279. end;
  1280. Procedure TDataset.Last;
  1281. begin
  1282. CheckBrowseMode;
  1283. DoBeforeScroll;
  1284. ClearBuffers;
  1285. try
  1286. InternalLast;
  1287. GetPriorRecords;
  1288. if FRecordCount>0 then
  1289. FActiveRecord:=FRecordCount-1
  1290. finally
  1291. FEOF:=true;
  1292. DataEvent(deDataSetChange, 0);
  1293. DoAfterScroll;
  1294. end;
  1295. end;
  1296. Function TDataset.MoveBy(Distance: Longint): Longint;
  1297. Var
  1298. TheResult: Integer;
  1299. Function Scrollforward : Integer;
  1300. begin
  1301. Result:=0;
  1302. {$ifdef dsdebug}
  1303. Writeln('Scrolling forward :',Distance);
  1304. Writeln('Active buffer : ',FActiveRecord);
  1305. Writeln('RecordCount : ',FRecordCount);
  1306. WriteLn('BufferCount : ',FBufferCount);
  1307. {$endif}
  1308. FBOF:=False;
  1309. While (Distance>0) and not FEOF do
  1310. begin
  1311. If FActiveRecord<FRecordCount-1 then
  1312. begin
  1313. Inc(FActiveRecord);
  1314. Dec(Distance);
  1315. Inc(TheResult); //Inc(Result);
  1316. end
  1317. else
  1318. begin
  1319. {$ifdef dsdebug}
  1320. Writeln('Moveby : need next record');
  1321. {$endif}
  1322. If GetNextRecord then
  1323. begin
  1324. Dec(Distance);
  1325. Dec(Result);
  1326. Inc(TheResult); //Inc(Result);
  1327. end
  1328. else
  1329. FEOF:=true;
  1330. end;
  1331. end
  1332. end;
  1333. Function ScrollBackward : Integer;
  1334. begin
  1335. CheckBiDirectional;
  1336. Result:=0;
  1337. {$ifdef dsdebug}
  1338. Writeln('Scrolling backward:',Abs(Distance));
  1339. Writeln('Active buffer : ',FActiveRecord);
  1340. Writeln('RecordCunt : ',FRecordCount);
  1341. WriteLn('BufferCount : ',FBufferCount);
  1342. {$endif}
  1343. FEOF:=False;
  1344. While (Distance<0) and not FBOF do
  1345. begin
  1346. If FActiveRecord>0 then
  1347. begin
  1348. Dec(FActiveRecord);
  1349. Inc(Distance);
  1350. Dec(TheResult); //Dec(Result);
  1351. end
  1352. else
  1353. begin
  1354. {$ifdef dsdebug}
  1355. Writeln('Moveby : need next record');
  1356. {$endif}
  1357. If GetPriorRecord then
  1358. begin
  1359. Inc(Distance);
  1360. Inc(Result);
  1361. Dec(TheResult); //Dec(Result);
  1362. end
  1363. else
  1364. FBOF:=true;
  1365. end;
  1366. end
  1367. end;
  1368. Var
  1369. Scrolled : Integer;
  1370. begin
  1371. CheckBrowseMode;
  1372. Result:=0; TheResult:=0;
  1373. DoBeforeScroll;
  1374. If (Distance = 0) or
  1375. ((Distance>0) and FEOF) or
  1376. ((Distance<0) and FBOF) then
  1377. exit;
  1378. Try
  1379. Scrolled := 0;
  1380. If Distance>0 then
  1381. Scrolled:=ScrollForward
  1382. else
  1383. Scrolled:=ScrollBackward;
  1384. finally
  1385. {$ifdef dsdebug}
  1386. WriteLn('ActiveRecord=', FActiveRecord,' FEOF=',FEOF,' FBOF=',FBOF);
  1387. {$Endif}
  1388. DataEvent(deDatasetScroll,Scrolled);
  1389. DoAfterScroll;
  1390. Result:=TheResult;
  1391. end;
  1392. end;
  1393. Procedure TDataset.Next;
  1394. begin
  1395. MoveBy(1);
  1396. end;
  1397. Procedure TDataset.Open;
  1398. begin
  1399. Active:=True;
  1400. end;
  1401. Procedure TDataset.Post;
  1402. Procedure Checkrequired;
  1403. Var I : longint;
  1404. begin
  1405. For I:=0 to FFieldList.Count-1 do
  1406. With FFieldList[i] do
  1407. // Required fields that are NOT autoinc !! Autoinc cannot be set !!
  1408. if Required and not ReadOnly and
  1409. (FieldKind=fkData) and Not (DataType=ftAutoInc) then
  1410. DatabaseErrorFmt(SNeedField,[DisplayName],Self);
  1411. end;
  1412. begin
  1413. if State in [dsEdit,dsInsert] then
  1414. begin
  1415. DataEvent(deUpdateRecord,0);
  1416. DataEvent(deCheckBrowseMode,0);
  1417. {$ifdef dsdebug}
  1418. writeln ('Post: checking required fields');
  1419. {$endif}
  1420. CheckRequired;
  1421. DoBeforePost;
  1422. If Not TryDoing(@InternalPost,OnPostError) then exit;
  1423. cursorposchanged;
  1424. {$ifdef dsdebug}
  1425. writeln ('Post: Internalpost succeeded');
  1426. {$endif}
  1427. FreeFieldBuffers;
  1428. // First set the state to dsBrowse, then the Resync, to prevent the calling of
  1429. // the deDatasetChange event, while the state is still 'editable', while the db isn't
  1430. SetState(dsBrowse);
  1431. Resync([]);
  1432. {$ifdef dsdebug}
  1433. writeln ('Post: Browse mode set');
  1434. {$endif}
  1435. DoAfterPost;
  1436. end
  1437. else
  1438. DatabaseErrorFmt(SNotInEditState, [Name], Self);
  1439. end;
  1440. Procedure TDataset.Prior;
  1441. begin
  1442. MoveBy(-1);
  1443. end;
  1444. Procedure TDataset.Refresh;
  1445. begin
  1446. CheckbrowseMode;
  1447. DoBeforeRefresh;
  1448. UpdateCursorPos;
  1449. InternalRefresh;
  1450. { SetCurrentRecord is called by UpdateCursorPos already, so as long as
  1451. InternalRefresh doesn't do strange things this should be ok. }
  1452. // SetCurrentRecord(FActiverecord);
  1453. Resync([]);
  1454. DoAfterRefresh;
  1455. end;
  1456. Procedure TDataset.RegisterDataSource(ADatasource : TDataSource);
  1457. begin
  1458. FDatasources.Add(ADataSource);
  1459. RecalcBufListSize;
  1460. end;
  1461. Procedure TDataset.Resync(Mode: TResyncMode);
  1462. var i,count : integer;
  1463. begin
  1464. // See if we can find the requested record.
  1465. {$ifdef dsdebug}
  1466. Writeln ('Resync called');
  1467. {$endif}
  1468. // place the cursor of the underlying dataset to the active record
  1469. // SetCurrentRecord(FActiverecord);
  1470. // Now look if the data on the current cursor of the underlying dataset is still available
  1471. If GetRecord(Fbuffers[0],gmcurrent,False)<>grOk Then
  1472. // If that fails and rmExact is set, then raise an exception
  1473. If rmExact in Mode then
  1474. DatabaseError(SNoSuchRecord,Self)
  1475. // else, if rmexact is not set, try to fetch the next or prior record in the underlying dataset
  1476. else if (GetRecord(Fbuffers[0],gmnext,True)<>grOk) and
  1477. (GetRecord(Fbuffers[0],gmprior,True)<>grOk) then
  1478. begin
  1479. {$ifdef dsdebug}
  1480. Writeln ('Resync: fuzzy resync');
  1481. {$endif}
  1482. // nothing found, invalidate buffer and bail out.
  1483. ClearBuffers;
  1484. // Make sure that the active record is 'empty', ie: that all fields are null
  1485. InternalInitRecord(ActiveBuffer);
  1486. DataEvent(deDatasetChange,0);
  1487. exit;
  1488. end;
  1489. FCurrentRecord := 0;
  1490. FEOF := false;
  1491. FBOF := false;
  1492. // If we've arrived here, FBuffer[0] is the current record
  1493. If (rmCenter in Mode) then
  1494. count := (FRecordCount div 2)
  1495. else
  1496. count := FActiveRecord;
  1497. i := 0;
  1498. FRecordcount := 1;
  1499. FActiveRecord := 0;
  1500. // Fill the buffers before the active record
  1501. while (i < count) and GetPriorRecord do
  1502. inc(i);
  1503. FActiveRecord := i;
  1504. // Fill the rest of the buffer
  1505. getnextrecords;
  1506. // If the buffer is not full yet, try to fetch some more prior records
  1507. if FRecordcount < FBuffercount then inc(FActiverecord,getpriorrecords);
  1508. // That's all folks!
  1509. DataEvent(deDatasetChange,0);
  1510. end;
  1511. Procedure TDataset.SetFields(const Values: array of const);
  1512. Var I : longint;
  1513. begin
  1514. For I:=0 to high(Values) do
  1515. Fields[I].AssignValue(Values[I]);
  1516. end;
  1517. Function TDataset.Translate(Src, Dest: PChar; ToOem: Boolean): Integer;
  1518. begin
  1519. strcopy(dest,src);
  1520. end;
  1521. Function Tdataset.TryDoing (P : TDataOperation; Ev : TDatasetErrorEvent) : Boolean;
  1522. Var Retry : TDataAction;
  1523. begin
  1524. {$ifdef dsdebug}
  1525. Writeln ('Trying to do');
  1526. If P=Nil then writeln ('Procedure to call is nil !!!');
  1527. {$endif dsdebug}
  1528. Result:=True;
  1529. Retry:=daRetry;
  1530. while Retry=daRetry do
  1531. Try
  1532. {$ifdef dsdebug}
  1533. Writeln ('Trying : updatecursorpos');
  1534. {$endif dsdebug}
  1535. UpdateCursorPos;
  1536. {$ifdef dsdebug}
  1537. Writeln ('Trying to do it');
  1538. {$endif dsdebug}
  1539. P;
  1540. exit;
  1541. except
  1542. On E : EDatabaseError do
  1543. begin
  1544. retry:=daFail;
  1545. If Assigned(Ev) then
  1546. Ev(Self,E,Retry);
  1547. Case Retry of
  1548. daFail : Raise;
  1549. daAbort : Result:=False;
  1550. end;
  1551. end;
  1552. else
  1553. Raise;
  1554. end;
  1555. {$ifdef dsdebug}
  1556. Writeln ('Exit Trying to do');
  1557. {$endif dsdebug}
  1558. end;
  1559. Procedure TDataset.UpdateCursorPos;
  1560. begin
  1561. If FRecordCount>0 then
  1562. SetCurrentRecord(FactiveRecord);
  1563. end;
  1564. Procedure TDataset.UpdateRecord;
  1565. begin
  1566. if not (State in dsEditModes) then
  1567. DatabaseErrorFmt(SNotInEditState, [Name], Self);
  1568. DataEvent(deUpdateRecord, 0);
  1569. end;
  1570. Function TDataSet.UpdateStatus: TUpdateStatus;
  1571. begin
  1572. Result:=usUnmodified;
  1573. end;
  1574. Procedure TDataset.RemoveField (Field : TField);
  1575. begin
  1576. //!! To be implemented
  1577. end;
  1578. Function TDataset.Getfieldcount : Longint;
  1579. begin
  1580. Result:=FFieldList.Count;
  1581. end;
  1582. Procedure TDataset.ShiftBuffersBackward;
  1583. var TempBuf : pointer;
  1584. begin
  1585. TempBuf := FBuffers[0];
  1586. move(FBuffers[1],FBuffers[0],(fbuffercount)*sizeof(FBuffers[0]));
  1587. FBuffers[buffercount]:=TempBuf;
  1588. end;
  1589. Procedure TDataset.ShiftBuffersForward;
  1590. var TempBuf : pointer;
  1591. begin
  1592. TempBuf := FBuffers[FBufferCount];
  1593. move(FBuffers[0],FBuffers[1],(fbuffercount)*sizeof(FBuffers[0]));
  1594. FBuffers[0]:=TempBuf;
  1595. end;
  1596. function TDataset.GetFieldValues(Fieldname: string): Variant;
  1597. var i: Integer;
  1598. FieldList: TList;
  1599. begin
  1600. if Pos(';', FieldName) <> 0 then begin
  1601. FieldList := TList.Create;
  1602. try
  1603. GetFieldList(FieldList, FieldName);
  1604. Result := VarArrayCreate([0, FieldList.Count - 1], varVariant);
  1605. for i := 0 to FieldList.Count - 1 do
  1606. Result[i] := TField(FieldList[i]).Value;
  1607. finally
  1608. FieldList.Free;
  1609. end;
  1610. end else
  1611. Result := FieldByName(FieldName).Value
  1612. end;
  1613. procedure TDataset.SetFieldValues(Fieldname: string; Value: Variant);
  1614. var i: Integer;
  1615. FieldList: TList;
  1616. begin
  1617. if Pos(';', FieldName) <> 0 then
  1618. begin
  1619. FieldList := TList.Create;
  1620. try
  1621. GetFieldList(FieldList, FieldName);
  1622. for i := 0 to FieldList.Count - 1 do
  1623. TField(FieldList[i]).Value := Value[i];
  1624. finally
  1625. FieldList.Free;
  1626. end;
  1627. end else
  1628. FieldByName(FieldName).Value := Value;
  1629. end;
  1630. Function TDataset.Locate(const keyfields: string; const keyvalues: Variant; options: TLocateOptions) : boolean;
  1631. begin
  1632. CheckBiDirectional;
  1633. Result := False;
  1634. end;
  1635. Function TDataset.Lookup(const KeyFields: string; const KeyValues: Variant; const ResultFields: string): Variant;
  1636. begin
  1637. Result := False;
  1638. end;
  1639. Procedure TDataset.UnRegisterDataSource(ADatasource : TDatasource);
  1640. begin
  1641. FDataSources.Remove(ADataSource);
  1642. end;