sqldbrestdataset.pp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2019 by Michael Van Canneyt, member of the
  4. Free Pascal development team
  5. Simple SQLDBRESTBridge JSON dataset component and connection.
  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. unit sqldbrestdataset;
  13. {$mode objfpc}
  14. interface
  15. uses
  16. Classes, SysUtils, JS, web, db, JSONDataset, restconnection;
  17. Type
  18. { TSQLDBRestConnection }
  19. TSQLDBRestConnection = Class(TRestConnection)
  20. private
  21. FConnectionsResourceName: String;
  22. FCustomViewResourceName: String;
  23. FDataProperty: String;
  24. FmetaDataProperty: String;
  25. FMetaDataResourceName: String;
  26. FonGetResources: TNotifyEvent;
  27. FPassword: String;
  28. FResourceList: TStrings;
  29. FUserName: String;
  30. procedure DoResources(Sender: TObject);
  31. function DoStoreDataProp: Boolean;
  32. function DoStoreMetadata: Boolean;
  33. function DoStoreMetadataProp: Boolean;
  34. Protected
  35. Procedure SetupRequest(aXHR : TJSXMLHttpRequest); override;
  36. Function GetUpdateBaseURL(aRequest: TRecordUpdateDescriptor): String; override;
  37. Function GetReadBaseURL(aRequest: TDataRequest): String; Override;
  38. Public
  39. Constructor create(aOwner : TComponent); override;
  40. Destructor Destroy; override;
  41. Procedure GetResources(OnResult : TNotifyEvent = Nil);
  42. Property ResourceList : TStrings Read FResourceList;
  43. Published
  44. Property OnGetResources : TNotifyEvent Read FonGetResources Write FOnGetResources;
  45. Property metaDataProperty : String read FmetaDataProperty Write FmetaDataProperty Stored DoStoreMetadataProp;
  46. Property DataProperty : String read FDataProperty Write FDataProperty Stored DoStoreDataProp;
  47. Property MetaDataResourceName : String Read FMetaDataResourceName Write FMetaDataResourceName Stored DoStoreMetadata;
  48. Property UserName : String Read FUserName Write FUserName;
  49. Property Password : String Read FPassword Write FPassword;
  50. Property ConnectionsResourceName : String Read FConnectionsResourceName Write FConnectionsResourceName;
  51. Property CustomViewResourceName : String Read FCustomViewResourceName Write FCustomViewResourceName;
  52. // Published from TRESTCOnnection
  53. Property BaseURL;
  54. Property PageParam;
  55. Property OnGetURL;
  56. Property OnUpdateURL;
  57. end;
  58. { TSQLDBRestDataset }
  59. { TQueryParam }
  60. TQueryParam = class(TParam)
  61. private
  62. FEnabled: Boolean;
  63. Public
  64. Procedure Assign(Source : TPersistent); override;
  65. function AsQuery : String;
  66. Published
  67. Property Enabled : Boolean Read FEnabled Write FEnabled;
  68. end;
  69. { TQueryParams }
  70. TQueryParams = Class(TParams)
  71. private
  72. function GetP(aIndex : Integer): TQueryParam;
  73. procedure SetP(aIndex : Integer; AValue: TQueryParam);
  74. Public
  75. Property Params[aIndex : Integer] : TQueryParam Read GetP Write SetP; default;
  76. end;
  77. TGetQueryParamsEvent = Procedure (Sender : TDataset; IsReadURL : Boolean; var QueryString : String) of object;
  78. TSQLDBRestDataset = Class(TJSONDataset)
  79. private
  80. FAutoApplyUpdates: Boolean;
  81. FConnection: TSQLDBRestConnection;
  82. FDatabaseConnection: String;
  83. FOnGetQueryParams: TGetQueryParamsEvent;
  84. FParams: TQueryParams;
  85. FResourceID: String;
  86. FResourceName: String;
  87. FSQL: TStrings;
  88. function CleanSQL: String;
  89. function CustomViewResourceName: String;
  90. procedure DoSQLChange(Sender: TObject);
  91. procedure SetConnection(AValue: TSQLDBRestConnection);
  92. procedure SetParams(AValue: TQueryParams);
  93. procedure SetResourceID(AValue: String);
  94. procedure SetResourceName(AValue: String);
  95. procedure SetSQL(AValue: TStrings);
  96. Protected
  97. Procedure DoAfterPost; override;
  98. Procedure DoAfterDelete; override;
  99. function MyURL(isRead : Boolean): String; virtual;
  100. Function CreateQueryParams : TQueryParams; virtual;
  101. function GetURLQueryParams(IsRead : Boolean): string; virtual;
  102. function DataPacketReceived(ARequest: TDataRequest): Boolean; override;
  103. function GetStringFieldLength(F: TJSObject; AName: String; AIndex: Integer): integer;virtual;
  104. function StringToFieldType(S: String): TFieldType; virtual;
  105. Function DoGetDataProxy: TDataProxy; override;
  106. Procedure MetaDataToFieldDefs; override;
  107. Public
  108. Constructor Create(aOwner : TComponent); override;
  109. Destructor Destroy; override;
  110. Class Function DefaultBlobDataToBytes(aValue : JSValue) : TBytes; override;
  111. Class Function DefaultBytesToBlobData(aValue : TBytes) : JSValue; override;
  112. Function ParamByName(const aName : String) : TQueryParam;
  113. Published
  114. // Connection to use to get data
  115. Property Connection: TSQLDBRestConnection Read FConnection Write SetConnection;
  116. // The resource to get/post/put/delete
  117. Property ResourceName : String Read FResourceName Write SetResourceName;
  118. // When set, the CustomView resource (as set in CustomViewResourceName) is used. Use with care!
  119. Property SQL : TStrings Read FSQL Write SetSQL;
  120. // Database connection to use for the resource. Will be appended to URL.
  121. property DatabaseConnection : String Read FDatabaseConnection Write FDatabaseConnection;
  122. // Parameters to send (use for filtering)
  123. Property Params : TQueryParams Read FParams Write SetParams;
  124. {
  125. If you want to get a single resource, set the ID of the resource here.
  126. This is equivalent to setting a parameter ID to the specified value.
  127. }
  128. Property ResourceID : String Read FResourceID Write SetResourceID;
  129. // Get additional parameters with this event.
  130. Property OnGetQueryParams : TGetQueryParamsEvent Read FOnGetQueryParams Write FOnGetQueryParams;
  131. // Always immediatly call ApplyUpdates after post and delete.
  132. Property AutoApplyUpdates : Boolean Read FAutoApplyUpdates Write FAutoApplyUpdates;
  133. end;
  134. implementation
  135. uses DateUtils;
  136. Type
  137. { TServiceRequest }
  138. TServiceRequest = Class(TObject)
  139. Private
  140. FOnMyDone,
  141. FOnDone : TNotifyEvent;
  142. FXHR: TJSXMLHttpRequest;
  143. function GetResult: String;
  144. function GetResultJSON: TJSObject;
  145. function GetStatusCode: Integer;
  146. function onLoad(Event{%H-}: TEventListenerEvent): boolean;
  147. Public
  148. Constructor Create(Const aMethod,aURL,aUserName,aPassword : String; aOnDone1 : TNotifyEvent; aOnDone2 : TNotifyEvent = Nil);
  149. Procedure Execute;
  150. Property RequestResult : String read GetResult;
  151. Property ResultJSON : TJSObject read GetResultJSON;
  152. Property OnDone : TNotifyEvent Read FOnDone;
  153. Property StatusCode : Integer Read GetStatusCode;
  154. end;
  155. { TQueryParam }
  156. procedure TQueryParam.Assign(Source: TPersistent);
  157. Var
  158. P : TQueryParam absolute Source;
  159. begin
  160. if Source is TQueryParam then
  161. begin
  162. FEnabled:=P.Enabled;
  163. end;
  164. inherited Assign(Source);
  165. end;
  166. function TQueryParam.AsQuery: String;
  167. var
  168. S : String;
  169. B : TBytes;
  170. I : Integer;
  171. begin
  172. Result:='';
  173. if Not Enabled then
  174. exit;
  175. Case DataType of
  176. ftInteger : Result:=IntToStr(AsInteger);
  177. ftAutoInc,
  178. ftLargeInt : Result:=IntToStr(AsLargeInt);
  179. ftBoolean : Result:=IntToStr(Ord(AsBoolean));
  180. ftFloat : Str(asFloat,Result);
  181. ftDate : Result:=DateToISO8601(asDateTime);
  182. ftTime : Result:=DateToISO8601(asDateTime);
  183. ftDateTime : Result:=DateToISO8601(asDateTime);
  184. ftBlob :
  185. begin
  186. B:=AsBlob;
  187. Result:='';
  188. For I:=0 to Length(B)-1 do
  189. Result:=TJSString(Result).Concat(TJSString.fromCharCode(B[I]));
  190. end;
  191. ftMemo : Result:=AsMemo;
  192. else
  193. Result:=AsString
  194. end;
  195. Result:=Name+'='+encodeURIComponent(AsString);
  196. end;
  197. { TQueryParams }
  198. function TQueryParams.GetP(aIndex : Integer): TQueryParam;
  199. begin
  200. Result:=Items[aIndex] as TQueryParam
  201. end;
  202. procedure TQueryParams.SetP(aIndex : Integer; AValue: TQueryParam);
  203. begin
  204. Items[aIndex]:=aValue;
  205. end;
  206. { TServiceRequest }
  207. constructor TServiceRequest.Create(const aMethod,aURL, aUserName, aPassword: String; aOnDone1 : TNotifyEvent; aOnDone2 : TNotifyEvent = Nil);
  208. begin
  209. FOnMyDone:=aOnDone1;
  210. FOnDone:=aOnDone2;
  211. FXHR:=TJSXMLHttpRequest.New;
  212. FXHR.AddEventListener('load',@onLoad);
  213. FXHR.open(aMethod,aURL,true);
  214. (* else
  215. begin
  216. // FXHR.withCredentials := true;
  217. FXHR.open(aMethod,aURL,true,aUserName,aPassword);
  218. end;*)
  219. FXHR.setRequestHeader('Content-Type', 'application/json');
  220. FXHR.setRequestHeader('Authorization', 'Basic '+window.btoa(aUserName+':'+aPassword));
  221. end;
  222. procedure TServiceRequest.Execute;
  223. begin
  224. FXHR.send;
  225. end;
  226. function TServiceRequest.GetResult: String;
  227. begin
  228. Result:=FXHR.responseText;
  229. end;
  230. function TServiceRequest.GetResultJSON: TJSObject;
  231. begin
  232. if SameText(FXHR.getResponseHeader('Content-Type'),'application/json') then
  233. Result:=TJSJSON.parseObject(RequestResult)
  234. else
  235. Result:=nil;
  236. end;
  237. function TServiceRequest.GetStatusCode: Integer;
  238. begin
  239. Result:=FXHR.Status;
  240. end;
  241. function TServiceRequest.onLoad(Event: TEventListenerEvent): boolean;
  242. begin
  243. if Assigned(FOnMyDone) then
  244. FOnMyDone(Self);
  245. Result:=False;
  246. end;
  247. { TSQLDBRestConnection }
  248. function TSQLDBRestConnection.DoStoreMetadata: Boolean;
  249. begin
  250. Result:=(FMetadataResourceName<>'metadata');
  251. end;
  252. function TSQLDBRestConnection.DoStoreMetadataProp: Boolean;
  253. begin
  254. Result:=(FMetaDataProperty<>'metaData');
  255. end;
  256. procedure TSQLDBRestConnection.SetupRequest(aXHR: TJSXMLHttpRequest);
  257. begin
  258. aXHR.setRequestHeader('Content-Type', 'application/json');
  259. aXHR.setRequestHeader('Accept', 'application/json');
  260. if (UserName<>'') then
  261. aXHR.setRequestHeader('Authorization', 'Basic '+window.btoa(UserName+':'+Password));
  262. // Will call the OnSetupHTTPRequest handler
  263. inherited SetupRequest(aXHR);
  264. end;
  265. function TSQLDBRestConnection.GetUpdateBaseURL(aRequest: TRecordUpdateDescriptor): String;
  266. Var
  267. DS : TSQLDBRestDataset;
  268. begin
  269. Result:=inherited GetUpdateBaseURL(aRequest);
  270. DS:=TSQLDBRestDataset(aRequest.Dataset);
  271. Result:=IncludeTrailingPathDelimiter(Result)+DS.MyURL(False);
  272. end;
  273. function TSQLDBRestConnection.GetReadBaseURL(aRequest: TDataRequest): String;
  274. Var
  275. DS : TSQLDBRestDataset;
  276. begin
  277. Result:=inherited GetReadBaseURL(aRequest);
  278. DS:=TSQLDBRestDataset(aRequest.Dataset);
  279. Result:=IncludeTrailingPathDelimiter(Result)+DS.MyURL(True);
  280. end;
  281. procedure TSQLDBRestConnection.DoResources(Sender: TObject);
  282. Var
  283. R : TServiceRequest absolute Sender;
  284. J,Res : TJSObject;
  285. A : TJSArray;
  286. i : Integer;
  287. begin
  288. FResourceList.Clear;
  289. if (R.StatusCode=200) then
  290. begin
  291. J:=R.ResultJSON;
  292. if J=Nil then
  293. exit;
  294. A:=TJSArray(J.Properties['data']);
  295. For I:=0 to A.Length-1 do
  296. begin
  297. Res:=TJSObject(A[i]);
  298. FResourceList.Add(String(Res.Properties['name']));
  299. end;
  300. end;
  301. If Assigned(R.OnDone) then
  302. R.OnDone(Self);
  303. If Assigned(OnGetResources) then
  304. OnGetResources(Self);
  305. end;
  306. function TSQLDBRestConnection.DoStoreDataProp: Boolean;
  307. begin
  308. Result:=(FDataProperty<>'data');
  309. end;
  310. constructor TSQLDBRestConnection.create(aOwner: TComponent);
  311. begin
  312. inherited create(aOwner);
  313. FResourceList:=TStringList.Create;
  314. FMetaDataResourceName:='metadata';
  315. FmetaDataProperty:='metaData';
  316. FDataProperty:='data';
  317. TStringList(FResourceList).Sorted:=true;
  318. end;
  319. destructor TSQLDBRestConnection.Destroy;
  320. begin
  321. FreeAndNil(FResourceList);
  322. inherited Destroy;
  323. end;
  324. procedure TSQLDBRestConnection.GetResources(OnResult: TNotifyEvent);
  325. Var
  326. aURL : String;
  327. R : TServiceRequest;
  328. begin
  329. aURL:=IncludeTrailingPathDelimiter(BaseURL)+MetaDataResourceName+'?fmt=json';
  330. R:=TServiceRequest.Create('GET',aURL,Self.UserName,Self.Password,@DoResources,OnResult);
  331. R.Execute;
  332. end;
  333. { TSQLDBRestDataset }
  334. procedure TSQLDBRestDataset.SetConnection(AValue: TSQLDBRestConnection);
  335. begin
  336. if FConnection=AValue then Exit;
  337. if Assigned(FConnection) then
  338. FConnection.RemoveFreeNotification(Self);
  339. FConnection:=AValue;
  340. if Assigned(FConnection) then
  341. FConnection.FreeNotification(Self);
  342. end;
  343. procedure TSQLDBRestDataset.SetParams(AValue: TQueryParams);
  344. begin
  345. if FParams=AValue then Exit;
  346. FParams.Assign(AValue);
  347. end;
  348. procedure TSQLDBRestDataset.SetResourceID(AValue: String);
  349. begin
  350. if FResourceID=AValue then Exit;
  351. CheckInactive;
  352. FResourceID:=AValue;
  353. end;
  354. function TSQLDBRestDataset.GetURLQueryParams(IsRead :Boolean) : string;
  355. Procedure AddToResult(aQuery : string);
  356. begin
  357. if aQuery='' then
  358. exit;
  359. If Result<>'' then
  360. Result:=Result+'&';
  361. Result:=Result+aQuery;
  362. end;
  363. Var
  364. I : Integer;
  365. begin
  366. Result:='';
  367. if IsRead then
  368. begin
  369. if SameText(ResourceName,CustomViewResourceName) then
  370. AddToResult('SQL='+EncodeURIComponent(CleanSQL));
  371. For I:=0 to Params.Count-1 do
  372. AddToResult(Params[I].AsQuery);
  373. end;
  374. if Assigned(FOnGetQueryParams) then
  375. FOnGetQueryParams(Self,IsRead,Result);
  376. end;
  377. function TSQLDBRestDataset.MyURL(isRead: Boolean): String;
  378. Var
  379. Qry : String;
  380. begin
  381. Result:=DatabaseConnection;
  382. if (Result<>'') and (Result[Length(Result)]<>'/') then
  383. Result:=Result+'/';
  384. Result:=Result+ResourceName;
  385. if IsRead and (ResourceID<>'') then
  386. Result:=Result+'/'+EncodeURIComponent(ResourceID);
  387. Qry:=GetURLQueryParams(IsRead);
  388. if Qry<>'' then
  389. Result:=Result+'?'+Qry;
  390. end;
  391. procedure TSQLDBRestDataset.DoSQLChange(Sender: TObject);
  392. begin
  393. if Trim(FSQL.Text)<>'' then
  394. FResourceName:=CustomViewResourceName;
  395. end;
  396. procedure TSQLDBRestDataset.SetResourceName(AValue: String);
  397. begin
  398. if FResourceName=AValue then Exit;
  399. CheckInactive;
  400. if Not SameText(aValue,CustomViewResourceName) then
  401. FSQL.Clear;
  402. FResourceName:=AValue;
  403. end;
  404. function TSQLDBRestDataset.CustomViewResourceName : String;
  405. begin
  406. if Assigned(Connection) then
  407. Result:=Connection.CustomViewResourceName
  408. else
  409. Result:='customView';
  410. end;
  411. function TSQLDBRestDataset.CleanSQL: String;
  412. begin
  413. Result:=StringReplace(SQL.Text,#13#10,' ',[rfReplaceAll]);
  414. Result:=StringReplace(Result,#10,' ',[rfReplaceAll]);
  415. Result:=StringReplace(Result,#10,' ',[rfReplaceAll]);
  416. end;
  417. procedure TSQLDBRestDataset.SetSQL(AValue: TStrings);
  418. begin
  419. if FSQL=AValue then Exit;
  420. FSQL.Assign(AValue);
  421. end;
  422. procedure TSQLDBRestDataset.DoAfterPost;
  423. begin
  424. inherited DoAfterPost;
  425. if AutoApplyUpdates then
  426. ApplyUpdates;
  427. end;
  428. procedure TSQLDBRestDataset.DoAfterDelete;
  429. begin
  430. inherited DoAfterDelete;
  431. if AutoApplyUpdates then
  432. ApplyUpdates;
  433. end;
  434. function TSQLDBRestDataset.CreateQueryParams: TQueryParams;
  435. begin
  436. Result:=TQueryParams.Create(Self,TQueryParam);
  437. end;
  438. class function TSQLDBRestDataset.DefaultBlobDataToBytes(aValue: JSValue): TBytes;
  439. begin
  440. Result:=BytesOf(Window.atob(String(aValue)));
  441. end;
  442. class function TSQLDBRestDataset.DefaultBytesToBlobData(aValue: TBytes
  443. ): JSValue;
  444. begin
  445. Result:=Window.Btoa(StringOf(aValue));
  446. end;
  447. function TSQLDBRestDataset.ParamByName(const aName: String): TQueryParam;
  448. begin
  449. Result:=TQueryParam(Params.ParamByName(aName));
  450. end;
  451. function TSQLDBRestDataset.DoGetDataProxy: TDataProxy;
  452. begin
  453. Result:=Connection.DataProxy;
  454. end;
  455. function TSQLDBRestDataset.StringToFieldType(S: String): TFieldType;
  456. begin
  457. if (s='int') then
  458. Result:=ftInteger
  459. else if (s='bigint') then
  460. Result:=ftLargeInt
  461. else if (s='float') then
  462. Result:=ftFloat
  463. else if (s='bool') then
  464. Result:=ftBoolean
  465. else if (s='date') then
  466. Result:=ftDate
  467. else if (s='datetime') then
  468. Result:=ftDateTime
  469. else if (s='time') then
  470. Result:=ftTime
  471. else if (s='blob') then
  472. Result:=ftBlob
  473. else if (s='string') then
  474. Result:=ftString
  475. else
  476. if MapUnknownToStringType then
  477. Result:=ftString
  478. else
  479. Raise EJSONDataset.CreateFmt('Unknown JSON data type : %s',[s]);
  480. end;
  481. function TSQLDBRestDataset.GetStringFieldLength(F: TJSObject; AName: String;
  482. AIndex: Integer): integer;
  483. Var
  484. I,L : Integer;
  485. D : JSValue;
  486. begin
  487. Result:=0;
  488. D:=F.Properties['maxLen'];
  489. if Not jsIsNan(toNumber(D)) then
  490. begin
  491. Result:=Trunc(toNumber(D));
  492. if (Result<=0) then
  493. Raise EJSONDataset.CreateFmt('Invalid maximum length specifier for field %s',[AName])
  494. end
  495. else
  496. begin
  497. For I:=0 to Rows.Length-1 do
  498. begin
  499. D:=FieldMapper.GetJSONDataForField(Aname,AIndex,Rows[i]);
  500. if isString(D) then
  501. begin
  502. l:=Length(String(D));
  503. if L>Result then
  504. Result:=L;
  505. end;
  506. end;
  507. end;
  508. if (Result=0) then
  509. Result:=20;
  510. end;
  511. procedure TSQLDBRestDataset.MetaDataToFieldDefs;
  512. Var
  513. A : TJSArray;
  514. F : TJSObject;
  515. I,FS : Integer;
  516. N: String;
  517. ft: TFieldType;
  518. D : JSValue;
  519. begin
  520. FieldDefs.Clear;
  521. D:=Metadata.Properties['fields'];
  522. if Not IsArray(D) then
  523. Raise EJSONDataset.Create('Invalid metadata object');
  524. A:=TJSArray(D);
  525. For I:=0 to A.Length-1 do
  526. begin
  527. If Not isObject(A[i]) then
  528. Raise EJSONDataset.CreateFmt('Field definition %d in metadata is not an object',[i]);
  529. F:=TJSObject(A[i]);
  530. D:=F.Properties['name'];
  531. If Not isString(D) then
  532. Raise EJSONDataset.CreateFmt('Field definition %d in has no or invalid name property',[i]);
  533. N:=String(D);
  534. D:=F.Properties['type'];
  535. If IsNull(D) or isUndefined(D) then
  536. ft:=ftstring
  537. else If Not isString(D) then
  538. begin
  539. Raise EJSONDataset.CreateFmt('Field definition %d in has invalid type property',[i])
  540. end
  541. else
  542. begin
  543. ft:=StringToFieldType(String(D));
  544. end;
  545. if (ft=ftString) then
  546. fs:=GetStringFieldLength(F,N,I)
  547. else
  548. fs:=0;
  549. FieldDefs.Add(N,ft,fs);
  550. end;
  551. end;
  552. constructor TSQLDBRestDataset.Create(aOwner: TComponent);
  553. begin
  554. inherited Create(aOwner);
  555. FSQL:=TStringList.Create;
  556. TStringList(FSQL).OnChange:=@DoSQLChange;
  557. FParams:=CreateQueryParams;
  558. BlobFormat:=bfBase64;
  559. end;
  560. destructor TSQLDBRestDataset.Destroy;
  561. begin
  562. FreeAndNil(FSQL);
  563. FreeAndnil(FParams);
  564. inherited Destroy;
  565. end;
  566. function TSQLDBRestDataset.DataPacketReceived(ARequest: TDataRequest): Boolean;
  567. Var
  568. O : TJSObject;
  569. A : TJSArray;
  570. smetadata,sroot : String;
  571. begin
  572. Result:=False;
  573. If isNull(aRequest.Data) then
  574. exit;
  575. If isString(aRequest.Data) then
  576. O:=TJSOBject(TJSJSON.Parse(String(aRequest.Data)))
  577. else if isObject(aRequest.Data) then
  578. O:=TJSOBject(aRequest.Data)
  579. else
  580. DatabaseError('Cannot handle data packet');
  581. sRoot:=Connection.DataProperty;
  582. sMetaData:=Connection.metaDataProperty;
  583. if (sroot='') then
  584. sroot:='data';
  585. if (smetadata='') then
  586. smetadata:='metaData';
  587. { if (IDField='') then
  588. idField:='id';}
  589. if O.hasOwnProperty(sMetaData) and isObject(o[sMetaData]) then
  590. begin
  591. if not Active then // Load fields from metadata
  592. metaData:=TJSObject(o[SMetaData]);
  593. { if metaData.hasOwnProperty('idField') and isString(metaData['idField']) then
  594. IDField:=string(metaData['idField']);}
  595. end;
  596. if O.hasOwnProperty(sRoot) and isArray(o[sRoot]) then
  597. begin
  598. A:=TJSArray(o[sRoot]);
  599. Result:=A.Length>0;
  600. AddToRows(A);
  601. end;
  602. end;
  603. end.