source upload

This commit is contained in:
Razor12911
2022-01-17 22:16:47 +02:00
parent 12936d065b
commit 098e8c48de
1778 changed files with 1206749 additions and 0 deletions

View File

@@ -0,0 +1,189 @@
TSynRestDataset
===============
By *EMartin* (Esteban Martin).
# Presentation
Migrating from *RemObjects* to *mORMot* I had to implement a GUI functionality that *RemObjects* has, an editable dataset connected through URL (RO version 3 use SOAP and other components adapters, etc.).
My implementation is basic and the most probably is not the best, but works for me, the same use RESTful URL for get and update data, also get data from a *mORMot* interface based services returning a *mORMot* JSON array but cannot update because the table not exists.
In this folder there are two units: `SynRestVCL.pas` and `SynRestMidasVCL.pas`, both have some duplicated code from its counterpart (`SynDBVCL.pas` and `SynDBMidasVCL.pas`) and the others, but the rest are modifications with use of RESTful instead of the `TSQLDBConnection` (this require the database client installed in the client machine).
A `TSQLModel` is required because the `TSynRestDataset` get the fields definition column type and size from this. Also is used from the `TSQLRecord` the defined validations (I used `InternalDefineModel`) and the `ComputeFieldsBeforeWrite` (I used this for default values).
This was developed with Delphi 7 on Windows 7 and probably (almost sure) is not cross platform.
If this serves for others may be the best option will be that *ab* integrate this in the framework and make this code more *mORMot*. Meanwhile I will update on the google drive.
I hope this is helpful to someone.
# Example 1: from a table
// defining the table
TSQLRecordTest = class(TSQLRecord)
private
fDecimal: Double;
fNumber: Double;
fTestID: Integer;
fText: RawUTF8;
fDateTime: TDateTime;
protected
class procedure InternalDefineModel(Props: TSQLRecordProperties); override;
public
procedure ComputeFieldsBeforeWrite(aRest: TSQLRest; aOccasion: TSQLEvent); override;
published
property Test_ID: Integer read fTestID write fTestID;
property Text: RawUTF8 index 255 read fText write fText;
property Date_Time: TDateTime read fDateTime write fDateTime;
property Number: Double read fNumber write fNumber;
property Decimal_: Double read fDecimal write fDecimal;
end;
...
{ TSQLRecordTest }
procedure TSQLRecordTest.ComputeFieldsBeforeWrite(aRest: TSQLRest; aOccasion: TSQLEvent);
begin
inherited;
fDateTime := Now;
end;
class procedure TSQLRecordTest.InternalDefineModel(Props: TSQLRecordProperties);
begin
AddFilterNotVoidText(['Text']);
AddFilterOrValidate('Text', TSynValidateNonNull.Create);
end;
// client
type
TForm3 = class(TForm)
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
btnOpen: TButton;
edtURL: TEdit;
dsRest: TDataSource;
procedure FormCreate(Sender: TObject);
procedure btnOpenClick(Sender: TObject);
procedure DBNavigator1Click(Sender: TObject; Button: TNavigateBtn);
private
{ Private declarations }
fRestDS: TSynRestDataset;
public
{ Public declarations }
end;
...
procedure TForm3.FormCreate(Sender: TObject);
begin
fRestDS := TSynRestDataset.Create(Self);
fRestDS.Dataset.SQLModel := TSQLModel.Create([TSQLRecordTest], 'root');
dsRest.Dataset := fRestDS;
end;
procedure TForm3.btnOpenClick(Sender: TObject);
begin
fRestDS.Close;
fRestDS.CommandText := edtURL.Text; // edtURL.Text = 'http://localhost:8888/root/Test/select=*
fRestDS.Open;
// you can filter by
// where: fRestDS.CommandText := edtURL.Text; // edtURL.Text = 'http://localhost:8888/root/Test/select=*&where=CONDITION
// fRestDS.Open;
// named parameter: fRestDS.CommandText := edtURL.Text; // edtURL.Text = 'http://localhost:8888/root/Test/select=*&where=:PARAMNAME
// fRestDS.Params.ParamByName('PARAMNAME').Value := XXX
// fRestDS.Open;
end;
procedure TForm3.DBNavigator1Click(Sender: TObject; Button: TNavigateBtn);
begin
if (Button = nbPost) then
fRestDS.ApplyUpdates(0);
end;
# Example 2: from a service
// defining the table, the service name and operation name are required
TSQLRecordServiceName_OperationName = class(TSQLRecord)
private
fText: RawUTF8;
published
property Text: RawUTF8 index 255 read fText write fText;
end;
...
// server (the implementation)
TServiceName =class(TInterfacedObjectWithCustomCreate, IServiceName)
public
...
// this function can also be function OperationName(const aParamName: RawUTF8): RawUTF8;
function OperationName(const aParamName: RawUTF8; out aData: RawUTF8): Integer;
...
end;
...
function TServiceName.OperationName(const aParamName: RawUTF8; out aData: RawUTF8): Integer;
begin
Result := OK;
aData := '[{"text":"test"},{"text":"test1"}]';
end;
...
// client
type
TForm3 = class(TForm)
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
btnOpen: TButton;
edtURL: TEdit;
dsRest: TDataSource;
procedure FormCreate(Sender: TObject);
procedure btnOpenClick(Sender: TObject);
procedure DBNavigator1Click(Sender: TObject; Button: TNavigateBtn);
private
{ Private declarations }
fRestDS: TSynRestDataset;
public
{ Public declarations }
end;
...
procedure TForm3.FormCreate(Sender: TObject);
begin
fRestDS := TSynRestDataset.Create(Self);
fRestDS.Dataset.SQLModel := TSQLModel.Create([TSQLRecordServiceName_OperationName], 'root');
dsRest.Dataset := fRestDS;
end;
procedure TForm3.btnOpenClick(Sender: TObject);
begin
fRestDS.Close;
fRestDS.CommandText := edtURL.Text; // edtURL.Text = 'http://localhost:8888/root/ServiceName.OperationName?aParamName=XXX
fRestDS.Open;
// you can filter by named parameter:
// fRestDS.CommandText := edtURL.Text; // 'http://localhost:8888/root/ServiceName.OperationName?aParamName=:aParamName
// fRestDS.Params.ParamByName('aParamName').Value := XXX
// fRestDS.Open;
end;
procedure TForm3.DBNavigator1Click(Sender: TObject; Button: TNavigateBtn);
begin
if (Button = nbPost) then
fRestDS.ApplyUpdates(0); // raise an error "Cannot update data from a service"
end;
# Forum Thread
See http://synopse.info/forum/viewtopic.php?id=2712
# License
Feel free to use and/or append to Lib and extend if needed.