dataset.inc 43 KB

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