2021-04-05 18:45:55 +02:00
|
|
|
|
unit MainFormU;
|
2018-10-23 16:18:34 +02:00
|
|
|
|
|
|
|
|
|
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,
|
2021-11-18 00:49:12 +01:00
|
|
|
|
Data.DB,
|
|
|
|
|
FireDAC.Comp.Client,
|
|
|
|
|
MVCFramework.Nullables,
|
|
|
|
|
MVCFramework.ActiveRecord,
|
2022-11-17 19:33:27 +01:00
|
|
|
|
System.Generics.Collections, System.Diagnostics;
|
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;
|
2022-11-15 09:27:08 +01:00
|
|
|
|
btnReadOnlyFields: TButton;
|
2019-06-24 20:59:33 +02:00
|
|
|
|
FDConnection1: TFDConnection;
|
2020-01-04 12:53:53 +01:00
|
|
|
|
btnNullTest: TButton;
|
2020-03-27 00:37:28 +01:00
|
|
|
|
btnCRUDNoAutoInc: TButton;
|
2020-03-31 16:23:22 +02:00
|
|
|
|
btnCRUDWithStringPKs: TButton;
|
2020-04-08 18:04:45 +02:00
|
|
|
|
btnWithSpaces: TButton;
|
2020-06-19 19:31:34 +02:00
|
|
|
|
btnCountWithRQL: TButton;
|
2020-08-11 00:54:42 +02:00
|
|
|
|
btnReadAndWriteOnly: TButton;
|
2020-08-13 17:40:02 +02:00
|
|
|
|
btnClientGeneratedPK: TButton;
|
2020-08-28 18:04:29 +02:00
|
|
|
|
btnAttributes: TButton;
|
2021-03-20 00:30:20 +01:00
|
|
|
|
btnJSON_XML_Types: TButton;
|
2021-04-25 22:40:06 +02:00
|
|
|
|
btnMerge: TButton;
|
2021-11-17 15:36:20 +01:00
|
|
|
|
btnTableFilter: TButton;
|
2021-11-18 00:49:12 +01:00
|
|
|
|
btnPartitioning: TButton;
|
2022-06-16 14:05:01 +02:00
|
|
|
|
btnCRUDWithGUID: TButton;
|
2022-11-10 18:30:11 +01:00
|
|
|
|
btnOOP: TButton;
|
|
|
|
|
btnReadOnly: TButton;
|
2022-11-17 19:33:27 +01:00
|
|
|
|
btnSpeed: TButton;
|
2023-01-29 17:29:24 +01:00
|
|
|
|
btnRefresh: 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);
|
2022-11-15 09:27:08 +01:00
|
|
|
|
procedure btnReadOnlyFieldsClick(Sender: TObject);
|
2019-09-13 15:17:56 +02:00
|
|
|
|
procedure FormShow(Sender: TObject);
|
2020-01-04 12:53:53 +01:00
|
|
|
|
procedure btnNullablesClick(Sender: TObject);
|
|
|
|
|
procedure btnNullTestClick(Sender: TObject);
|
2020-03-27 00:37:28 +01:00
|
|
|
|
procedure btnCRUDNoAutoIncClick(Sender: TObject);
|
2020-03-31 16:23:22 +02:00
|
|
|
|
procedure btnCRUDWithStringPKsClick(Sender: TObject);
|
2020-04-08 18:04:45 +02:00
|
|
|
|
procedure btnWithSpacesClick(Sender: TObject);
|
2020-06-19 19:31:34 +02:00
|
|
|
|
procedure btnCountWithRQLClick(Sender: TObject);
|
2020-08-11 00:54:42 +02:00
|
|
|
|
procedure btnReadAndWriteOnlyClick(Sender: TObject);
|
2020-08-13 17:40:02 +02:00
|
|
|
|
procedure btnClientGeneratedPKClick(Sender: TObject);
|
2020-08-28 18:04:29 +02:00
|
|
|
|
procedure btnAttributesClick(Sender: TObject);
|
2021-03-20 00:30:20 +01:00
|
|
|
|
procedure btnJSON_XML_TypesClick(Sender: TObject);
|
2021-04-25 22:40:06 +02:00
|
|
|
|
procedure btnMergeClick(Sender: TObject);
|
2021-11-17 15:36:20 +01:00
|
|
|
|
procedure btnTableFilterClick(Sender: TObject);
|
2021-11-18 00:49:12 +01:00
|
|
|
|
procedure btnPartitioningClick(Sender: TObject);
|
2022-06-16 14:05:01 +02:00
|
|
|
|
procedure btnCRUDWithGUIDClick(Sender: TObject);
|
2022-11-10 18:30:11 +01:00
|
|
|
|
procedure btnOOPClick(Sender: TObject);
|
|
|
|
|
procedure btnReadOnlyClick(Sender: TObject);
|
2022-11-17 19:33:27 +01:00
|
|
|
|
procedure btnSpeedClick(Sender: TObject);
|
2023-01-29 17:29:24 +01:00
|
|
|
|
procedure btnRefreshClick(Sender: TObject);
|
2018-10-23 16:18:34 +02:00
|
|
|
|
private
|
|
|
|
|
procedure Log(const Value: string);
|
2020-06-25 22:54:57 +02:00
|
|
|
|
procedure LoadCustomers;
|
2018-10-23 16:18:34 +02:00
|
|
|
|
public
|
|
|
|
|
{ Public declarations }
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
var
|
|
|
|
|
MainForm: TMainForm;
|
|
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
|
|
{$R *.dfm}
|
|
|
|
|
|
2021-04-26 23:01:31 +02:00
|
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
|
uses
|
|
|
|
|
EntitiesU,
|
|
|
|
|
System.Threading,
|
|
|
|
|
MVCFramework.DataSet.Utils,
|
|
|
|
|
MVCFramework.RQL.Parser,
|
|
|
|
|
System.Math,
|
2021-11-18 00:49:12 +01:00
|
|
|
|
FDConnectionConfigU,
|
|
|
|
|
EngineChoiceFormU,
|
|
|
|
|
System.Rtti;
|
2018-10-23 16:18:34 +02:00
|
|
|
|
|
2020-06-19 19:31:34 +02:00
|
|
|
|
const
|
|
|
|
|
Cities: array [0 .. 4] of string = ('Rome', 'New York', 'London', 'Melbourne', 'Berlin');
|
|
|
|
|
CompanySuffix: array [0 .. 5] of string = ('Corp.', 'Inc.', 'Ltd.', 'Srl', 'SPA', 'doo');
|
|
|
|
|
Stuff: array [0 .. 4] of string = ('Burger', 'GAS', 'Motors', 'House', 'Boats');
|
|
|
|
|
|
2020-08-28 18:04:29 +02:00
|
|
|
|
procedure TMainForm.btnAttributesClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
|
lID: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Log('** Dynamic Properties Access');
|
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustomer.Attributes['CompanyName'] := 'Google Inc.';
|
|
|
|
|
lCustomer.Attributes['City'] := 'Montain View, CA';
|
|
|
|
|
lCustomer.Attributes['Note'] := 'Hello there!';
|
|
|
|
|
lCustomer.Attributes['Code'] := 'XX123';
|
|
|
|
|
lCustomer.Attributes['Rating'] := 3;
|
|
|
|
|
lCustomer.Insert;
|
|
|
|
|
lID := lCustomer.ID;
|
|
|
|
|
Log('Just inserted Customer ' + lID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomer>(lID);
|
|
|
|
|
try
|
|
|
|
|
Assert('Google Inc.' = lCustomer.Attributes['CompanyName'].AsType<NullableString>().Value);
|
|
|
|
|
Assert('Montain View, CA' = lCustomer.Attributes['City'].AsString);
|
|
|
|
|
Assert('XX123' = lCustomer.Attributes['Code'].AsType<NullableString>().Value);
|
|
|
|
|
Assert('Hello there!' = lCustomer.Attributes['Note'].AsString);
|
|
|
|
|
lCustomer.Update;
|
|
|
|
|
Log('Just updated Customer ' + lID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustomer.LoadByPK(lID);
|
|
|
|
|
lCustomer.Code.Value := '9012';
|
|
|
|
|
lCustomer.Update;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-08-13 17:40:02 +02:00
|
|
|
|
procedure TMainForm.btnClientGeneratedPKClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lCustomer: TCustomerPlainWithClientPK;
|
|
|
|
|
begin
|
|
|
|
|
Log('** OnBeforeInsert and SetPK');
|
|
|
|
|
lCustomer := TCustomerPlainWithClientPK.Create();
|
|
|
|
|
try
|
|
|
|
|
lCustomer.Store;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-06-19 19:31:34 +02:00
|
|
|
|
procedure TMainForm.btnCountWithRQLClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lRQL: string;
|
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
|
I: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Log('** TMVCActiveRecord.Count<TCustomer>(RQL) [Just uses Filter]');
|
|
|
|
|
|
|
|
|
|
TMVCActiveRecord.DeleteAll(TCustomer);
|
|
|
|
|
for I := 1 to 30 do
|
|
|
|
|
begin
|
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustomer.Code := Format('%5.5d', [TThread.CurrentThread.ThreadID, I]);
|
|
|
|
|
lCustomer.City := Cities[Random(high(Cities) + 1)];
|
|
|
|
|
lCustomer.CompanyName := Format('%s %s %s', [lCustomer.City, Stuff[Random(high(Stuff) + 1)],
|
|
|
|
|
CompanySuffix[Random(high(CompanySuffix) + 1)]]);
|
|
|
|
|
lCustomer.Note := lCustomer.CompanyName + ' is from ' + lCustomer.City;
|
|
|
|
|
lCustomer.Insert;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lRQL := 'contains(city,"e")';
|
|
|
|
|
Log(lRQL + ' => ' + TMVCActiveRecord.Count<TCustomer>(lRQL).ToString);
|
|
|
|
|
|
|
|
|
|
lRQL := 'contains(city,"e");sort(+city)';
|
|
|
|
|
Log(lRQL + ' => ' + TMVCActiveRecord.Count<TCustomer>(lRQL).ToString);
|
|
|
|
|
|
|
|
|
|
lRQL := 'contains(city,"e");limit(1,1)';
|
|
|
|
|
Log(lRQL + ' => ' + TMVCActiveRecord.Count<TCustomer>(lRQL).ToString);
|
|
|
|
|
|
|
|
|
|
lRQL := 'contains(city,"e");sort(+city);limit(1,1)';
|
|
|
|
|
Log(lRQL + ' => ' + TMVCActiveRecord.Count<TCustomer>(lRQL).ToString);
|
|
|
|
|
|
|
|
|
|
lRQL := 'contains(city,"e");sort(+city);limit(0,5)';
|
|
|
|
|
Log(lRQL + ' => ' + TMVCActiveRecord.Count<TCustomer>(lRQL).ToString);
|
|
|
|
|
end;
|
|
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
|
procedure TMainForm.btnCRUDClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
|
lID: Integer;
|
2021-04-05 18:45:55 +02:00
|
|
|
|
lTestNote: string;
|
2018-10-23 16:18:34 +02:00
|
|
|
|
begin
|
2019-12-17 17:34:23 +01:00
|
|
|
|
Log('** Simple CRUD test');
|
2020-08-28 18:04:29 +02:00
|
|
|
|
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
|
2020-08-11 00:54:42 +02:00
|
|
|
|
Log('Entity ' + TCustomer.ClassName + ' is mapped to table ' + lCustomer.TableName);
|
2018-10-23 16:18:34 +02:00
|
|
|
|
lCustomer.CompanyName := 'Google Inc.';
|
|
|
|
|
lCustomer.City := 'Montain View, CA';
|
2021-11-21 19:27:06 +01:00
|
|
|
|
lCustomer.Note := 'Μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος οὐλομένην 😁';
|
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';
|
2021-04-05 18:45:55 +02:00
|
|
|
|
lCustomer.Note := lCustomer.Note + sLineBreak + 'Code changed to 5678 🙂';
|
|
|
|
|
lTestNote := lCustomer.Note;
|
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);
|
2021-04-05 18:45:55 +02:00
|
|
|
|
lCustomer.Code.Value := '😉9012🙂';
|
|
|
|
|
lCustomer.Update;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustomer.LoadByPK(lID);
|
|
|
|
|
Assert(lCustomer.Code.Value = '😉9012🙂');
|
|
|
|
|
Assert(lCustomer.Note = lTestNote);
|
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;
|
|
|
|
|
|
2020-03-27 00:37:28 +01:00
|
|
|
|
procedure TMainForm.btnCRUDNoAutoIncClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lCustomer: TCustomerPlain;
|
|
|
|
|
lID: Integer;
|
|
|
|
|
I: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Log('** Simple CRUD (no autoinc) test');
|
|
|
|
|
Log('There are ' + TMVCActiveRecord.Count<TCustomerPlain>().ToString + ' row/s for entity ' +
|
|
|
|
|
TCustomerPlain.ClassName);
|
|
|
|
|
TMVCActiveRecord.DeleteAll(TCustomerPlain);
|
|
|
|
|
Log('Deleting all entities ' + TCustomerPlain.ClassName);
|
|
|
|
|
for I := 1 to 100 do
|
|
|
|
|
begin
|
|
|
|
|
lCustomer := TCustomerPlain.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustomer.ID := I;
|
|
|
|
|
// just for test!!
|
|
|
|
|
case I mod 3 of
|
|
|
|
|
0:
|
|
|
|
|
lCustomer.CompanyName := 'Google Inc.';
|
|
|
|
|
1:
|
|
|
|
|
lCustomer.CompanyName := 'bit Time Professionals';
|
|
|
|
|
2:
|
|
|
|
|
lCustomer.CompanyName := 'Walt Disney Corp.';
|
|
|
|
|
end;
|
|
|
|
|
lCustomer.City := 'Montain View, CA';
|
|
|
|
|
lCustomer.Note := 'Hello there!';
|
2020-06-25 22:54:57 +02:00
|
|
|
|
lCustomer.CreationTime := Time;
|
|
|
|
|
lCustomer.CreationDate := Date;
|
2020-03-27 00:37:28 +01:00
|
|
|
|
lCustomer.Insert;
|
|
|
|
|
lID := lCustomer.ID;
|
|
|
|
|
Log('Just inserted Customer ' + lID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('Now there are ' + TMVCActiveRecord.Count<TCustomerPlain>().ToString + ' row/s for entity ' +
|
|
|
|
|
TCustomerPlain.ClassName);
|
|
|
|
|
TMVCActiveRecord.DeleteRQL(TCustomerPlain, 'lt(id,90)');
|
|
|
|
|
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerPlain>(lID);
|
|
|
|
|
try
|
|
|
|
|
Assert(not lCustomer.Code.HasValue);
|
|
|
|
|
lCustomer.Code.Value := '5678';
|
|
|
|
|
lCustomer.Note := lCustomer.Note + sLineBreak + 'Code changed to 5678';
|
|
|
|
|
lCustomer.Update;
|
|
|
|
|
Log('Just updated Customer ' + lID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustomer := TCustomerPlain.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustomer.LoadByPK(lID);
|
|
|
|
|
lCustomer.Code.Value := '9012';
|
|
|
|
|
lCustomer.Update;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerPlain>(lID);
|
|
|
|
|
try
|
|
|
|
|
lCustomer.Delete;
|
|
|
|
|
Log('Just deleted Customer ' + lID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2022-06-16 14:05:01 +02:00
|
|
|
|
procedure TMainForm.btnCRUDWithGUIDClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lTestNote: string;
|
|
|
|
|
lCustWithGUID: TCustomerWithGUID;
|
|
|
|
|
lIDGUID: TGUID;
|
|
|
|
|
begin
|
2022-06-19 18:57:47 +02:00
|
|
|
|
TMVCActiveRecord.DeleteAll(TCustomerWithGUID);
|
|
|
|
|
|
2022-06-16 14:05:01 +02:00
|
|
|
|
Log('** Using GUID as primary key');
|
|
|
|
|
|
|
|
|
|
lCustWithGUID := TCustomerWithGUID.Create;
|
|
|
|
|
try
|
|
|
|
|
Log('Entity ' + TCustomerWithGUID.ClassName + ' is mapped to table ' + lCustWithGUID.TableName);
|
|
|
|
|
lCustWithGUID.GUID := TGUID.NewGuid;
|
|
|
|
|
lCustWithGUID.CompanyName := 'Google Inc.';
|
|
|
|
|
lCustWithGUID.City := 'Montain View, CA';
|
|
|
|
|
lCustWithGUID.Note := 'Μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος οὐλομένην 😁';
|
|
|
|
|
lCustWithGUID.Insert;
|
|
|
|
|
lIDGUID := lCustWithGUID.GUID;
|
|
|
|
|
Log('Just inserted Customer With GUID ' + lIDGUID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustWithGUID.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustWithGUID := TMVCActiveRecord.GetByPK<TCustomerWithGUID>(lIDGUID);
|
|
|
|
|
try
|
|
|
|
|
Assert(not lCustWithGUID.Code.HasValue);
|
|
|
|
|
lCustWithGUID.Code.Value := '5678';
|
|
|
|
|
lCustWithGUID.Note := lCustWithGUID.Note + sLineBreak + 'Code changed to 5678 🙂';
|
|
|
|
|
lTestNote := lCustWithGUID.Note;
|
|
|
|
|
lCustWithGUID.Update;
|
|
|
|
|
Log('Just updated Customer ' + lIDGUID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustWithGUID.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustWithGUID := TCustomerWithGUID.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustWithGUID.LoadByPK(lIDGUID);
|
|
|
|
|
lCustWithGUID.Code.Value := '😉9012🙂';
|
|
|
|
|
lCustWithGUID.Update;
|
|
|
|
|
finally
|
|
|
|
|
lCustWithGUID.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustWithGUID := TMVCActiveRecord.GetByPK<TCustomerWithGUID>(lIDGUID);
|
|
|
|
|
try
|
|
|
|
|
lCustWithGUID.Delete;
|
|
|
|
|
Log('Just deleted Customer ' + lIDGUID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustWithGUID.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-03-31 16:23:22 +02:00
|
|
|
|
procedure TMainForm.btnCRUDWithStringPKsClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lCustomer: TCustomerWithCode;
|
|
|
|
|
lCode: string;
|
|
|
|
|
I: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Log('** Simple CRUD (with string pks) test');
|
|
|
|
|
Log('There are ' + TMVCActiveRecord.Count<TCustomerWithCode>().ToString + ' row/s for entity ' +
|
|
|
|
|
TCustomerWithCode.ClassName);
|
|
|
|
|
TMVCActiveRecord.DeleteAll(TCustomerWithCode);
|
|
|
|
|
Log('Deleting all entities ' + TCustomerWithCode.ClassName);
|
|
|
|
|
for I := 1 to 100 do
|
|
|
|
|
begin
|
|
|
|
|
lCustomer := TCustomerWithCode.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustomer.Code := I.ToString.PadLeft(4, '0');
|
|
|
|
|
// just for test!!
|
|
|
|
|
case I mod 3 of
|
|
|
|
|
0:
|
|
|
|
|
lCustomer.CompanyName := 'Google Inc.';
|
|
|
|
|
1:
|
|
|
|
|
lCustomer.CompanyName := 'bit Time Professionals';
|
|
|
|
|
2:
|
|
|
|
|
lCustomer.CompanyName := 'Walt Disney Corp.';
|
|
|
|
|
end;
|
|
|
|
|
lCustomer.City := 'Montain View, CA';
|
|
|
|
|
lCustomer.Note := 'Hello there!';
|
|
|
|
|
lCustomer.Insert;
|
|
|
|
|
lCode := lCustomer.Code.Value;
|
|
|
|
|
Log('Just inserted Customer ' + lCode);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-08-28 18:04:29 +02:00
|
|
|
|
Log('Now there are ' + TMVCActiveRecord.Count<TCustomerWithCode>().ToString + ' row/s for entity '
|
|
|
|
|
+ TCustomerPlain.ClassName);
|
2020-03-31 16:23:22 +02:00
|
|
|
|
TMVCActiveRecord.DeleteRQL(TCustomerWithCode, 'lt(code,"0090")');
|
|
|
|
|
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithCode>(lCode);
|
|
|
|
|
try
|
|
|
|
|
Assert(lCustomer.Code.HasValue);
|
|
|
|
|
lCustomer.Note := lCustomer.Note + sLineBreak + 'Note changed!';
|
|
|
|
|
lCustomer.Update;
|
|
|
|
|
Log('Just updated Customer ' + lCode);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustomer := TCustomerWithCode.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustomer.LoadByPK(lCode);
|
|
|
|
|
lCustomer.CompanyName := 'My New Company!';
|
|
|
|
|
lCustomer.Update;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithCode>(lCode);
|
|
|
|
|
try
|
|
|
|
|
lCustomer.Delete;
|
|
|
|
|
Log('Just deleted Customer ' + lCode);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
|
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;
|
|
|
|
|
|
2021-03-20 00:30:20 +01:00
|
|
|
|
procedure TMainForm.btnJSON_XML_TypesClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lCTypes: TComplexTypes;
|
|
|
|
|
lID: Int64;
|
|
|
|
|
begin
|
2022-10-29 00:34:49 +02:00
|
|
|
|
if GetBackEndByConnection(TMVCActiveRecord.CurrentConnection) = TMVCActiveRecordBackEnd.PostgreSQL then
|
|
|
|
|
begin
|
|
|
|
|
TMVCActiveRecord.DeleteAll(TComplexTypes);
|
2021-03-20 00:30:20 +01:00
|
|
|
|
|
2022-10-29 00:34:49 +02:00
|
|
|
|
lCTypes := TComplexTypes.Create;
|
|
|
|
|
try
|
|
|
|
|
lCTypes.JSON := '{"field_type":"json"}';
|
|
|
|
|
lCTypes.JSONB := '{"field_type":"jsonb"}';
|
|
|
|
|
lCTypes.XML := '<field_type>xml</field_type>';
|
|
|
|
|
lCTypes.Insert;
|
|
|
|
|
lID := lCTypes.ID;
|
|
|
|
|
finally
|
|
|
|
|
lCTypes.Free;
|
|
|
|
|
end;
|
2021-03-20 00:30:20 +01:00
|
|
|
|
|
2022-10-29 00:34:49 +02:00
|
|
|
|
lCTypes := TMVCActiveRecord.GetByPK<TComplexTypes>(lID);
|
|
|
|
|
try
|
|
|
|
|
lCTypes.JSON := '{"field_type":"json", "updated": true}';
|
|
|
|
|
lCTypes.JSONB := '{"field_type":"jsonb", "updated": true}';
|
|
|
|
|
lCTypes.XML := '<field_type updated="true">xml</field_type>';
|
|
|
|
|
lCTypes.Update;
|
|
|
|
|
finally
|
|
|
|
|
lCTypes.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('Executing ==> (jsonb_field ->> ''updated'')::bool = true');
|
|
|
|
|
lCTypes := TMVCActiveRecord.GetFirstByWhere<TComplexTypes>('(jsonb_field ->> ''updated'')::bool = true', []);
|
|
|
|
|
try
|
|
|
|
|
Log('JSON ==> ' + lCTypes.JSON);
|
|
|
|
|
finally
|
|
|
|
|
lCTypes.Free;
|
|
|
|
|
end;
|
2021-03-20 00:30:20 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2021-04-25 22:40:06 +02:00
|
|
|
|
procedure TMainForm.btnMergeClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
|
lCustomers: TObjectList<TCustomer>;
|
|
|
|
|
lCustomersChanges: TObjectList<TCustomer>;
|
|
|
|
|
begin
|
2021-04-29 22:52:28 +02:00
|
|
|
|
Log('** IMVCMultiExecutor demo');
|
2021-04-25 22:40:06 +02:00
|
|
|
|
TMVCActiveRecord.DeleteAll(TCustomer);
|
|
|
|
|
LoadCustomers;
|
2021-04-29 22:52:28 +02:00
|
|
|
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,1)', 1000);
|
2021-04-25 22:40:06 +02:00
|
|
|
|
try
|
2021-04-29 22:52:28 +02:00
|
|
|
|
lCustomersChanges := TObjectList<TCustomer>.Create(True);
|
2021-04-25 22:40:06 +02:00
|
|
|
|
try
|
2021-04-29 22:52:28 +02:00
|
|
|
|
//these 2 customers will be updated
|
2021-04-25 22:40:06 +02:00
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
lCustomersChanges.Add(lCustomer);
|
2021-04-29 22:52:28 +02:00
|
|
|
|
lCustomer.ID := lCustomers[0].ID;
|
2021-04-25 22:40:06 +02:00
|
|
|
|
lCustomer.Code := 'C8765';
|
2021-04-29 22:52:28 +02:00
|
|
|
|
lCustomer.CompanyName := '(changed) Company1';
|
|
|
|
|
lCustomer.City := '(changed) City';
|
|
|
|
|
lCustomer.Rating := 1;
|
2021-04-25 22:40:06 +02:00
|
|
|
|
|
2021-04-29 22:52:28 +02:00
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
lCustomersChanges.Add(lCustomer);
|
|
|
|
|
lCustomer.ID := lCustomers[1].ID;
|
|
|
|
|
lCustomer.Code := lCustomers[1].Code;
|
|
|
|
|
lCustomer.CompanyName := '(changed) Company2';
|
|
|
|
|
lCustomer.City := '(changed) City';
|
|
|
|
|
lCustomer.Rating := 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//these 2 customer will be created
|
2021-04-25 22:40:06 +02:00
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
lCustomersChanges.Add(lCustomer);
|
|
|
|
|
lCustomer.Code := 'C9898';
|
2021-04-29 22:52:28 +02:00
|
|
|
|
lCustomer.CompanyName := '(new) Company3';
|
|
|
|
|
lCustomer.City := '(new) New City2';
|
|
|
|
|
lCustomer.Rating := 1;
|
|
|
|
|
|
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
lCustomersChanges.Add(lCustomer);
|
|
|
|
|
lCustomer.Code := 'C2343';
|
|
|
|
|
lCustomer.CompanyName := '(new) Company4';
|
|
|
|
|
lCustomer.City := '(new) New City2';
|
|
|
|
|
lCustomer.Rating := 1;
|
2021-04-25 22:40:06 +02:00
|
|
|
|
|
2021-04-29 22:52:28 +02:00
|
|
|
|
//all the other customers will be deleted
|
|
|
|
|
|
2021-05-03 19:29:01 +02:00
|
|
|
|
//calculate the unit-of-work to merge the lists
|
2022-10-29 00:34:49 +02:00
|
|
|
|
var lUOW := TMVCActiveRecord.Merge<TCustomer>(lCustomers, lCustomersChanges);
|
|
|
|
|
//apply the UnitOfWork
|
|
|
|
|
lUOW.Apply(
|
2021-04-29 22:52:28 +02:00
|
|
|
|
procedure (const Customer: TCustomer; const EntityAction: TMVCEntityAction; var Handled: Boolean)
|
|
|
|
|
begin
|
|
|
|
|
Handled := False; //set it to true to execute action manually
|
|
|
|
|
case EntityAction of
|
|
|
|
|
eaCreate: Log('Inserting Customer : ' + Customer.ToString);
|
|
|
|
|
eaUpdate: Log('Updating Customer : ' + Customer.ToString);
|
|
|
|
|
eaDelete: Log('Deleting Customer : ' + Customer.ToString);
|
|
|
|
|
end;
|
|
|
|
|
end);
|
2022-10-29 00:34:49 +02:00
|
|
|
|
|
|
|
|
|
|
2021-04-25 22:40:06 +02:00
|
|
|
|
finally
|
2021-05-03 19:29:01 +02:00
|
|
|
|
lCustomersChanges.Free;
|
2021-04-25 22:40:06 +02:00
|
|
|
|
end;
|
|
|
|
|
finally
|
2021-05-03 19:29:01 +02:00
|
|
|
|
lCustomers.Free;
|
2021-04-25 22:40:06 +02:00
|
|
|
|
end;
|
2021-04-29 22:52:28 +02:00
|
|
|
|
|
|
|
|
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,1)', 1000);
|
|
|
|
|
try
|
|
|
|
|
Assert(lCustomers.Count = 4, 'Expected 4 customers, got ' + lCustomers.Count.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustomers.Free;
|
|
|
|
|
end;
|
2021-04-25 22:40:06 +02:00
|
|
|
|
end;
|
|
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
|
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
|
|
|
|
begin
|
2019-12-17 17:34:23 +01:00
|
|
|
|
Log('** Multithreading test');
|
2020-08-28 18:04:29 +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;
|
2021-03-03 18:42:59 +01:00
|
|
|
|
ActiveRecordConnectionsRegistry.AddDefaultConnection(lConn, True);
|
2019-01-13 18:56:33 +01:00
|
|
|
|
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)];
|
2020-08-28 18:04:29 +02:00
|
|
|
|
lCustomer.CompanyName :=
|
|
|
|
|
Format('%s %s %s', [lCustomer.City, Stuff[Random(high(Stuff) + 1)],
|
2020-03-23 18:51:57 +01:00
|
|
|
|
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
|
2021-03-03 18:42:59 +01:00
|
|
|
|
ActiveRecordConnectionsRegistry.RemoveDefaultConnection;
|
2018-10-23 16:18:34 +02:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2021-04-25 22:40:06 +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),
|
2020-08-28 18:04:29 +02:00
|
|
|
|
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),
|
2021-04-25 22:40:06 +02:00
|
|
|
|
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');
|
2020-08-28 18:04:29 +02:00
|
|
|
|
Log('There are ' + TMVCActiveRecord.Count<TCustomer>().ToString + ' row/s for entity ' +
|
|
|
|
|
TCustomer.ClassName);
|
2020-01-04 12:53:53 +01:00
|
|
|
|
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;
|
2020-01-06 16:49:18 +01:00
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
|
lID: Integer;
|
2020-01-04 12:53:53 +01:00
|
|
|
|
begin
|
2020-01-06 16:49:18 +01:00
|
|
|
|
Log('** Nullables Test');
|
|
|
|
|
TMVCActiveRecord.DeleteAll(TNullablesTest);
|
|
|
|
|
|
|
|
|
|
lTest := TNullablesTest.Create();
|
|
|
|
|
try
|
|
|
|
|
lTest.f_int2 := 2;
|
|
|
|
|
lTest.f_int4 := 4;
|
|
|
|
|
lTest.f_int8 := 8;
|
2020-08-11 00:54:42 +02:00
|
|
|
|
with TStreamWriter.Create(lTest.f_blob) do
|
|
|
|
|
try
|
|
|
|
|
write('Hello World');
|
|
|
|
|
finally
|
|
|
|
|
Free;
|
|
|
|
|
end;
|
2020-01-06 16:49:18 +01:00
|
|
|
|
lTest.Insert;
|
|
|
|
|
Log('Inserting nulls');
|
|
|
|
|
finally
|
|
|
|
|
lTest.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('Loading records with nulls');
|
|
|
|
|
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);
|
|
|
|
|
Assert(Assigned(lTest));
|
|
|
|
|
lTest.f_int4 := lTest.f_int4.Value + 4;
|
|
|
|
|
lTest.f_int8 := lTest.f_int8.Value + 8;
|
2020-08-11 00:54:42 +02:00
|
|
|
|
lTest.f_blob.Size := 0;
|
2020-01-06 16:49:18 +01:00
|
|
|
|
lTest.Update;
|
|
|
|
|
finally
|
|
|
|
|
lTest.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2023-01-06 15:00:54 +01:00
|
|
|
|
lTest := TMVCActiveRecord.GetFirstByWhere<TNullablesTest>('f_int2 = ?', [2]);
|
2020-01-06 16:49:18 +01:00
|
|
|
|
try
|
2023-01-06 15:00:54 +01:00
|
|
|
|
Assert(lTest.f_int2.ValueOrDefault = 2);
|
2020-01-06 16:49:18 +01:00
|
|
|
|
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);
|
2020-08-11 00:54:42 +02:00
|
|
|
|
Assert(lTest.f_blob.Size = 0, 'Blob contains a value when should not');
|
2023-01-06 15:00:54 +01:00
|
|
|
|
TMVCActiveRecord.DeleteRQL(TNullablesTest, 'eq(f_int2,2)');
|
2020-01-06 16:49:18 +01:00
|
|
|
|
finally
|
|
|
|
|
lTest.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2023-01-06 15:00:54 +01:00
|
|
|
|
Assert(TMVCActiveRecord.GetFirstByWhere<TNullablesTest>('f_int2 = 2', [], False) = nil);
|
2020-01-04 12:53:53 +01:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2020-08-28 18:04:29 +02:00
|
|
|
|
Log('There are ' + TMVCActiveRecord.Count<TCustomer>().ToString + ' row/s for entity ' +
|
|
|
|
|
TCustomer.ClassName);
|
2020-01-06 16:49:18 +01:00
|
|
|
|
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 + ' with nulls');
|
|
|
|
|
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;
|
|
|
|
|
|
2020-01-04 12:53:53 +01:00
|
|
|
|
end;
|
|
|
|
|
|
2021-11-18 00:49:12 +01:00
|
|
|
|
procedure TMainForm.btnPartitioningClick(Sender: TObject);
|
2022-03-31 09:31:11 +02:00
|
|
|
|
var
|
|
|
|
|
lCust1: TCustomerWithRate1;
|
|
|
|
|
lCust2: TCustomerWithRate2;
|
|
|
|
|
lList: TObjectList<TCustomerWithRate1>;
|
2021-11-18 00:49:12 +01:00
|
|
|
|
begin
|
2023-07-07 20:26:49 +02:00
|
|
|
|
Log('** Partitioning Test');
|
2021-11-18 00:49:12 +01:00
|
|
|
|
TMVCActiveRecord.DeleteAll(TCustomerWithRate1);
|
|
|
|
|
Assert(TMVCActiveRecord.Count(TCustomerWithRate1) = 0);
|
|
|
|
|
TMVCActiveRecord.DeleteAll(TCustomerWithRate2);
|
|
|
|
|
Assert(TMVCActiveRecord.Count(TCustomerWithRate2) = 0);
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lCust1 := TCustomerWithRate1.Create;
|
2021-11-18 00:49:12 +01:00
|
|
|
|
try
|
|
|
|
|
lCust1.City := 'Rome';
|
|
|
|
|
lCust1.Code := '123';
|
|
|
|
|
lCust1.Store;
|
|
|
|
|
finally
|
|
|
|
|
lCust1.Free;
|
|
|
|
|
end;
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lCust2 := TCustomerWithRate2.Create;
|
2021-11-18 00:49:12 +01:00
|
|
|
|
try
|
|
|
|
|
lCust2.City := 'Rome';
|
|
|
|
|
lCust2.Code := '456';
|
|
|
|
|
lCust2.Store;
|
|
|
|
|
Assert(TMVCActiveRecord.GetByPK<TCustomerWithRate1>(lCust2.ID, False) = nil);
|
|
|
|
|
finally
|
|
|
|
|
lCust2.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lList := TMVCActiveRecord.SelectRQL<TCustomerWithRate1>('eq(city,"Rome")',-1);
|
2021-11-18 00:49:12 +01:00
|
|
|
|
try
|
|
|
|
|
Assert(lList.Count = 1);
|
|
|
|
|
Assert(lList[0].Code = '123');
|
|
|
|
|
finally
|
|
|
|
|
lList.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2023-07-07 20:26:49 +02:00
|
|
|
|
Log('Retriving only TCustomerWithRate1');
|
2021-11-18 00:49:12 +01:00
|
|
|
|
Assert(TMVCActiveRecord.Count(TCustomerWithRate1) = 1);
|
|
|
|
|
Assert(TMVCActiveRecord.Count(TCustomerWithRate1, 'eq(code,"xxx")') = 0);
|
2023-07-07 20:26:49 +02:00
|
|
|
|
Log('Retriving only TCustomerWithRate2');
|
2021-11-18 00:49:12 +01:00
|
|
|
|
Assert(TMVCActiveRecord.Count(TCustomerWithRate2) = 1);
|
|
|
|
|
Assert(TMVCActiveRecord.Count(TCustomerWithRate2, 'eq(code,"xxx")') = 0);
|
|
|
|
|
end;
|
|
|
|
|
|
2020-08-11 00:54:42 +02:00
|
|
|
|
procedure TMainForm.btnReadAndWriteOnlyClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lArtWO, lArtWO2: TArticleWithWriteOnlyFields;
|
|
|
|
|
lArtRO: TArticleWithReadOnlyFields;
|
|
|
|
|
lID: NullableInt32;
|
|
|
|
|
lArt: TArticle;
|
|
|
|
|
begin
|
|
|
|
|
lArtWO := TArticleWithWriteOnlyFields.Create();
|
|
|
|
|
try
|
|
|
|
|
lArtWO.Description := 'Description1';
|
|
|
|
|
lArtWO.Price := 12;
|
|
|
|
|
lArtWO.Insert;
|
|
|
|
|
Log('Stored TArticleWithWriteOnlyFields');
|
|
|
|
|
lID := lArtWO.ID;
|
|
|
|
|
|
|
|
|
|
lArt := TMVCActiveRecord.GetByPK<TArticle>(lID);
|
|
|
|
|
try
|
|
|
|
|
Assert(lArtWO.Description = lArt.Description);
|
|
|
|
|
Assert(lArtWO.Price = lArt.Price);
|
|
|
|
|
Log('Check Stored version of TArticleWithWriteOnlyFields');
|
|
|
|
|
|
|
|
|
|
Log('Reading data using TArticleWithReadOnlyFields');
|
|
|
|
|
lArtRO := TMVCActiveRecord.GetByPK<TArticleWithReadOnlyFields>(lID);
|
|
|
|
|
try
|
|
|
|
|
Assert(lArtRO.Description = lArt.Description);
|
|
|
|
|
Assert(lArtRO.Price = lArt.Price);
|
|
|
|
|
Log('Check Read data of TArticleWithWriteOnlyFields using TArticleWithReadOnlyFields');
|
|
|
|
|
finally
|
|
|
|
|
lArtRO.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('Reading data using TArticleWithWriteOnlyFields (???)');
|
|
|
|
|
lArtWO2 := TMVCActiveRecord.GetByPK<TArticleWithWriteOnlyFields>(lID);
|
|
|
|
|
try
|
|
|
|
|
Assert(lArtWO2.ID.ValueOrDefault = lID.ValueOrDefault);
|
|
|
|
|
Assert(lArtWO2.Description = '');
|
|
|
|
|
Assert(lArtWO2.Price = 0);
|
|
|
|
|
finally
|
|
|
|
|
lArtWO2.Free;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
lArt.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lArtRO := TArticleWithReadOnlyFields.Create();
|
|
|
|
|
try
|
|
|
|
|
lArtRO.Description := 'Description1';
|
|
|
|
|
lArtRO.Price := 12;
|
|
|
|
|
ShowMessage('Now an exception will be raised...');
|
|
|
|
|
lArtRO.Insert; // exception here :-)
|
|
|
|
|
finally
|
|
|
|
|
lArtRO.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
finally
|
|
|
|
|
lArtWO.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2022-11-10 18:30:11 +01:00
|
|
|
|
procedure TMainForm.btnReadOnlyClick(Sender: TObject);
|
|
|
|
|
begin
|
|
|
|
|
var lROCustomer := TMVCActiveRecord.GetFirstByWhere<TReadOnlyCustomer>('',[]);
|
|
|
|
|
try
|
|
|
|
|
lROCustomer.Code := '1234';
|
|
|
|
|
ShowMessage('An exception is going to be raised');
|
|
|
|
|
lROCustomer.Update();
|
|
|
|
|
finally
|
|
|
|
|
lROCustomer.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
|
2020-08-28 18:04:29 +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
|
2020-06-25 22:54:57 +02:00
|
|
|
|
LoadCustomers;
|
2022-08-09 13:02:29 +02:00
|
|
|
|
|
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-08-28 18:04:29 +02: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-08-28 18:04:29 +02: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-08-28 18:04:29 +02: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
|
|
|
|
|
2020-10-19 19:41:16 +02:00
|
|
|
|
Log('**RQL Query (4) - <empty> with limit 20');
|
|
|
|
|
lList := TMVCActiveRecord.SelectRQL(TCustomer, '', 20);
|
|
|
|
|
try
|
|
|
|
|
Log(lList.Count.ToString + ' record/s found');
|
|
|
|
|
Assert(lList.Count = 20);
|
|
|
|
|
finally
|
|
|
|
|
lList.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('**RQL Query (5) - <empty> sort by code with limit 20');
|
|
|
|
|
lList := TMVCActiveRecord.SelectRQL(TCustomer, 'sort(+code)', 20);
|
|
|
|
|
try
|
|
|
|
|
Log(lList.Count.ToString + ' record/s found');
|
|
|
|
|
Assert(lList.Count = 20);
|
|
|
|
|
finally
|
|
|
|
|
lList.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('**RQL Query (6) - <empty> with limit 10');
|
|
|
|
|
lList := TMVCActiveRecord.SelectRQL(TCustomer, '', 10);
|
|
|
|
|
try
|
|
|
|
|
Log(lList.Count.ToString + ' record/s found');
|
|
|
|
|
Assert(lList.Count = 10);
|
|
|
|
|
finally
|
|
|
|
|
lList.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('**RQL Query (7) - <empty> with limit 1');
|
|
|
|
|
lList := TMVCActiveRecord.SelectRQL(TCustomer, '', 1);
|
|
|
|
|
try
|
|
|
|
|
Log(lList.Count.ToString + ' record/s found');
|
|
|
|
|
Assert(lList.Count = 1);
|
|
|
|
|
finally
|
|
|
|
|
lList.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('**RQL Query (8) - <empty> with limit 0');
|
|
|
|
|
lList := TMVCActiveRecord.SelectRQL(TCustomer, '', 0);
|
|
|
|
|
try
|
|
|
|
|
Log(lList.Count.ToString + ' record/s found');
|
|
|
|
|
Assert(lList.Count = 0);
|
|
|
|
|
finally
|
|
|
|
|
lList.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
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;
|
2020-02-05 23:46:38 +01:00
|
|
|
|
lID: NullableInt64;
|
2018-10-23 16:18:34 +02:00
|
|
|
|
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
|
2020-08-28 18:04:29 +02:00
|
|
|
|
lCustomers := TMVCActiveRecord.Select<TCustomer>
|
|
|
|
|
('SELECT * FROM customers WHERE description CONTAINING ?', ['google'])
|
2019-09-13 15:17:56 +02:00
|
|
|
|
else if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'mysql' then
|
2020-08-28 18:04:29 +02:00
|
|
|
|
lCustomers := TMVCActiveRecord.Select<TCustomer>
|
|
|
|
|
('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
|
2019-09-13 15:17:56 +02:00
|
|
|
|
else if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'postgresql' then
|
2020-08-28 18:04:29 +02:00
|
|
|
|
lCustomers := TMVCActiveRecord.Select<TCustomer>
|
|
|
|
|
('SELECT * FROM customers WHERE description ILIKE ''%google%''', [])
|
2019-09-13 15:17:56 +02:00
|
|
|
|
else if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'sqlite' then
|
2020-08-28 18:04:29 +02:00
|
|
|
|
lCustomers := TMVCActiveRecord.Select<TCustomer>
|
|
|
|
|
('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
|
2020-01-08 15:30:10 +01:00
|
|
|
|
else if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'interbase' then
|
2020-08-28 18:04:29 +02:00
|
|
|
|
lCustomers := TMVCActiveRecord.Select<TCustomer>
|
|
|
|
|
('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
|
2020-04-18 15:04:27 +02:00
|
|
|
|
else if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'mssql' then
|
2020-08-28 18:04:29 +02:00
|
|
|
|
lCustomers := TMVCActiveRecord.Select<TCustomer>
|
|
|
|
|
('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
|
2019-05-19 20:23:45 +02:00
|
|
|
|
else
|
2020-08-28 18:04:29 +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-06-25 22:54:57 +02:00
|
|
|
|
Log(Format('%4d - %8.5s - %s', [lCustomer.ID.ValueOrDefault, lCustomer.Code.ValueOrDefault,
|
|
|
|
|
lCustomer.CompanyName.ValueOrDefault]));
|
2018-10-23 16:18:34 +02:00
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
lCustomers.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-06-25 22:54:57 +02:00
|
|
|
|
LoadCustomers;
|
|
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
|
Log('** Query SQL returning DataSet');
|
2023-01-06 15:00:54 +01:00
|
|
|
|
lDS := TMVCActiveRecord.SelectDataSet('SELECT * FROM customers', [], True);
|
2018-10-23 16:18:34 +02:00
|
|
|
|
try
|
|
|
|
|
while not lDS.Eof do
|
|
|
|
|
begin
|
2020-08-28 18:04:29 +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;
|
|
|
|
|
|
2020-03-23 18:51:57 +01:00
|
|
|
|
lDS := TMVCActiveRecord.SelectDataSet
|
2020-08-28 18:04:29 +02:00
|
|
|
|
('SELECT * FROM orders o join customers c on c.id = o.id_customer where o.order_date >= ?',
|
|
|
|
|
[Date - 5000], [ftDate]);
|
2020-03-23 18:51:57 +01:00
|
|
|
|
try
|
|
|
|
|
while not lDS.Eof do
|
|
|
|
|
begin
|
2020-08-28 18:04:29 +02:00
|
|
|
|
Log(Format('OrderDate: %12s - Customer: %s',
|
|
|
|
|
[datetostr(lDS.FieldByName('order_date').AsDateTime), lDS.FieldByName('description')
|
|
|
|
|
.AsString]));
|
2020-03-23 18:51:57 +01:00
|
|
|
|
lDS.Next;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
lDS.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lDS := TMVCActiveRecord.SelectDataSet
|
|
|
|
|
('SELECT * FROM orders o left join customers c on c.id = o.id_customer where o.order_date >= ? and c.id > ?',
|
2020-08-28 18:04:29 +02:00
|
|
|
|
[Date - 5000, 1], [ftDate]);
|
2020-03-23 18:51:57 +01:00
|
|
|
|
try
|
|
|
|
|
while not lDS.Eof do
|
|
|
|
|
begin
|
2020-08-28 18:04:29 +02:00
|
|
|
|
Log(Format('OrderDate: %12s - Customer: %s',
|
|
|
|
|
[datetostr(lDS.FieldByName('order_date').AsDateTime), lDS.FieldByName('description')
|
|
|
|
|
.AsString]));
|
2020-03-23 18:51:57 +01:00
|
|
|
|
lDS.Next;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
lDS.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-02-05 23:46:38 +01:00
|
|
|
|
Log('** GetFirstByWhere');
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetFirstByWhere<TCustomer>('id > ?', [1]);
|
|
|
|
|
try
|
2020-08-28 18:04:29 +02:00
|
|
|
|
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault,
|
|
|
|
|
lCustomer.CompanyName.ValueOrDefault]));
|
2020-02-05 23:46:38 +01:00
|
|
|
|
lID := lCustomer.ID;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-03-23 18:51:57 +01:00
|
|
|
|
lCustomer := TMVCActiveRecord.GetFirstByWhere<TCustomer>('id > ?', [1], [ftInteger]);
|
|
|
|
|
try
|
2020-08-28 18:04:29 +02:00
|
|
|
|
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault,
|
|
|
|
|
lCustomer.CompanyName.ValueOrDefault]));
|
2020-03-23 18:51:57 +01:00
|
|
|
|
lID := lCustomer.ID;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-02-05 23:46:38 +01:00
|
|
|
|
Log('** GetOneByWhere');
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetOneByWhere<TCustomer>('id = ?', [lID.Value]);
|
|
|
|
|
try
|
2020-08-28 18:04:29 +02:00
|
|
|
|
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault,
|
|
|
|
|
lCustomer.CompanyName.ValueOrDefault]));
|
2020-02-05 23:46:38 +01:00
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-03-23 18:51:57 +01:00
|
|
|
|
lCustomer := TMVCActiveRecord.GetOneByWhere<TCustomer>('id = ?', [lID.Value], [ftInteger]);
|
|
|
|
|
try
|
2020-08-28 18:04:29 +02:00
|
|
|
|
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault,
|
|
|
|
|
lCustomer.CompanyName.ValueOrDefault]));
|
2020-03-23 18:51:57 +01:00
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
|
end;
|
|
|
|
|
|
2022-11-17 19:33:27 +01:00
|
|
|
|
procedure TMainForm.btnSpeedClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
I: Integer;
|
|
|
|
|
lCustomers: TArray<TCustomer>;
|
|
|
|
|
lSW: TStopWatch;
|
2022-11-20 00:51:57 +01:00
|
|
|
|
lElapsedMS: UInt32;
|
|
|
|
|
const
|
|
|
|
|
INSTANCES_COUNT = 2000000;
|
2022-11-17 19:33:27 +01:00
|
|
|
|
begin
|
|
|
|
|
TMVCActiveRecord.DeleteAll(TCustomer);
|
2022-11-20 00:51:57 +01:00
|
|
|
|
SetLength(lCustomers, INSTANCES_COUNT);
|
2022-11-17 19:33:27 +01:00
|
|
|
|
lSW := TStopwatch.StartNew;
|
2022-11-20 00:51:57 +01:00
|
|
|
|
for I := 0 to INSTANCES_COUNT - 1 do
|
2022-11-17 19:33:27 +01:00
|
|
|
|
begin
|
|
|
|
|
lCustomers[I] := TCustomer.Create;
|
|
|
|
|
end;
|
2022-11-20 00:51:57 +01:00
|
|
|
|
lElapsedMS := lSW.ElapsedMilliseconds;
|
|
|
|
|
Log(Format('Created %s TCustomer instances in %d ms',
|
|
|
|
|
[FormatFloat('###,###,###', INSTANCES_COUNT), lElapsedMS]));
|
|
|
|
|
for I := 0 to INSTANCES_COUNT - 1 do
|
2022-11-17 19:33:27 +01:00
|
|
|
|
begin
|
|
|
|
|
lCustomers[I].Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2021-11-17 15:36:20 +01:00
|
|
|
|
procedure TMainForm.btnTableFilterClick(Sender: TObject);
|
2022-03-31 09:31:11 +02:00
|
|
|
|
var
|
|
|
|
|
i: Integer;
|
|
|
|
|
lIDOfABadCustomer: Int64;
|
|
|
|
|
lIDOfAGoodCustomer: Int64;
|
|
|
|
|
lHowMany: Int64;
|
|
|
|
|
lCust: TMVCActiveRecord;
|
|
|
|
|
Customer: TCustomer;
|
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
|
lCustomer1: TCustomer;
|
|
|
|
|
lNotAGoodCustomer: TCustomer;
|
|
|
|
|
lThisShouldBeNil: TCustomer;
|
|
|
|
|
lAGoodCustomer: TCustomer;
|
|
|
|
|
lThisShouldNotBeNil: TCustomer;
|
|
|
|
|
lGoodCustomers: TObjectList<TGoodCustomer>;
|
|
|
|
|
lGoodCustomers2: TMVCActiveRecordList;
|
2021-11-17 15:36:20 +01:00
|
|
|
|
begin
|
|
|
|
|
Log('**Table Filtering');
|
|
|
|
|
Log('Deleting only best customers...');
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lIDOfABadCustomer := -1;
|
|
|
|
|
lIDOfAGoodCustomer := -1;
|
2021-11-17 15:36:20 +01:00
|
|
|
|
TMVCActiveRecord.DeleteAll(TGoodCustomer);
|
|
|
|
|
Log('Inserting some customers');
|
2022-03-31 09:31:11 +02:00
|
|
|
|
for i := 1 to 5 do
|
2021-11-17 15:36:20 +01:00
|
|
|
|
begin
|
2022-03-31 09:31:11 +02:00
|
|
|
|
Customer := TCustomer.Create();
|
2021-11-17 15:36:20 +01:00
|
|
|
|
try
|
|
|
|
|
Customer.Code := I.ToString;
|
|
|
|
|
Customer.Rating := I;
|
|
|
|
|
Customer.Store;
|
|
|
|
|
if i = 1 then
|
|
|
|
|
begin
|
|
|
|
|
lIDOfABadCustomer := Customer.ID.Value;
|
|
|
|
|
end;
|
|
|
|
|
if i = 5 then
|
|
|
|
|
begin
|
|
|
|
|
lIDOfAGoodCustomer := Customer.ID.Value;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
Customer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('Retrieving only best customers...');
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lGoodCustomers := TMVCActiveRecord.SelectRQL<TGoodCustomer>('sort(+rating)',10);
|
2021-11-17 15:36:20 +01:00
|
|
|
|
try
|
|
|
|
|
Assert(lGoodCustomers.Count = 2); { only rating >= 4}
|
2022-03-31 09:31:11 +02:00
|
|
|
|
for lCust in lGoodCustomers do
|
2021-11-17 15:36:20 +01:00
|
|
|
|
begin
|
|
|
|
|
Log(lCust.ToString);
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
lGoodCustomers.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('How many "best customers" we have?');
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lHowMany := TMVCActiveRecord.Count<TGoodCustomer>;
|
2021-11-17 15:36:20 +01:00
|
|
|
|
Log(Format('We have %d best customers', [lHowMany]));
|
|
|
|
|
|
|
|
|
|
Log('How many "best customers" with rating = 5 we have?');
|
|
|
|
|
lHowMany := TMVCActiveRecord.Count<TGoodCustomer>('eq(rating,5)');
|
|
|
|
|
Log(Format('We have %d best customers with rating = 5', [lHowMany]));
|
|
|
|
|
|
|
|
|
|
Log('Retrieving only best customers...');
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lGoodCustomers2 := TMVCActiveRecord.SelectRQL(TGoodCustomer, '', -1);
|
2021-11-17 15:36:20 +01:00
|
|
|
|
try
|
|
|
|
|
Assert(lGoodCustomers2.Count = 2); { only rating >= 4}
|
2022-03-31 09:31:11 +02:00
|
|
|
|
for lCust in lGoodCustomers2 do
|
2021-11-17 15:36:20 +01:00
|
|
|
|
begin
|
|
|
|
|
Log(lCust.ToString);
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
lGoodCustomers2.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2021-11-18 17:52:06 +01:00
|
|
|
|
Log('Retrieving only best customers ordered by company name...');
|
|
|
|
|
lGoodCustomers := TMVCActiveRecord.SelectRQL<TGoodCustomer>('sort(+CompanyName)',10);
|
|
|
|
|
try
|
|
|
|
|
Assert(lGoodCustomers.Count = 2); { only rating >= 4}
|
2022-03-31 09:31:11 +02:00
|
|
|
|
for lCust in lGoodCustomers do
|
2021-11-18 17:52:06 +01:00
|
|
|
|
begin
|
|
|
|
|
Log(lCust.ToString);
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
lGoodCustomers.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
2022-11-10 18:30:11 +01:00
|
|
|
|
Log('Retrieving only worst customers...');
|
2021-11-17 15:36:20 +01:00
|
|
|
|
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lNotAGoodCustomer := TMVCActiveRecord.SelectOneByRQL<TCustomer>('eq(rating,1)', True);
|
2021-11-17 15:36:20 +01:00
|
|
|
|
try
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lThisShouldBeNil := TMVCActiveRecord.GetByPK<TGoodCustomer>(lNotAGoodCustomer.ID, False);
|
2021-11-17 15:36:20 +01:00
|
|
|
|
Assert(lThisShouldBeNil = nil);
|
|
|
|
|
finally
|
|
|
|
|
lNotAGoodCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lAGoodCustomer := TMVCActiveRecord.SelectOneByRQL<TCustomer>('eq(rating,5)', True);
|
2021-11-17 15:36:20 +01:00
|
|
|
|
try
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lThisShouldNotBeNil := TMVCActiveRecord.GetByPK<TGoodCustomer>(lAGoodCustomer.ID, False);
|
2021-11-17 15:36:20 +01:00
|
|
|
|
try
|
|
|
|
|
Assert(lThisShouldNotBeNil <> nil);
|
|
|
|
|
Log(lThisShouldNotBeNil.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lThisShouldNotBeNil.Free;
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
lAGoodCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('Promoting a customer...');
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lCustomer := TBadCustomer.Create;
|
2021-11-17 15:36:20 +01:00
|
|
|
|
try
|
|
|
|
|
lCustomer.LoadByPK(lIDOfABadCustomer);
|
|
|
|
|
lCustomer.Rating := 5;
|
|
|
|
|
lCustomer.Store;
|
|
|
|
|
Assert(not lCustomer.LoadByPK(lIDOfABadCustomer)); {this customer is not "bad" anymore}
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
Log('Demote a customer...');
|
2022-03-31 09:31:11 +02:00
|
|
|
|
lCustomer1 := TGoodCustomer.Create;
|
2021-11-17 15:36:20 +01:00
|
|
|
|
try
|
|
|
|
|
lCustomer1.LoadByPK(lIDOfAGoodCustomer);
|
|
|
|
|
lCustomer1.Rating := 1;
|
|
|
|
|
lCustomer1.Store;
|
|
|
|
|
Assert(not lCustomer1.LoadByPK(lIDOfAGoodCustomer)); {this customer is not "good" anymore}
|
|
|
|
|
finally
|
|
|
|
|
lCustomer1.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2022-11-15 09:27:08 +01:00
|
|
|
|
procedure TMainForm.btnReadOnlyFieldsClick(Sender: TObject);
|
2019-02-21 20:17:11 +01:00
|
|
|
|
var
|
2022-11-15 09:27:08 +01:00
|
|
|
|
lCustomer: TCustomerWithReadOnlyFields;
|
2019-02-21 20:17:11 +01:00
|
|
|
|
lID: Integer;
|
|
|
|
|
begin
|
2022-11-15 09:27:08 +01:00
|
|
|
|
Log('** CRUD test with read-only fields');
|
|
|
|
|
lCustomer := TCustomerWithReadOnlyFields.Create;
|
2019-02-21 20:17:11 +01:00
|
|
|
|
try
|
|
|
|
|
{
|
2022-11-15 09:27:08 +01:00
|
|
|
|
'Code' will not be persisted on table because defined as 'foReadOnly'
|
2019-02-21 20:17:11 +01:00
|
|
|
|
}
|
|
|
|
|
lCustomer.Code := '1234';
|
|
|
|
|
lCustomer.CompanyName := 'Google Inc.';
|
|
|
|
|
lCustomer.City := 'Montain View, CA';
|
|
|
|
|
lCustomer.Insert;
|
|
|
|
|
lID := lCustomer.ID;
|
2022-11-15 09:27:08 +01:00
|
|
|
|
Log('Just inserted Customer ' + lID.ToString + ' with a R/O field');
|
2019-02-21 20:17:11 +01:00
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2022-11-15 09:27:08 +01:00
|
|
|
|
//let's check that code is empty
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithReadOnlyFields>(lID);
|
2019-02-21 20:17:11 +01:00
|
|
|
|
try
|
2022-11-15 09:27:08 +01:00
|
|
|
|
Assert(lCustomer.Code.IsEmpty);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
//if underlying field is not null, it is loaded as usual
|
|
|
|
|
TMVCActiveRecord.CurrentConnection.ExecSQL('update customers set code = ''XYZ'' where id = ?', [lID]);
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithReadOnlyFields>(lID);
|
|
|
|
|
try
|
|
|
|
|
Assert('XYZ' = lCustomer.Code);
|
2019-02-21 20:17:11 +01:00
|
|
|
|
lCustomer.CompanyName := lCustomer.CompanyName + ' changed!';
|
|
|
|
|
lCustomer.Code := 'this code will not be saved';
|
2022-11-15 09:27:08 +01:00
|
|
|
|
lCustomer.Update; //do not save field "code"
|
2019-02-21 20:17:11 +01:00
|
|
|
|
Log('Just updated Customer ' + lID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2022-11-15 09:27:08 +01:00
|
|
|
|
//but being foReadOnly is not updated
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithReadOnlyFields>(lID);
|
2019-02-21 20:17:11 +01:00
|
|
|
|
try
|
2022-11-15 09:27:08 +01:00
|
|
|
|
Assert('XYZ' = lCustomer.Code);
|
2019-02-21 20:17:11 +01:00
|
|
|
|
lCustomer.Delete;
|
2022-11-15 09:27:08 +01:00
|
|
|
|
Log('Just deleted Customer ' + lID.ToString + ' with a R/O field');
|
2019-02-21 20:17:11 +01:00
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2023-01-29 17:29:24 +01:00
|
|
|
|
procedure TMainForm.btnRefreshClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
|
lID: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Log('** Refresh test');
|
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
try
|
|
|
|
|
Log('Entity ' + TCustomer.ClassName + ' is mapped to table ' + lCustomer.TableName);
|
|
|
|
|
lCustomer.CompanyName := 'Google Inc.';
|
|
|
|
|
lCustomer.City := 'Montain View, CA';
|
|
|
|
|
lCustomer.Note := 'Μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος οὐλομένην 😁';
|
|
|
|
|
lCustomer.Insert;
|
|
|
|
|
Assert('Montain View, CA' = lCustomer.City);
|
|
|
|
|
Assert('Μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος οὐλομένην 😁' = lCustomer.Note);
|
|
|
|
|
lCustomer.City := '';
|
|
|
|
|
lCustomer.Note := '';
|
|
|
|
|
Log('Refreshing the customer');
|
|
|
|
|
lCustomer.Refresh;
|
|
|
|
|
Assert('Montain View, CA' = lCustomer.City);
|
|
|
|
|
Assert('Μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος οὐλομένην 😁' = lCustomer.Note);
|
|
|
|
|
lID := lCustomer.ID;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
try
|
|
|
|
|
Log('Loading customer using Refresh');
|
|
|
|
|
lCustomer.ID := lID;
|
|
|
|
|
lCustomer.Refresh;
|
|
|
|
|
Assert('Montain View, CA' = lCustomer.City);
|
|
|
|
|
Assert('Μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος οὐλομένην 😁' = lCustomer.Note);
|
|
|
|
|
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)');
|
2023-07-07 20:26:49 +02:00
|
|
|
|
|
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;
|
|
|
|
|
|
2023-07-07 20:26:49 +02:00
|
|
|
|
ShowMessage('Try to update a customer with empty "CODE" (an exception will be raised)');
|
|
|
|
|
|
2019-08-02 12:32:23 +02:00
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithLogic>(lID);
|
2018-10-23 16:18:34 +02:00
|
|
|
|
try
|
2020-08-28 18:04:29 +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-04-08 18:04:45 +02:00
|
|
|
|
procedure TMainForm.btnWithSpacesClick(Sender: TObject);
|
|
|
|
|
var
|
|
|
|
|
lCustomer: TCustomerWithSpaces;
|
|
|
|
|
lID: Integer;
|
|
|
|
|
I: Integer;
|
2021-04-07 19:41:02 +02:00
|
|
|
|
cRQL1: string;
|
|
|
|
|
lList: TMVCActiveRecordList;
|
|
|
|
|
lItem: TMVCActiveRecord;
|
2020-04-08 18:04:45 +02:00
|
|
|
|
begin
|
|
|
|
|
Log('** Simple CRUD (table and fields with spaces) test');
|
|
|
|
|
Log('There are ' + TMVCActiveRecord.Count<TCustomerWithSpaces>().ToString + ' row/s for entity ' +
|
|
|
|
|
TCustomerWithSpaces.ClassName);
|
|
|
|
|
TMVCActiveRecord.DeleteAll(TCustomerWithSpaces);
|
|
|
|
|
Log('Deleting all entities ' + TCustomerWithSpaces.ClassName);
|
|
|
|
|
for I := 1 to 100 do
|
|
|
|
|
begin
|
|
|
|
|
lCustomer := TCustomerWithSpaces.Create;
|
|
|
|
|
try
|
2021-04-07 19:41:02 +02:00
|
|
|
|
lID := I;
|
|
|
|
|
lCustomer.ID := lID;
|
2020-04-08 18:04:45 +02:00
|
|
|
|
// just for test!!
|
|
|
|
|
case I mod 3 of
|
|
|
|
|
0:
|
|
|
|
|
lCustomer.CompanyName := 'Google Inc.';
|
|
|
|
|
1:
|
|
|
|
|
lCustomer.CompanyName := 'bit Time Professionals';
|
|
|
|
|
2:
|
|
|
|
|
lCustomer.CompanyName := 'Walt Disney Corp.';
|
|
|
|
|
end;
|
|
|
|
|
lCustomer.City := 'Montain View, CA';
|
|
|
|
|
lCustomer.Note := 'Hello there!';
|
|
|
|
|
lCustomer.Insert;
|
|
|
|
|
Log('Just inserted Customer ' + lID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2020-08-28 18:04:29 +02:00
|
|
|
|
Log('Now there are ' + TMVCActiveRecord.Count<TCustomerWithSpaces>().ToString +
|
|
|
|
|
' row/s for entity ' + TCustomerWithSpaces.ClassName);
|
2021-04-07 19:41:02 +02:00
|
|
|
|
Log('Deleting using RQL...');
|
|
|
|
|
TMVCActiveRecord.DeleteRQL(TCustomerWithSpaces, 'lt(id,80)');
|
|
|
|
|
Log('Now there are ' + TMVCActiveRecord.Count<TCustomerWithSpaces>().ToString +
|
|
|
|
|
' row/s for entity ' + TCustomerWithSpaces.ClassName);
|
2020-04-08 18:04:45 +02:00
|
|
|
|
|
2021-04-25 22:40:06 +02:00
|
|
|
|
// gets the last inserted customer
|
2020-04-08 18:04:45 +02:00
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithSpaces>(lID);
|
|
|
|
|
try
|
|
|
|
|
Assert(not lCustomer.Code.HasValue);
|
|
|
|
|
lCustomer.Code.Value := '5678';
|
|
|
|
|
lCustomer.Note := lCustomer.Note + sLineBreak + 'Code changed to 5678';
|
|
|
|
|
lCustomer.Update;
|
|
|
|
|
Log('Just updated Customer ' + lID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustomer := TCustomerWithSpaces.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustomer.LoadByPK(lID);
|
|
|
|
|
lCustomer.Code.Value := '9012';
|
|
|
|
|
lCustomer.Update;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithSpaces>(lID);
|
|
|
|
|
try
|
|
|
|
|
lCustomer.Delete;
|
|
|
|
|
Log('Just deleted Customer ' + lID.ToString);
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
2021-04-07 19:41:02 +02:00
|
|
|
|
|
|
|
|
|
cRQL1 := 'eq(CompanyName,"Google Inc.")';
|
|
|
|
|
Log('>> RQL Query (customers with spaces) - ' + cRQL1);
|
|
|
|
|
lList := TMVCActiveRecord.SelectRQL(TCustomerWithSpaces, cRQL1, 20);
|
|
|
|
|
try
|
|
|
|
|
Log(lList.Count.ToString + ' record/s found');
|
|
|
|
|
for lItem in lList do
|
|
|
|
|
begin
|
|
|
|
|
lCustomer := TCustomerWithSpaces(lItem);
|
|
|
|
|
Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault,
|
|
|
|
|
lCustomer.CompanyName.ValueOrDefault, lCustomer.City]));
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
lList.Free;
|
|
|
|
|
end;
|
2020-04-08 18:04:45 +02:00
|
|
|
|
end;
|
|
|
|
|
|
2022-11-10 18:30:11 +01:00
|
|
|
|
procedure TMainForm.btnOOPClick(Sender: TObject);
|
|
|
|
|
begin
|
|
|
|
|
Log('** OOP with ActiveRecord (person, employee, manager)');
|
|
|
|
|
TMVCActiveRecord.DeleteAll(TPerson);
|
|
|
|
|
|
2023-07-07 20:26:49 +02:00
|
|
|
|
var lPerson := TPerson.Create;
|
|
|
|
|
try
|
|
|
|
|
lPerson.FirstName := 'Reed';
|
|
|
|
|
lPerson.LastName := 'Richards';
|
|
|
|
|
lPerson.Dob := EncodeDate(1985,11,4);
|
|
|
|
|
lPerson.IsMale := True;
|
|
|
|
|
lPerson.Store;
|
|
|
|
|
finally
|
|
|
|
|
lPerson.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2022-11-10 18:30:11 +01:00
|
|
|
|
var lEmployee := TEmployee.Create;
|
|
|
|
|
try
|
|
|
|
|
lEmployee.FirstName := 'Peter';
|
|
|
|
|
lEmployee.LastName := 'Parker';
|
|
|
|
|
lEmployee.Dob := EncodeDate(1985,11,4);
|
|
|
|
|
lEmployee.IsMale := True;
|
|
|
|
|
lEmployee.Salary := 2100;
|
|
|
|
|
lEmployee.Store;
|
|
|
|
|
finally
|
|
|
|
|
lEmployee.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2023-07-07 20:26:49 +02:00
|
|
|
|
lEmployee := TEmployee.Create;
|
|
|
|
|
try
|
|
|
|
|
lEmployee.FirstName := 'Sue';
|
|
|
|
|
lEmployee.LastName := 'Storm';
|
|
|
|
|
lEmployee.Dob := EncodeDate(1975,10,14);
|
|
|
|
|
lEmployee.IsMale := False;
|
|
|
|
|
lEmployee.Salary := 2200;
|
|
|
|
|
lEmployee.Store;
|
|
|
|
|
finally
|
|
|
|
|
lEmployee.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
2022-11-10 18:30:11 +01:00
|
|
|
|
var lManager := TManager.Create;
|
|
|
|
|
try
|
|
|
|
|
lManager.FirstName := 'Bruce';
|
|
|
|
|
lManager.LastName := 'Banner';
|
|
|
|
|
lManager.Dob := EncodeDate(1975,11,4);
|
|
|
|
|
lManager.IsMale := True;
|
|
|
|
|
lManager.Salary := 2800;
|
|
|
|
|
lManager.AnnualBonus := 5000;
|
|
|
|
|
lManager.Store;
|
|
|
|
|
finally
|
|
|
|
|
lManager.Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
var lPeople := TMVCActiveRecord.All<TPerson>;
|
|
|
|
|
try
|
2023-07-07 20:26:49 +02:00
|
|
|
|
Assert(lPeople.Count = 4);
|
2022-11-10 18:30:11 +01:00
|
|
|
|
finally
|
|
|
|
|
lPeople.Free;
|
|
|
|
|
end;
|
2023-07-07 20:26:49 +02:00
|
|
|
|
|
|
|
|
|
var lEmployees := TMVCActiveRecord.All<TEmployee>;
|
|
|
|
|
try
|
|
|
|
|
Assert(lEmployees.Count = 3);
|
|
|
|
|
finally
|
|
|
|
|
lEmployees.Free;
|
|
|
|
|
end;
|
2022-11-10 18:30:11 +01:00
|
|
|
|
end;
|
|
|
|
|
|
2019-09-13 15:17:56 +02:00
|
|
|
|
procedure TMainForm.FormDestroy(Sender: TObject);
|
2018-10-23 16:18:34 +02:00
|
|
|
|
begin
|
2021-08-13 18:05:48 +02:00
|
|
|
|
ActiveRecordConnectionsRegistry.RemoveDefaultConnection(False);
|
2018-10-23 16:18:34 +02:00
|
|
|
|
end;
|
|
|
|
|
|
2019-09-13 15:17:56 +02:00
|
|
|
|
procedure TMainForm.FormShow(Sender: TObject);
|
2021-08-13 18:05:48 +02:00
|
|
|
|
var
|
|
|
|
|
lEngine: TRDBMSEngine;
|
2019-01-08 12:48:27 +01:00
|
|
|
|
begin
|
2021-08-13 18:05:48 +02:00
|
|
|
|
if not TEngineChoiceForm.Execute(lEngine) then
|
|
|
|
|
begin
|
|
|
|
|
Close;
|
|
|
|
|
Exit;
|
|
|
|
|
end;
|
|
|
|
|
case lEngine of
|
2019-09-13 15:17:56 +02:00
|
|
|
|
TRDBMSEngine.PostgreSQL:
|
|
|
|
|
begin
|
|
|
|
|
FDConnectionConfigU.CreatePostgresqlPrivateConnDef(True);
|
|
|
|
|
end;
|
|
|
|
|
TRDBMSEngine.Firebird:
|
|
|
|
|
begin
|
|
|
|
|
FDConnectionConfigU.CreateFirebirdPrivateConnDef(True);
|
|
|
|
|
end;
|
|
|
|
|
TRDBMSEngine.Interbase:
|
|
|
|
|
begin
|
2020-01-08 15:30:10 +01:00
|
|
|
|
FDConnectionConfigU.CreateInterbasePrivateConnDef(True);
|
2019-09-13 15:17:56 +02:00
|
|
|
|
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
|
2020-04-18 15:04:27 +02:00
|
|
|
|
FDConnectionConfigU.CreateMSSQLServerPrivateConnDef(True);
|
2019-09-13 15:17:56 +02:00
|
|
|
|
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 + ')';
|
2020-01-08 15:30:10 +01:00
|
|
|
|
{$IFDEF USE_SEQUENCES}
|
|
|
|
|
Caption := Caption + ' USE_SEQUENCES';
|
|
|
|
|
{$ELSE}
|
|
|
|
|
Caption := Caption + ' WITHOUT SEQUENCES';
|
|
|
|
|
{$ENDIF}
|
2021-04-25 22:40:06 +02:00
|
|
|
|
btnWithSpaces.Enabled := (ActiveRecordConnectionsRegistry.GetCurrentBackend = 'postgresql') or
|
2021-04-07 19:41:02 +02:00
|
|
|
|
(ActiveRecordConnectionsRegistry.GetCurrentBackend = 'firebird') or
|
|
|
|
|
(ActiveRecordConnectionsRegistry.GetCurrentBackend = 'interbase') or
|
2021-04-05 19:35:46 +02:00
|
|
|
|
(ActiveRecordConnectionsRegistry.GetCurrentBackend = 'sqlite');
|
|
|
|
|
|
2021-03-20 00:30:20 +01:00
|
|
|
|
btnJSON_XML_Types.Enabled := ActiveRecordConnectionsRegistry.GetCurrentBackend = 'postgresql';
|
2019-01-08 12:48:27 +01:00
|
|
|
|
end;
|
|
|
|
|
|
2020-06-25 22:54:57 +02:00
|
|
|
|
procedure TMainForm.LoadCustomers;
|
|
|
|
|
var
|
|
|
|
|
lCustomer: TCustomer;
|
|
|
|
|
I: Integer;
|
|
|
|
|
begin
|
|
|
|
|
TMVCActiveRecord.DeleteAll(TCustomer);
|
|
|
|
|
for I := 1 to 50 do
|
|
|
|
|
begin
|
|
|
|
|
lCustomer := TCustomer.Create;
|
|
|
|
|
try
|
|
|
|
|
lCustomer.CompanyName := Stuff[Random(4)] + ' ' + CompanySuffix[Random(5)];
|
|
|
|
|
lCustomer.Code := Random(100).ToString.PadLeft(5, '0');
|
|
|
|
|
lCustomer.City := Cities[Random(4)];
|
|
|
|
|
lCustomer.Rating := Random(5);
|
|
|
|
|
lCustomer.Note := Stuff[Random(4)];
|
|
|
|
|
lCustomer.Insert;
|
|
|
|
|
finally
|
|
|
|
|
lCustomer.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2019-01-08 12:48:27 +01:00
|
|
|
|
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;
|
|
|
|
|
|
2021-04-25 22:40:06 +02:00
|
|
|
|
|
2018-10-23 16:18:34 +02:00
|
|
|
|
end.
|