dataset.inc 40 KB

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