2018-10-23 16:18:34 +02:00
|
|
|
unit MainFormU;
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
|
|
|
Winapi.Windows,
|
|
|
|
Winapi.Messages,
|
|
|
|
System.SysUtils,
|
|
|
|
System.Variants,
|
|
|
|
System.Classes,
|
|
|
|
Vcl.Graphics,
|
|
|
|
Vcl.Controls,
|
|
|
|
Vcl.Forms,
|
|
|
|
Vcl.Dialogs,
|
|
|
|
Vcl.StdCtrls,
|
|
|
|
FireDAC.Stan.Intf,
|
|
|
|
FireDAC.Stan.Option,
|
|
|
|
FireDAC.Stan.Error,
|
|
|
|
FireDAC.UI.Intf,
|
|
|
|
FireDAC.Phys.Intf,
|
|
|
|
FireDAC.Stan.Def,
|
|
|
|
FireDAC.Stan.Pool,
|
|
|
|
FireDAC.Stan.Async,
|
|
|
|
FireDAC.Phys,
|
|
|
|
FireDAC.VCLUI.Wait,
|
2020-01-04 12:53:53 +01:00
|
|
|
Data.DB, FireDAC.Comp.Client, MVCFramework.Nullables;
|
2019-06-24 20:59:33 +02:00
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
type
|
|
|
|
TMainForm = class(TForm)
|
|
|
|
btnCRUD: TButton;
|
|
|
|
btnSelect: TButton;
|
|
|
|
Memo1: TMemo;
|
|
|
|
btnRelations: TButton;
|
|
|
|
btnInheritance: TButton;
|
|
|
|
btnValidation: TButton;
|
|
|
|
btnMultiThreading: TButton;
|
2018-11-02 21:43:09 +01:00
|
|
|
btnRQL: TButton;
|
2019-02-21 20:17:11 +01:00
|
|
|
btnTransientFields: TButton;
|
2019-06-24 20:59:33 +02:00
|
|
|
FDConnection1: TFDConnection;
|
2020-01-04 12:53:53 +01:00
|
|
|
Button1: TButton;
|
|
|
|
btnNullables: TButton;
|
|
|
|
btnNullTest: TButton;
|
2018-10-23 16:18:34 +02:00
|
|
|
procedure btnCRUDClick(Sender: TObject);
|
|
|
|
procedure btnInheritanceClick(Sender: TObject);
|
|
|
|
procedure btnMultiThreadingClick(Sender: TObject);
|
|
|
|
procedure btnRelationsClick(Sender: TObject);
|
2018-11-02 21:43:09 +01:00
|
|
|
procedure btnRQLClick(Sender: TObject);
|
2018-10-23 16:18:34 +02:00
|
|
|
procedure btnSelectClick(Sender: TObject);
|
|
|
|
procedure btnValidationClick(Sender: TObject);
|
2019-01-08 12:48:27 +01:00
|
|
|
procedure FormDestroy(Sender: TObject);
|
2019-02-21 20:17:11 +01:00
|
|
|
procedure btnTransientFieldsClick(Sender: TObject);
|
2019-09-13 15:17:56 +02:00
|
|
|
procedure FormShow(Sender: TObject);
|
2020-01-04 12:53:53 +01:00
|
|
|
procedure Button1Click(Sender: TObject);
|
|
|
|
procedure btnNullablesClick(Sender: TObject);
|
|
|
|
procedure btnNullTestClick(Sender: TObject);
|
2018-10-23 16:18:34 +02:00
|
|
|
private
|
|
|
|
procedure Log(const Value: string);
|
|
|
|
public
|
|
|
|
{ Public declarations }
|
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
|
|
MainForm: TMainForm;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
{$R *.dfm}
|
|
|
|
|
2020-01-04 12:53:53 +01:00
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
uses
|
|
|
|
MVCFramework.ActiveRecord,
|
|
|
|
EntitiesU,
|
|
|
|
System.Threading,
|
|
|
|
System.Generics.Collections,
|
|
|
|
MVCFramework.DataSet.Utils,
|
|
|
|
MVCFramework.RQL.Parser,
|
|
|
|
System.Math,
|
2019-09-13 15:17:56 +02:00
|
|
|
FDConnectionConfigU, EngineChoiceFormU;
|
2018-10-23 16:18:34 +02:00
|
|
|
|
|
|
|
procedure TMainForm.btnCRUDClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
lID: Integer;
|
|
|
|
begin
|
2019-12-17 17:34:23 +01:00
|
|
|
Log('** Simple CRUD test');
|
|
|
|
Log('There are ' + TMVCActiveRecord.Count<TCustomer>().ToString + ' row/s for entity ' + TCustomer.ClassName);
|
2018-10-23 16:18:34 +02:00
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
try
|
|
|
|
lCustomer.CompanyName := 'Google Inc.';
|
|
|
|
lCustomer.City := 'Montain View, CA';
|
2019-12-23 10:35:36 +01:00
|
|
|
lCustomer.Note := 'Hello there!';
|
2018-10-23 16:18:34 +02:00
|
|
|
lCustomer.Insert;
|
|
|
|
lID := lCustomer.ID;
|
|
|
|
Log('Just inserted Customer ' + lID.ToString);
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
|
2018-11-09 18:11:59 +01:00
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomer>(lID);
|
2018-10-23 16:18:34 +02:00
|
|
|
try
|
2020-01-04 12:53:53 +01:00
|
|
|
Assert(not lCustomer.Code.HasValue);
|
|
|
|
lCustomer.Code.Value := '5678';
|
2019-12-23 10:35:36 +01:00
|
|
|
lCustomer.Note := lCustomer.Note + sLineBreak + 'Code changed to 5678';
|
2018-10-23 16:18:34 +02:00
|
|
|
lCustomer.Update;
|
|
|
|
Log('Just updated Customer ' + lID.ToString);
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
try
|
|
|
|
lCustomer.LoadByPK(lID);
|
2020-01-04 12:53:53 +01:00
|
|
|
lCustomer.Code.Value := '9012';
|
2018-10-23 16:18:34 +02:00
|
|
|
lCustomer.Update;
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
|
2018-11-09 18:11:59 +01:00
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomer>(lID);
|
2018-10-23 16:18:34 +02:00
|
|
|
try
|
|
|
|
lCustomer.Delete;
|
|
|
|
Log('Just deleted Customer ' + lID.ToString);
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.btnInheritanceClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
lCustomerEx: TCustomerEx;
|
|
|
|
begin
|
2019-12-17 17:34:23 +01:00
|
|
|
Log('** Inheritace test');
|
2018-10-23 16:18:34 +02:00
|
|
|
lCustomerEx := TCustomerEx.Create;
|
|
|
|
try
|
|
|
|
lCustomerEx.LoadByPK(1);
|
|
|
|
finally
|
|
|
|
lCustomerEx.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.btnMultiThreadingClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
lTasks: TArray<ITask>;
|
|
|
|
lProc: TProc;
|
2019-01-13 18:56:33 +01:00
|
|
|
lConnParams: string;
|
2018-10-23 16:18:34 +02:00
|
|
|
const
|
2019-09-13 15:17:56 +02:00
|
|
|
Cities: array [0 .. 4] of string = ('Rome', 'New York', 'London', 'Melbourne', 'Berlin');
|
2019-05-19 20:23:45 +02:00
|
|
|
CompanySuffix: array [0 .. 5] of string = ('Corp.', 'Inc.', 'Ltd.', 'Srl', 'SPA', 'doo');
|
|
|
|
Stuff: array [0 .. 4] of string = ('Burger', 'GAS', 'Motors', 'House', 'Boats');
|
2018-10-23 16:18:34 +02:00
|
|
|
begin
|
2019-12-17 17:34:23 +01:00
|
|
|
Log('** Multithreading test');
|
2019-05-19 20:23:45 +02:00
|
|
|
TMVCActiveRecord.DeleteRQL(TCustomer, 'in(City,["Rome","New York","London","Melbourne","Berlin"])');
|
2018-11-02 21:43:09 +01:00
|
|
|
|
2019-01-13 18:56:33 +01:00
|
|
|
lConnParams := FDConnection1.Params.Text;
|
2019-01-08 12:48:27 +01:00
|
|
|
lProc := procedure
|
2018-10-23 16:18:34 +02:00
|
|
|
var
|
|
|
|
lConn: TFDConnection;
|
2019-01-08 12:48:27 +01:00
|
|
|
lCustomer: TCustomer;
|
|
|
|
I: Integer;
|
2018-10-23 16:18:34 +02:00
|
|
|
begin
|
|
|
|
lConn := TFDConnection.Create(nil);
|
|
|
|
try
|
2018-11-02 21:43:09 +01:00
|
|
|
lConn.ConnectionDefName := CON_DEF_NAME;
|
2019-01-13 18:56:33 +01:00
|
|
|
ActiveRecordConnectionsRegistry.AddConnection('default', lConn, True);
|
|
|
|
lConn.Params.Text := lConnParams;
|
2018-10-23 16:18:34 +02:00
|
|
|
lConn.Open;
|
2019-05-19 20:23:45 +02:00
|
|
|
for I := 1 to 30 do
|
2018-10-23 16:18:34 +02:00
|
|
|
begin
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
try
|
2019-08-02 12:32:23 +02:00
|
|
|
lCustomer.Code := Format('%5.5d', [TThread.CurrentThread.ThreadID, I]);
|
2018-10-23 16:18:34 +02:00
|
|
|
lCustomer.City := Cities[Random(high(Cities) + 1)];
|
2019-09-13 15:17:56 +02:00
|
|
|
lCustomer.CompanyName := Format('%s %s %s', [lCustomer.City, Stuff[Random(High(Stuff) + 1)],
|
|
|
|
CompanySuffix[Random(High(CompanySuffix) + 1)]]);
|
2019-12-23 10:35:36 +01:00
|
|
|
lCustomer.Note := lCustomer.CompanyName + ' is from ' + lCustomer.City;
|
2018-10-23 16:18:34 +02:00
|
|
|
lCustomer.Insert;
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
finally
|
|
|
|
ActiveRecordConnectionsRegistry.RemoveConnection('default');
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2019-09-13 15:17:56 +02:00
|
|
|
lTasks := [TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
|
|
|
TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
|
|
|
TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
|
|
|
TTask.Run(lProc)];
|
2018-10-23 16:18:34 +02:00
|
|
|
TTask.WaitForAll(lTasks);
|
2019-05-19 20:23:45 +02:00
|
|
|
|
|
|
|
ShowMessage('Just inserted ' + TMVCActiveRecord.Count(TCustomer,
|
|
|
|
'in(City,["Rome","New York","London","Melbourne","Berlin"])').ToString + ' records');
|
2018-10-23 16:18:34 +02:00
|
|
|
end;
|
|
|
|
|
2020-01-04 12:53:53 +01:00
|
|
|
procedure TMainForm.btnNullablesClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
lID: Integer;
|
|
|
|
begin
|
|
|
|
Log('** Nullables Test');
|
|
|
|
Log('There are ' + TMVCActiveRecord.Count<TCustomer>().ToString + ' row/s for entity ' + TCustomer.ClassName);
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
try
|
|
|
|
lCustomer.CompanyName := 'Google Inc.';
|
|
|
|
lCustomer.City := 'Montain View, CA';
|
|
|
|
lCustomer.Note := 'Hello there!';
|
|
|
|
lCustomer.Insert;
|
|
|
|
lID := lCustomer.ID;
|
|
|
|
Assert(not lCustomer.Code.HasValue);
|
|
|
|
Log('Just inserted Customer ' + lID.ToString);
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomer>(lID);
|
|
|
|
try
|
|
|
|
Assert(not lCustomer.Code.HasValue);
|
|
|
|
Assert(not lCustomer.Rating.HasValue);
|
|
|
|
Assert(lCustomer.Rating.ValueOrDefault = 0);
|
|
|
|
lCustomer.Code.Value := '5678';
|
|
|
|
lCustomer.Rating.Value := 3;
|
|
|
|
Assert(lCustomer.Code.HasValue);
|
|
|
|
lCustomer.Note := lCustomer.Note + sLineBreak + 'Code changed to 5678';
|
|
|
|
lCustomer.Update;
|
|
|
|
Assert(lCustomer.Code.HasValue);
|
|
|
|
Assert(lCustomer.Rating.HasValue);
|
|
|
|
Log('Just updated Customer ' + lID.ToString);
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomer>(lID);
|
|
|
|
try
|
|
|
|
Assert(lCustomer.Code.HasValue);
|
|
|
|
Assert(lCustomer.Rating.HasValue);
|
|
|
|
Assert(lCustomer.Code.ValueOrDefault = '5678');
|
|
|
|
Assert(lCustomer.Rating.ValueOrDefault = 3);
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
try
|
|
|
|
lCustomer.LoadByPK(lID);
|
|
|
|
lCustomer.Code.Value := '9012';
|
|
|
|
lCustomer.Update;
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.btnNullTestClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
lTest: TNullablesTest;
|
|
|
|
begin
|
|
|
|
// TMVCActiveRecord.DeleteAll(TNullablesTest);
|
|
|
|
//
|
|
|
|
// lTest := TNullablesTest.Create();
|
|
|
|
// try
|
|
|
|
// lTest.f_int2 := 2;
|
|
|
|
// lTest.f_int4 := 4;
|
|
|
|
// lTest.f_int8 := 8;
|
|
|
|
// lTest.Insert;
|
|
|
|
// finally
|
|
|
|
// lTest.Free;
|
|
|
|
// end;
|
|
|
|
//
|
|
|
|
// lTest := TMVCActiveRecord.GetFirstByWhere<TNullablesTest>('f_int2 = ?', [2]);
|
|
|
|
// try
|
|
|
|
// Assert(lTest.f_int2.HasValue);
|
|
|
|
// Assert(lTest.f_int4.HasValue);
|
|
|
|
// Assert(lTest.f_int8.HasValue);
|
|
|
|
// Assert(not lTest.f_string.HasValue);
|
|
|
|
// Assert(not lTest.f_bool.HasValue);
|
|
|
|
// Assert(not lTest.f_date.HasValue);
|
|
|
|
// Assert(not lTest.f_time.HasValue);
|
|
|
|
// Assert(not lTest.f_datetime.HasValue);
|
|
|
|
// Assert(not lTest.f_float4.HasValue);
|
|
|
|
// Assert(not lTest.f_float8.HasValue);
|
|
|
|
// Assert(not lTest.f_bool.HasValue);
|
|
|
|
// lTest.f_int2 := lTest.f_int2.Value + 2;
|
|
|
|
// lTest.f_int4 := lTest.f_int4.Value + 4;
|
|
|
|
// lTest.f_int8 := lTest.f_int8.Value + 8;
|
|
|
|
// lTest.Update;
|
|
|
|
// finally
|
|
|
|
// lTest.Free;
|
|
|
|
// end;
|
|
|
|
//
|
|
|
|
// lTest := TMVCActiveRecord.GetFirstByWhere<TNullablesTest>('f_int2 = ?', [4]);
|
|
|
|
// try
|
|
|
|
// Assert(lTest.f_int2.ValueOrDefault = 4);
|
|
|
|
// Assert(lTest.f_int4.ValueOrDefault = 8);
|
|
|
|
// Assert(lTest.f_int8.ValueOrDefault = 16);
|
|
|
|
// Assert(not lTest.f_string.HasValue);
|
|
|
|
// Assert(not lTest.f_bool.HasValue);
|
|
|
|
// Assert(not lTest.f_date.HasValue);
|
|
|
|
// Assert(not lTest.f_time.HasValue);
|
|
|
|
// Assert(not lTest.f_datetime.HasValue);
|
|
|
|
// Assert(not lTest.f_float4.HasValue);
|
|
|
|
// Assert(not lTest.f_float8.HasValue);
|
|
|
|
// Assert(not lTest.f_bool.HasValue);
|
|
|
|
// TMVCActiveRecord.DeleteRQL(TNullablesTest, 'eq(f_int2,4)');
|
|
|
|
// finally
|
|
|
|
// lTest.Free;
|
|
|
|
// end;
|
|
|
|
//
|
|
|
|
// Assert(TMVCActiveRecord.GetFirstByWhere<TNullablesTest>('f_int2 = 4', [], False) = nil);
|
|
|
|
|
|
|
|
lTest := TNullablesTest.Create;
|
|
|
|
try
|
|
|
|
lTest.f_int2 := 2;
|
|
|
|
lTest.f_int4 := 4;
|
|
|
|
lTest.f_int8 := 8;
|
|
|
|
lTest.f_string := 'Hello World';
|
|
|
|
lTest.f_bool := True;
|
|
|
|
lTest.f_date := EncodeDate(2020, 02, 01);
|
|
|
|
lTest.f_time := EncodeTime(12, 24, 36, 0);
|
|
|
|
lTest.f_datetime := Now;
|
|
|
|
lTest.f_float4 := 1234.5678;
|
|
|
|
lTest.f_float8 := 12345678901234567890.0123456789;
|
|
|
|
lTest.f_currency := 1234567890.1234;
|
|
|
|
lTest.Insert;
|
|
|
|
finally
|
|
|
|
lTest.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
procedure TMainForm.btnRelationsClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
lCustomer: TCustomerEx;
|
|
|
|
lOrder: TOrder;
|
|
|
|
lOrderRows: TObjectList<TOrderDetail>;
|
|
|
|
lOrderRow: TOrderDetail;
|
2018-11-02 21:43:09 +01:00
|
|
|
lOrderDetail: TOrderDetail;
|
|
|
|
I: Integer;
|
|
|
|
j: Integer;
|
2018-10-23 16:18:34 +02:00
|
|
|
begin
|
2019-12-17 17:34:23 +01:00
|
|
|
Log('** Relations test');
|
2019-02-21 18:11:14 +01:00
|
|
|
TMVCActiveRecord.DeleteAll(TCustomerEx);
|
2018-11-02 21:43:09 +01:00
|
|
|
|
|
|
|
lCustomer := TCustomerEx.Create;
|
|
|
|
try
|
|
|
|
lCustomer.Code := '001';
|
|
|
|
lCustomer.CompanyName := 'Google Inc.';
|
|
|
|
lCustomer.Insert;
|
|
|
|
for I := 1 to 3 do
|
|
|
|
begin
|
|
|
|
lCustomer.Orders.Add(TOrder.Create);
|
|
|
|
lCustomer.Orders.Last.CustomerID := lCustomer.ID;
|
|
|
|
lCustomer.Orders.Last.OrderDate := EncodeDate(2018, 5 + I, 20 + I);
|
|
|
|
lCustomer.Orders.Last.Total := I * 3;
|
|
|
|
lCustomer.Orders.Last.Insert;
|
|
|
|
|
|
|
|
for j := 1 to 4 do
|
|
|
|
begin
|
|
|
|
lOrderDetail := TOrderDetail.Create;
|
|
|
|
try
|
|
|
|
lOrderDetail.OrderID := lCustomer.Orders.Last.ID;
|
|
|
|
lOrderDetail.ArticleID := j;
|
|
|
|
lOrderDetail.Price := Random(j * 10);
|
|
|
|
lOrderDetail.Discount := j;
|
|
|
|
lOrderDetail.Quantity := j * 2;
|
2019-09-13 15:17:56 +02:00
|
|
|
lOrderDetail.Description := 'MY PRODUCT ' + I.ToString + '/' + j.ToString;
|
2018-11-02 21:43:09 +01:00
|
|
|
lOrderDetail.Total := j * j * j;
|
|
|
|
lOrderDetail.Insert;
|
|
|
|
finally
|
|
|
|
lOrderDetail.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
|
2019-08-02 12:32:23 +02:00
|
|
|
lCustomer := TMVCActiveRecord.GetOneByWhere<TCustomerEx>('Code = ?', ['001']);
|
2018-10-23 16:18:34 +02:00
|
|
|
try
|
|
|
|
Log(lCustomer.CompanyName);
|
|
|
|
for lOrder in lCustomer.Orders do
|
|
|
|
begin
|
2019-09-13 15:17:56 +02:00
|
|
|
Log(Format(' %5.5d - %s - %m', [lOrder.ID, datetostr(lOrder.OrderDate), lOrder.Total]));
|
|
|
|
lOrderRows := TMVCActiveRecord.Where<TOrderDetail>('id_order = ?', [lOrder.ID]);
|
2018-10-23 16:18:34 +02:00
|
|
|
try
|
|
|
|
for lOrderRow in lOrderRows do
|
|
|
|
begin
|
2019-09-13 15:17:56 +02:00
|
|
|
Log(Format(' %-20s - %4d - %m', [lOrderRow.Description, lOrderRow.Quantity, lOrder.Total]));
|
2018-10-23 16:18:34 +02:00
|
|
|
end;
|
|
|
|
Log('');
|
|
|
|
finally
|
|
|
|
lOrderRows.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2018-11-02 21:43:09 +01:00
|
|
|
procedure TMainForm.btnRQLClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
lList: TMVCActiveRecordList;
|
|
|
|
lItem: TMVCActiveRecord;
|
|
|
|
lCustomer: TCustomer;
|
2019-06-24 20:59:33 +02:00
|
|
|
lCustList: TObjectList<TCustomer>;
|
2019-05-19 20:23:45 +02:00
|
|
|
const
|
2019-06-24 20:59:33 +02:00
|
|
|
cRQL1 = 'in(City,["Rome","London"]);sort(+code);limit(0,50)';
|
|
|
|
cRQL2 = 'and(eq(City,"Rome"),or(contains(CompanyName,"GAS"),contains(CompanyName,"Motors")))';
|
2018-11-02 21:43:09 +01:00
|
|
|
begin
|
2019-12-17 17:34:23 +01:00
|
|
|
Log('** RQL Queries Test');
|
|
|
|
Log('>> RQL Query (1) - ' + cRQL1);
|
2019-05-19 20:23:45 +02:00
|
|
|
lList := TMVCActiveRecord.SelectRQL(TCustomer, cRQL1, 20);
|
2019-05-16 00:16:55 +02:00
|
|
|
try
|
2019-05-19 20:23:45 +02:00
|
|
|
Log(lList.Count.ToString + ' record/s found');
|
2019-05-16 00:16:55 +02:00
|
|
|
for lItem in lList do
|
|
|
|
begin
|
|
|
|
lCustomer := TCustomer(lItem);
|
2020-01-04 12:53:53 +01:00
|
|
|
Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault,
|
|
|
|
lCustomer.City]));
|
2019-05-16 00:16:55 +02:00
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lList.Free;
|
|
|
|
end;
|
|
|
|
|
2019-12-17 17:34:23 +01:00
|
|
|
Log('>> RQL Query (2) - ' + cRQL2);
|
2019-06-24 20:59:33 +02:00
|
|
|
lCustList := TMVCActiveRecord.SelectRQL<TCustomer>(cRQL2, 20);
|
|
|
|
try
|
|
|
|
Log(lCustList.Count.ToString + ' record/s found');
|
|
|
|
for lCustomer in lCustList do
|
|
|
|
begin
|
2020-01-04 12:53:53 +01:00
|
|
|
Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault,
|
|
|
|
lCustomer.City]));
|
2019-06-24 20:59:33 +02:00
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lCustList.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
Log('**RQL Query (3) - ' + cRQL2);
|
2019-05-19 20:23:45 +02:00
|
|
|
lList := TMVCActiveRecord.SelectRQL(TCustomer, cRQL2, 20);
|
2018-11-02 21:43:09 +01:00
|
|
|
try
|
2019-05-19 20:23:45 +02:00
|
|
|
Log(lList.Count.ToString + ' record/s found');
|
2018-11-02 21:43:09 +01:00
|
|
|
for lItem in lList do
|
|
|
|
begin
|
|
|
|
lCustomer := TCustomer(lItem);
|
2020-01-04 12:53:53 +01:00
|
|
|
Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault,
|
|
|
|
lCustomer.City]));
|
2018-11-02 21:43:09 +01:00
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lList.Free;
|
|
|
|
end;
|
2019-05-16 00:16:55 +02:00
|
|
|
|
2018-11-02 21:43:09 +01:00
|
|
|
end;
|
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
procedure TMainForm.btnSelectClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
lCustomers: TObjectList<TCustomer>;
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
lDS: TDataSet;
|
|
|
|
begin
|
|
|
|
Log('** Query SQL');
|
2019-01-13 18:56:33 +01:00
|
|
|
// Bypassing the RQL parser you can use DBMS-specific features or just joining your tables.
|
2019-02-21 18:11:14 +01:00
|
|
|
// This is just a sample, you can do the "select" also using the RQL engine
|
2018-11-02 21:43:09 +01:00
|
|
|
if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'firebird' then
|
2019-09-13 15:17:56 +02:00
|
|
|
lCustomers := TMVCActiveRecord.Select<TCustomer>('SELECT * FROM customers WHERE description CONTAINING ?',
|
|
|
|
['google'])
|
|
|
|
else if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'mysql' then
|
|
|
|
lCustomers := TMVCActiveRecord.Select<TCustomer>('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
|
|
|
|
else if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'postgresql' then
|
|
|
|
lCustomers := TMVCActiveRecord.Select<TCustomer>('SELECT * FROM customers WHERE description ILIKE ''%google%''', [])
|
|
|
|
else if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'sqlite' then
|
|
|
|
lCustomers := TMVCActiveRecord.Select<TCustomer>('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
|
2019-05-19 20:23:45 +02:00
|
|
|
else
|
2019-09-13 15:17:56 +02:00
|
|
|
raise Exception.Create('Unsupported backend: ' + ActiveRecordConnectionsRegistry.GetCurrentBackend);
|
2019-01-13 18:56:33 +01:00
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
try
|
|
|
|
for lCustomer in lCustomers do
|
|
|
|
begin
|
2020-01-04 12:53:53 +01:00
|
|
|
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault]));
|
2018-10-23 16:18:34 +02:00
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lCustomers.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
Log('** Query SQL returning DataSet');
|
2019-02-21 18:11:14 +01:00
|
|
|
lDS := TMVCActiveRecord.SelectDataSet('SELECT * FROM customers', []);
|
2018-10-23 16:18:34 +02:00
|
|
|
try
|
|
|
|
while not lDS.Eof do
|
|
|
|
begin
|
2019-09-13 15:17:56 +02:00
|
|
|
Log(Format('%8.5s - %s', [lDS.FieldByName('code').AsString, lDS.FieldByName('description').AsString]));
|
2018-10-23 16:18:34 +02:00
|
|
|
lDS.Next;
|
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lDS.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
2019-02-21 20:17:11 +01:00
|
|
|
procedure TMainForm.btnTransientFieldsClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
lCustomer: TCustomerWithTransient;
|
|
|
|
lID: Integer;
|
|
|
|
begin
|
2019-12-17 17:34:23 +01:00
|
|
|
Log('** CRUD test with transient fields');
|
2019-02-21 20:17:11 +01:00
|
|
|
lCustomer := TCustomerWithTransient.Create;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
'Code' and City will not be persisted because defined as 'transient'
|
|
|
|
}
|
|
|
|
lCustomer.Code := '1234';
|
|
|
|
lCustomer.CompanyName := 'Google Inc.';
|
|
|
|
lCustomer.City := 'Montain View, CA';
|
|
|
|
lCustomer.Insert;
|
|
|
|
lID := lCustomer.ID;
|
|
|
|
Log('Just inserted "transient" Customer ' + lID.ToString);
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithTransient>(lID);
|
|
|
|
try
|
|
|
|
lCustomer.CompanyName := lCustomer.CompanyName + ' changed!';
|
|
|
|
lCustomer.Code := 'this code will not be saved';
|
|
|
|
lCustomer.Update;
|
|
|
|
Log('Just updated Customer ' + lID.ToString);
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithTransient>(lID);
|
|
|
|
try
|
|
|
|
lCustomer.Delete;
|
|
|
|
Log('Just deleted "transient" Customer ' + lID.ToString);
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
procedure TMainForm.btnValidationClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
lCustomer: TCustomerWithLogic;
|
|
|
|
lID: Integer;
|
|
|
|
begin
|
2019-12-17 17:34:23 +01:00
|
|
|
Log('** Validation test (some exceptions will be raised)');
|
2018-10-23 16:18:34 +02:00
|
|
|
lCustomer := TCustomerWithLogic.Create;
|
|
|
|
try
|
|
|
|
lCustomer.Code := '1234';
|
|
|
|
lCustomer.CompanyName := 'bit Time Professionals';
|
|
|
|
lCustomer.City := 'Rome';
|
|
|
|
lCustomer.Insert;
|
|
|
|
lID := lCustomer.ID;
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
|
2019-08-02 12:32:23 +02:00
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithLogic>(lID);
|
2018-10-23 16:18:34 +02:00
|
|
|
try
|
2019-09-13 15:17:56 +02:00
|
|
|
Log(lCustomer.CompanyName + ' => IsLocatedInRome: ' + BoolToStr(lCustomer.IsLocatedInRome, True));
|
2018-10-23 16:18:34 +02:00
|
|
|
lCustomer.Code := '';
|
|
|
|
lCustomer.Update; // raise exception
|
|
|
|
finally
|
|
|
|
lCustomer.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-01-04 12:53:53 +01:00
|
|
|
procedure TMainForm.Button1Click(Sender: TObject);
|
|
|
|
var
|
|
|
|
l: NullableString;
|
|
|
|
begin
|
|
|
|
Assert(not l.HasValue);
|
|
|
|
l := 'Ciao Mondo';
|
|
|
|
Assert(l.HasValue);
|
|
|
|
var ss: String := l;
|
|
|
|
Assert(l.HasValue);
|
|
|
|
Assert(l = 'Ciao Mondo');
|
|
|
|
Assert(l.HasValue);
|
|
|
|
l.SetNull;
|
|
|
|
Assert(not l.HasValue);
|
|
|
|
try
|
|
|
|
var s: String := l;
|
|
|
|
except
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2019-09-13 15:17:56 +02:00
|
|
|
procedure TMainForm.FormDestroy(Sender: TObject);
|
2018-10-23 16:18:34 +02:00
|
|
|
begin
|
2019-12-17 17:34:23 +01:00
|
|
|
ActiveRecordConnectionsRegistry.RemoveDefaultConnection;
|
2018-10-23 16:18:34 +02:00
|
|
|
end;
|
|
|
|
|
2019-09-13 15:17:56 +02:00
|
|
|
procedure TMainForm.FormShow(Sender: TObject);
|
2019-01-08 12:48:27 +01:00
|
|
|
begin
|
2019-09-13 15:17:56 +02:00
|
|
|
case TEngineChoiceForm.Execute of
|
|
|
|
TRDBMSEngine.PostgreSQL:
|
|
|
|
begin
|
|
|
|
FDConnectionConfigU.CreatePostgresqlPrivateConnDef(True);
|
|
|
|
end;
|
|
|
|
TRDBMSEngine.Firebird:
|
|
|
|
begin
|
|
|
|
FDConnectionConfigU.CreateFirebirdPrivateConnDef(True);
|
|
|
|
end;
|
|
|
|
TRDBMSEngine.Interbase:
|
|
|
|
begin
|
|
|
|
raise Exception.Create('This DEMO doesn''t support Interbase (while the framework does)');
|
|
|
|
end;
|
|
|
|
TRDBMSEngine.MySQL:
|
|
|
|
begin
|
|
|
|
FDConnectionConfigU.CreateMySQLPrivateConnDef(True);
|
|
|
|
end;
|
|
|
|
TRDBMSEngine.MariaDB:
|
|
|
|
begin
|
|
|
|
FDConnectionConfigU.CreateMySQLPrivateConnDef(True);
|
|
|
|
end;
|
|
|
|
TRDBMSEngine.SQLite:
|
|
|
|
begin
|
|
|
|
FDConnectionConfigU.CreateSqlitePrivateConnDef(True);
|
|
|
|
end;
|
|
|
|
TRDBMSEngine.MSSQLServer:
|
|
|
|
begin
|
|
|
|
// FDConnectionConfigU.CreatePostgresqlPrivateConnDef(True);
|
|
|
|
raise Exception.Create('This DEMO doesn''t support MSSQLServer (while the framework does)');
|
|
|
|
end;
|
|
|
|
else
|
|
|
|
raise Exception.Create('Unknown RDBMS');
|
|
|
|
end;
|
|
|
|
|
|
|
|
FDConnection1.Params.Clear;
|
|
|
|
FDConnection1.ConnectionDefName := FDConnectionConfigU.CON_DEF_NAME;
|
|
|
|
FDConnection1.Connected := True;
|
|
|
|
|
2019-12-17 17:34:23 +01:00
|
|
|
ActiveRecordConnectionsRegistry.AddDefaultConnection(FDConnection1);
|
2019-09-13 15:17:56 +02:00
|
|
|
Caption := Caption + ' (Curr Backend: ' + ActiveRecordConnectionsRegistry.GetCurrentBackend + ')';
|
2019-01-08 12:48:27 +01:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.Log(const Value: string);
|
2018-10-23 16:18:34 +02:00
|
|
|
begin
|
|
|
|
Memo1.Lines.Add(Value);
|
2019-12-17 17:34:23 +01:00
|
|
|
Memo1.Update;
|
2018-10-23 16:18:34 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|