dataset.inc 44 KB

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