dataset.inc 39 KB

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