Added dynamic properties accessors to TMVCActiveRecord descendants.

This commit is contained in:
Daniele Teti 2020-08-28 18:04:29 +02:00
parent 2049095872
commit a258bae533
5 changed files with 465 additions and 183 deletions

View File

@ -392,9 +392,9 @@ Congratulations to Daniele Teti and all the staff for the excellent work!" -- Ma
- Fixed! [issue388](https://github.com/danieleteti/delphimvcframework/issues/388)
- Fixed! Has been patched a serious security bug affecting deployment configurations which uses internal WebServer to serve static files (do not affect all Apache, IIS or proxied deployments). Thanks to **Stephan Munz** to have discovered it. *Update to dmvcframework-3.2-RC5+ is required for all such kind of deployments.*
## Changes in upcoming version (3.2.1-carbon)
## 3.2.1-carbon ("repo" version currently in beta)
### Bug Fixes and Improvements
### Improvements and Bug Fixes
- [docExpansion parameter for Swagger](https://github.com/danieleteti/delphimvcframework/issues/408)
@ -415,6 +415,8 @@ Congratulations to Daniele Teti and all the staff for the excellent work!" -- Ma
- New React demo (Thanks to [Angelo Sobreira da Silva](https://github.com/angelosobreira))
- Serialization support for `TList<Integer>`, `TList<String>`, `TList<Boolean>` and for all `TList<T>` of simple types.
- Added `foReadOnly` and `foWriteOnly` as field options in `MVCTableField` attribute (used by `TMVCActiveRecord`). Currently available field options are:
- *foPrimaryKey* { it's the primary key of the mapped table }
@ -505,6 +507,45 @@ Congratulations to Daniele Teti and all the staff for the excellent work!" -- Ma
- Added property `Context.HostingFrameworkType`. This property is of type `TMVCHostingFrameworkType` and can assume one of the following values: `hftIndy` (if the service is using the built-in Indy HTTP server) , `hftApache` (if the project is compiled as Apache module) or `hftISAPI` (if the project is compiled as ISAPI module).
- Added dynamic properties access to `TMVCActiveRecord` descendants. Indexed property `Attributes` is index using the property name and set/get a `TValue` representing the property value.
```delphi
procedure TMainForm.btnAttributesClick(Sender: TObject);
var
lCustomer: TCustomer;
lID: Integer;
begin
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;
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;
finally
lCustomer.Free;
end;
```
## Roadmap
DelphiMVCFramework roadmap is always updated as-soon-as the features planned are implemented. Check the roadmap [here](roadmap.md).

View File

@ -57,7 +57,6 @@ object MainForm: TMainForm
TabOrder = 2
WantReturns = False
WordWrap = False
ExplicitHeight = 571
end
object btnRelations: TButton
Left = 8
@ -177,6 +176,15 @@ object MainForm: TMainForm
TabOrder = 15
OnClick = btnClientGeneratedPKClick
end
object btnAttributes: TButton
Left = 8
Top = 599
Width = 121
Height = 33
Caption = 'Attributes'
TabOrder = 16
OnClick = btnAttributesClick
end
object FDConnection1: TFDConnection
Left = 176
Top = 56

View File

@ -44,6 +44,7 @@ type
btnCountWithRQL: TButton;
btnReadAndWriteOnly: TButton;
btnClientGeneratedPK: TButton;
btnAttributes: TButton;
procedure btnCRUDClick(Sender: TObject);
procedure btnInheritanceClick(Sender: TObject);
procedure btnMultiThreadingClick(Sender: TObject);
@ -62,6 +63,7 @@ type
procedure btnCountWithRQLClick(Sender: TObject);
procedure btnReadAndWriteOnlyClick(Sender: TObject);
procedure btnClientGeneratedPKClick(Sender: TObject);
procedure btnAttributesClick(Sender: TObject);
private
procedure Log(const Value: string);
procedure LoadCustomers;
@ -76,7 +78,6 @@ implementation
{$R *.dfm}
uses
MVCFramework.ActiveRecord,
EntitiesU,
@ -92,6 +93,48 @@ const
CompanySuffix: array [0 .. 5] of string = ('Corp.', 'Inc.', 'Ltd.', 'Srl', 'SPA', 'doo');
Stuff: array [0 .. 4] of string = ('Burger', 'GAS', 'Motors', 'House', 'Boats');
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;
procedure TMainForm.btnClientGeneratedPKClick(Sender: TObject);
var
lCustomer: TCustomerPlainWithClientPK;
@ -151,7 +194,8 @@ var
lID: Integer;
begin
Log('** Simple CRUD test');
Log('There are ' + TMVCActiveRecord.Count<TCustomer>().ToString + ' row/s for entity ' + TCustomer.ClassName);
Log('There are ' + TMVCActiveRecord.Count<TCustomer>().ToString + ' row/s for entity ' +
TCustomer.ClassName);
lCustomer := TCustomer.Create;
try
Log('Entity ' + TCustomer.ClassName + ' is mapped to table ' + lCustomer.TableName);
@ -299,8 +343,8 @@ begin
end;
end;
Log('Now there are ' + TMVCActiveRecord.Count<TCustomerWithCode>().ToString + ' row/s for entity ' +
TCustomerPlain.ClassName);
Log('Now there are ' + TMVCActiveRecord.Count<TCustomerWithCode>().ToString + ' row/s for entity '
+ TCustomerPlain.ClassName);
TMVCActiveRecord.DeleteRQL(TCustomerWithCode, 'lt(code,"0090")');
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithCode>(lCode);
@ -351,7 +395,8 @@ var
lConnParams: string;
begin
Log('** Multithreading test');
TMVCActiveRecord.DeleteRQL(TCustomer, 'in(City,["Rome","New York","London","Melbourne","Berlin"])');
TMVCActiveRecord.DeleteRQL(TCustomer,
'in(City,["Rome","New York","London","Melbourne","Berlin"])');
lConnParams := FDConnection1.Params.Text;
lProc := procedure
@ -372,7 +417,8 @@ begin
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)],
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;
@ -385,10 +431,10 @@ begin
end;
end;
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)];
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)];
TTask.WaitForAll(lTasks);
ShowMessage('Just inserted ' + TMVCActiveRecord.Count(TCustomer,
@ -401,7 +447,8 @@ var
lID: Integer;
begin
Log('** Nullables Test');
Log('There are ' + TMVCActiveRecord.Count<TCustomer>().ToString + ' row/s for entity ' + TCustomer.ClassName);
Log('There are ' + TMVCActiveRecord.Count<TCustomer>().ToString + ' row/s for entity ' +
TCustomer.ClassName);
lCustomer := TCustomer.Create;
try
lCustomer.CompanyName := 'Google Inc.';
@ -541,7 +588,8 @@ begin
lTest.Free;
end;
Log('There are ' + TMVCActiveRecord.Count<TCustomer>().ToString + ' row/s for entity ' + TCustomer.ClassName);
Log('There are ' + TMVCActiveRecord.Count<TCustomer>().ToString + ' row/s for entity ' +
TCustomer.ClassName);
lCustomer := TCustomer.Create;
try
lCustomer.CompanyName := 'Google Inc.';
@ -709,7 +757,8 @@ begin
try
for lOrderRow in lOrderRows do
begin
Log(Format(' %-20s - %4d - %m', [lOrderRow.Description, lOrderRow.Quantity, lOrder.Total]));
Log(Format(' %-20s - %4d - %m', [lOrderRow.Description, lOrderRow.Quantity,
lOrder.Total]));
end;
Log('');
finally
@ -740,8 +789,8 @@ begin
for lItem in lList do
begin
lCustomer := TCustomer(lItem);
Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault,
lCustomer.City]));
Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault,
lCustomer.CompanyName.ValueOrDefault, lCustomer.City]));
end;
finally
lList.Free;
@ -753,8 +802,8 @@ begin
Log(lCustList.Count.ToString + ' record/s found');
for lCustomer in lCustList do
begin
Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault,
lCustomer.City]));
Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault,
lCustomer.CompanyName.ValueOrDefault, lCustomer.City]));
end;
finally
lCustList.Free;
@ -767,8 +816,8 @@ begin
for lItem in lList do
begin
lCustomer := TCustomer(lItem);
Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault,
lCustomer.City]));
Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault,
lCustomer.CompanyName.ValueOrDefault, lCustomer.City]));
end;
finally
lList.Free;
@ -787,20 +836,26 @@ begin
// Bypassing the RQL parser you can use DBMS-specific features or just joining your tables.
// This is just a sample, you can do the "select" also using the RQL engine
if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'firebird' then
lCustomers := TMVCActiveRecord.Select<TCustomer>('SELECT * FROM customers WHERE description CONTAINING ?',
['google'])
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%''', [])
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%''', [])
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%''', [])
lCustomers := TMVCActiveRecord.Select<TCustomer>
('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
else if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'interbase' then
lCustomers := TMVCActiveRecord.Select<TCustomer>('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
lCustomers := TMVCActiveRecord.Select<TCustomer>
('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
else if ActiveRecordConnectionsRegistry.GetCurrentBackend = 'mssql' then
lCustomers := TMVCActiveRecord.Select<TCustomer>('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
lCustomers := TMVCActiveRecord.Select<TCustomer>
('SELECT * FROM customers WHERE description LIKE ''%google%''', [])
else
raise Exception.Create('Unsupported backend: ' + ActiveRecordConnectionsRegistry.GetCurrentBackend);
raise Exception.Create('Unsupported backend: ' +
ActiveRecordConnectionsRegistry.GetCurrentBackend);
try
for lCustomer in lCustomers do
@ -819,7 +874,8 @@ begin
try
while not lDS.Eof do
begin
Log(Format('%8.5s - %s', [lDS.FieldByName('code').AsString, lDS.FieldByName('description').AsString]));
Log(Format('%8.5s - %s', [lDS.FieldByName('code').AsString, lDS.FieldByName('description')
.AsString]));
lDS.Next;
end;
finally
@ -827,13 +883,14 @@ begin
end;
lDS := TMVCActiveRecord.SelectDataSet
('SELECT * FROM orders o join customers c on c.id = o.id_customer where o.order_date >= ?', [Date - 5000],
[ftDate]);
('SELECT * FROM orders o join customers c on c.id = o.id_customer where o.order_date >= ?',
[Date - 5000], [ftDate]);
try
while not lDS.Eof do
begin
Log(Format('OrderDate: %12s - Customer: %s', [datetostr(lDS.FieldByName('order_date').AsDateTime),
lDS.FieldByName('description').AsString]));
Log(Format('OrderDate: %12s - Customer: %s',
[datetostr(lDS.FieldByName('order_date').AsDateTime), lDS.FieldByName('description')
.AsString]));
lDS.Next;
end;
finally
@ -842,13 +899,13 @@ begin
lDS := TMVCActiveRecord.SelectDataSet
('SELECT * FROM orders o left join customers c on c.id = o.id_customer where o.order_date >= ? and c.id > ?',
[Date - 5000, 1],
[ftDate]);
[Date - 5000, 1], [ftDate]);
try
while not lDS.Eof do
begin
Log(Format('OrderDate: %12s - Customer: %s', [datetostr(lDS.FieldByName('order_date').AsDateTime),
lDS.FieldByName('description').AsString]));
Log(Format('OrderDate: %12s - Customer: %s',
[datetostr(lDS.FieldByName('order_date').AsDateTime), lDS.FieldByName('description')
.AsString]));
lDS.Next;
end;
finally
@ -858,7 +915,8 @@ begin
Log('** GetFirstByWhere');
lCustomer := TMVCActiveRecord.GetFirstByWhere<TCustomer>('id > ?', [1]);
try
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault]));
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault,
lCustomer.CompanyName.ValueOrDefault]));
lID := lCustomer.ID;
finally
lCustomer.Free;
@ -866,7 +924,8 @@ begin
lCustomer := TMVCActiveRecord.GetFirstByWhere<TCustomer>('id > ?', [1], [ftInteger]);
try
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault]));
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault,
lCustomer.CompanyName.ValueOrDefault]));
lID := lCustomer.ID;
finally
lCustomer.Free;
@ -875,14 +934,16 @@ begin
Log('** GetOneByWhere');
lCustomer := TMVCActiveRecord.GetOneByWhere<TCustomer>('id = ?', [lID.Value]);
try
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault]));
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault,
lCustomer.CompanyName.ValueOrDefault]));
finally
lCustomer.Free;
end;
lCustomer := TMVCActiveRecord.GetOneByWhere<TCustomer>('id = ?', [lID.Value], [ftInteger]);
try
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault]));
Log(Format('%8.5s - %s', [lCustomer.Code.ValueOrDefault,
lCustomer.CompanyName.ValueOrDefault]));
finally
lCustomer.Free;
end;
@ -948,7 +1009,8 @@ begin
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithLogic>(lID);
try
Log(lCustomer.CompanyName + ' => IsLocatedInRome: ' + BoolToStr(lCustomer.IsLocatedInRome, True));
Log(lCustomer.CompanyName + ' => IsLocatedInRome: ' +
BoolToStr(lCustomer.IsLocatedInRome, True));
lCustomer.Code := '';
lCustomer.Update; // raise exception
finally
@ -991,8 +1053,8 @@ begin
end;
end;
Log('Now there are ' + TMVCActiveRecord.Count<TCustomerWithSpaces>().ToString + ' row/s for entity ' +
TCustomerWithSpaces.ClassName);
Log('Now there are ' + TMVCActiveRecord.Count<TCustomerWithSpaces>().ToString +
' row/s for entity ' + TCustomerWithSpaces.ClassName);
TMVCActiveRecord.DeleteRQL(TCustomerWithSpaces, 'lt(id,90)');
lCustomer := TMVCActiveRecord.GetByPK<TCustomerWithSpaces>(lID);

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{F8576ED6-649F-4E28-B364-1F60687C75F2}</ProjectGuid>
<ProjectVersion>18.8</ProjectVersion>
<ProjectVersion>19.0</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>activerecord_showcase.dpr</MainSource>
<Base>True</Base>
@ -163,13 +163,13 @@
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">
<DeployFile LocalName="bin\activerecord_showcase.exe" Configuration="Debug" Class="ProjectOutput">
<DeployFile LocalName="bin\activerecord_showcase.exe" Configuration="BUILD" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>activerecord_showcase.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="bin\activerecord_showcase.exe" Configuration="BUILD" Class="ProjectOutput">
<DeployFile LocalName="bin\activerecord_showcase.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>activerecord_showcase.exe</RemoteName>
<Overwrite>true</Overwrite>
@ -722,6 +722,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -744,6 +754,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_LaunchDark2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1125">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -843,6 +863,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -854,6 +884,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch3x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -898,6 +938,26 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_LaunchDark2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_LaunchDark3x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
@ -945,6 +1005,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSLaunchScreen">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen</RemoteDir>
<Operation>64</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen</RemoteDir>
<Operation>64</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>

View File

@ -58,8 +58,7 @@ type
end;
TMVCActiveRecordClass = class of TMVCActiveRecord;
TMVCActiveRecordFieldOption = (
foPrimaryKey, { it's the primary key of the mapped table }
TMVCActiveRecordFieldOption = (foPrimaryKey, { it's the primary key of the mapped table }
foAutoGenerated, { not written, read - similar to readonly }
foTransient, { not written, not read }
foReadOnly, { not written, read }
@ -157,12 +156,13 @@ type
fEntityAllowedActions: TMVCEntityActions;
fRQL2SQL: TRQL2SQL;
procedure MapTValueToParam(aValue: TValue; const aParam: TFDParam);
function MapNullableTValueToParam(aValue: TValue;
const aParam: TFDParam): Boolean;
function MapNullableTValueToParam(aValue: TValue; const aParam: TFDParam): Boolean;
function GetPrimaryKeyIsAutogenerated: Boolean;
procedure SetPrimaryKeyIsAutogenerated(const Value: Boolean);
function GetPrimaryKeyFieldType: TFieldType;
procedure SetTableName(const Value: string);
function GetAttributes(const AttrName: string): TValue;
procedure SetAttributes(const AttrName: string; const Value: TValue);
protected
fRTTIType: TRttiInstanceType;
fProps: TArray<TRTTIField>;
@ -181,14 +181,9 @@ type
class function ExecQuery(const SQL: string; const Values: array of Variant): TDataSet; overload;
class function ExecQuery(const SQL: string; const Values: array of Variant; const Connection: TFDConnection)
: TDataSet; overload;
class function ExecQuery(
const SQL: string;
const Values: array of Variant;
const ValueTypes: array of TFieldType): TDataSet; overload;
class function ExecQuery(
const SQL: string;
const Values: array of Variant;
const ValueTypes: array of TFieldType;
class function ExecQuery(const SQL: string; const Values: array of Variant; const ValueTypes: array of TFieldType)
: TDataSet; overload;
class function ExecQuery(const SQL: string; const Values: array of Variant; const ValueTypes: array of TFieldType;
const Connection: TFDConnection): TDataSet; overload;
procedure FillPrimaryKey(const SequenceName: string);
function ExecNonQuery(const SQL: string; RefreshAutoGenerated: Boolean = false): int64; overload;
@ -284,10 +279,13 @@ type
function TableInfo: string;
procedure LoadByDataset(const aDataSet: TDataSet; const aOptions: TMVCActiveRecordLoadOptions = []);
procedure SetPK(const aValue: TValue);
procedure SetPropertyValue(const aProp: TRttiProperty; const aValue: TValue);
function GetPK: TValue;
function TryGetPKValue(var Value: TValue; out IsNullableType: Boolean): Boolean;
procedure AddChildren(const ChildObject: TObject);
procedure RemoveChildren(const ChildObject: TObject);
// dynamic access
property Attributes[const AttrName: string]: TValue read GetAttributes write SetAttributes;
[MVCDoNotSerialize]
property TableName: string read fTableName write SetTableName;
[MVCDoNotSerialize]
@ -324,51 +322,34 @@ type
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function GetByPK<T: TMVCActiveRecord, constructor>(const aValue: string;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function Select<T: TMVCActiveRecord, constructor>(const SQL: string;
const Params: array of Variant;
class function Select<T: TMVCActiveRecord, constructor>(const SQL: string; const Params: array of Variant;
const Options: TMVCActiveRecordLoadOptions = []): TObjectList<T>; overload;
class function Select<T: TMVCActiveRecord, constructor>(const SQL: string;
const Params: array of Variant;
const ParamTypes: array of TFieldType;
const Options: TMVCActiveRecordLoadOptions = []): TObjectList<T>; overload;
class function SelectOne<T: TMVCActiveRecord, constructor>(const SQL: string;
const Params: array of Variant;
const ParamTypes: array of TFieldType;
const Options: TMVCActiveRecordLoadOptions = [];
class function Select<T: TMVCActiveRecord, constructor>(const SQL: string; const Params: array of Variant;
const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions = []): TObjectList<T>; overload;
class function SelectOne<T: TMVCActiveRecord, constructor>(const SQL: string; const Params: array of Variant;
const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions = [];
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function SelectOne<T: TMVCActiveRecord, constructor>(const SQL: string;
const Params: array of Variant;
class function SelectOne<T: TMVCActiveRecord, constructor>(const SQL: string; const Params: array of Variant;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function SelectRQL<T: constructor, TMVCActiveRecord>(const RQL: string; const MaxRecordCount: Integer)
: TObjectList<T>; overload;
class function SelectOneByRQL<T: constructor, TMVCActiveRecord>(
const RQL: string;
class function SelectOneByRQL<T: constructor, TMVCActiveRecord>(const RQL: string;
const RaiseExceptionIfNotFound: Boolean): T; overload;
class function All<T: TMVCActiveRecord, constructor>: TObjectList<T>; overload;
class function Count<T: TMVCActiveRecord>(const RQL: string = ''): int64; overload;
class function Where<T: TMVCActiveRecord, constructor>(
const SQLWhere: string;
const Params: array of Variant): TObjectList<T>; overload;
class function Where<T: TMVCActiveRecord, constructor>(
const SQLWhere: string;
const Params: array of Variant;
class function Where<T: TMVCActiveRecord, constructor>(const SQLWhere: string; const Params: array of Variant)
: TObjectList<T>; overload;
class function Where<T: TMVCActiveRecord, constructor>(const SQLWhere: string; const Params: array of Variant;
const ParamTypes: array of TFieldType): TObjectList<T>; overload;
class function GetOneByWhere<T: TMVCActiveRecord, constructor>(
const SQLWhere: string;
const Params: array of Variant;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function GetOneByWhere<T: TMVCActiveRecord, constructor>(const SQLWhere: string;
const Params: array of Variant;
const ParamTypes: array of TFieldType;
const Params: array of Variant; const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function GetOneByWhere<T: TMVCActiveRecord, constructor>(const SQLWhere: string;
const Params: array of Variant; const ParamTypes: array of TFieldType;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function GetFirstByWhere<T: TMVCActiveRecord, constructor>(
const SQLWhere: string;
const Params: array of Variant;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function GetFirstByWhere<T: TMVCActiveRecord, constructor>(
const SQLWhere: string;
const Params: array of Variant;
const ParamTypes: array of TFieldType;
class function GetFirstByWhere<T: TMVCActiveRecord, constructor>(const SQLWhere: string;
const Params: array of Variant; const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function GetFirstByWhere<T: TMVCActiveRecord, constructor>(const SQLWhere: string;
const Params: array of Variant; const ParamTypes: array of TFieldType;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
end;
@ -448,8 +429,7 @@ type
function GetCompiler: TRQLCompiler;
function GetCompilerClass: TRQLCompilerClass; virtual; abstract;
function GetMapping: TMVCFieldsMapping;
function TableFieldsDelimited(const Map: TFieldsMap; const PKFieldName: string;
const Delimiter: string): string;
function TableFieldsDelimited(const Map: TFieldsMap; const PKFieldName: string; const Delimiter: string): string;
public
constructor Create(Mapping: TMVCFieldsMapping); virtual;
destructor Destroy; override;
@ -458,25 +438,21 @@ type
function HasReturning: Boolean; virtual;
// end-capabilities
function CreateSQLWhereByRQL(const RQL: string; const Mapping: TMVCFieldsMapping;
const UseArtificialLimit: Boolean = True;
const UseFilterOnly: Boolean = false
): string; virtual; abstract;
function CreateSelectSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
function CreateSelectByPKSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
virtual; abstract;
function CreateInsertSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
function CreateUpdateSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
function CreateDeleteSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
virtual; abstract;
const UseArtificialLimit: Boolean = True; const UseFilterOnly: Boolean = false): string; virtual; abstract;
function CreateSelectSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
function CreateSelectByPKSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
function CreateInsertSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
function CreateUpdateSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
function CreateDeleteSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
function CreateDeleteAllSQL(const TableName: string): string; virtual; abstract;
function CreateSelectCount(const TableName: string): string; virtual; abstract;
function GetSequenceValueSQL(
const PKFieldName: string; const SequenceName: string; const Step: Integer = 1): string; virtual;
function GetSequenceValueSQL(const PKFieldName: string; const SequenceName: string; const Step: Integer = 1)
: string; virtual;
// Overwritten by descendant if the SQL syntaxt requires more than the simple table name
// or if the table name contains spaces.
@ -523,6 +499,7 @@ uses
MVCFramework.DataSet.Utils,
MVCFramework.Logger,
MVCFramework.Nullables,
MVCFramework.RTTI.Utils,
FireDAC.Stan.Option,
Data.FmtBcd, System.Variants;
@ -633,8 +610,7 @@ begin
end;
end;
procedure TMVCConnectionsRepository.AddDefaultConnection(
const aConnection: TFDConnection; const aOwns: Boolean);
procedure TMVCConnectionsRepository.AddDefaultConnection(const aConnection: TFDConnection; const aOwns: Boolean);
begin
AddConnection('default', aConnection, aOwns);
end;
@ -1068,8 +1044,7 @@ begin
Result := GetScalar(lSQL, []);
end;
function TMVCActiveRecord.InternalSelectRQL(const RQL: string;
const MaxRecordCount: Integer): TMVCActiveRecordList;
function TMVCActiveRecord.InternalSelectRQL(const RQL: string; const MaxRecordCount: Integer): TMVCActiveRecordList;
var
lSQL: string;
begin
@ -1099,6 +1074,17 @@ begin
Result := SQLGenerator.CreateSelectSQL(fTableName, fMap, fPrimaryKeyFieldName, fPrimaryKeyOptions);
end;
function TMVCActiveRecord.GetAttributes(const AttrName: string): TValue;
var
lProperty: TRttiProperty;
begin
if not TRttiUtils.ExistsProperty(Self, AttrName, lProperty) then
begin
raise EMVCActiveRecord.CreateFmt('Attribute [%s] not found', [AttrName]);
end;
Result := lProperty.GetValue(Self);
end;
function TMVCActiveRecord.GetBackEnd: string;
begin
if fBackendDriver.IsEmpty then
@ -1108,8 +1094,7 @@ begin
Result := fBackendDriver;
end;
class function TMVCActiveRecord.GetByPK(const aClass: TMVCActiveRecordClass;
const aValue: string;
class function TMVCActiveRecord.GetByPK(const aClass: TMVCActiveRecordClass; const aValue: string;
const RaiseExceptionIfNotFound: Boolean): TMVCActiveRecord;
begin
Result := aClass.Create;
@ -1171,8 +1156,7 @@ begin
end;
end;
class function TMVCActiveRecordHelper.GetByPK<T>(const aValue: string;
const RaiseExceptionIfNotFound: Boolean): T;
class function TMVCActiveRecordHelper.GetByPK<T>(const aValue: string; const RaiseExceptionIfNotFound: Boolean): T;
var
lActiveRecord: TMVCActiveRecord;
begin
@ -1192,9 +1176,8 @@ begin
end;
end;
class function TMVCActiveRecordHelper.GetFirstByWhere<T>(const SQLWhere: string;
const Params: array of Variant; const ParamTypes: array of TFieldType;
const RaiseExceptionIfNotFound: Boolean): T;
class function TMVCActiveRecordHelper.GetFirstByWhere<T>(const SQLWhere: string; const Params: array of Variant;
const ParamTypes: array of TFieldType; const RaiseExceptionIfNotFound: Boolean): T;
var
lList: TObjectList<T>;
begin
@ -1218,9 +1201,8 @@ begin
Result := GetFirstByWhere<T>(SQLWhere, Params, [], RaiseExceptionIfNotFound);
end;
class function TMVCActiveRecordHelper.GetOneByWhere<T>(const SQLWhere: string;
const Params: array of Variant; const ParamTypes: array of TFieldType;
const RaiseExceptionIfNotFound: Boolean): T;
class function TMVCActiveRecordHelper.GetOneByWhere<T>(const SQLWhere: string; const Params: array of Variant;
const ParamTypes: array of TFieldType; const RaiseExceptionIfNotFound: Boolean): T;
begin
Result := GetFirstByWhere<T>(SQLWhere, Params, ParamTypes, false);
if Result = nil then
@ -1261,9 +1243,7 @@ begin
Result := fMapping;
end;
class function TMVCActiveRecordHelper.GetOneByWhere<T>(
const SQLWhere: string;
const Params: array of Variant;
class function TMVCActiveRecordHelper.GetOneByWhere<T>(const SQLWhere: string; const Params: array of Variant;
const RaiseExceptionIfNotFound: Boolean): T;
begin
Result := GetFirstByWhere<T>(SQLWhere, Params, false);
@ -1274,9 +1254,7 @@ begin
end;
end;
class function TMVCActiveRecordHelper.SelectOneByRQL<T>(
const RQL: string;
const RaiseExceptionIfNotFound: Boolean): T;
class function TMVCActiveRecordHelper.SelectOneByRQL<T>(const RQL: string; const RaiseExceptionIfNotFound: Boolean): T;
var
lAR: TMVCActiveRecord;
lSQL: string;
@ -1414,15 +1392,13 @@ begin
end;
end;
procedure TMVCActiveRecord.MapDatasetToObject(const DataSet: TDataSet;
const Options: TMVCActiveRecordLoadOptions;
procedure TMVCActiveRecord.MapDatasetToObject(const DataSet: TDataSet; const Options: TMVCActiveRecordLoadOptions;
var Handled: Boolean);
begin
// do nothing
end;
procedure TMVCActiveRecord.MapObjectToParams(const Params: TFDParams;
var Handled: Boolean);
procedure TMVCActiveRecord.MapObjectToParams(const Params: TFDParams; var Handled: Boolean);
begin
// do nothing
end;
@ -1704,18 +1680,15 @@ begin
begin
aParam.AsDate := Trunc(aValue.AsExtended);
end
else
if lName = 'TDateTime' then
else if lName = 'TDateTime' then
begin
aParam.AsDateTime := aValue.AsExtended;
end
else
if lName = 'TTime' then
else if lName = 'TTime' then
begin
aParam.AsTime := aValue.AsExtended;
end
else
if lName = 'Currency' then
else if lName = 'Currency' then
begin
aParam.AsCurrency := aValue.AsCurrency;
end
@ -2043,8 +2016,7 @@ begin
end;
class function TMVCActiveRecord.SelectDataSet(const SQL: string;
const Params: array of Variant;
class function TMVCActiveRecord.SelectDataSet(const SQL: string; const Params: array of Variant;
const ParamTypes: array of TFieldType): TDataSet;
begin
Result := TMVCActiveRecord.ExecQuery(SQL, Params, ParamTypes);
@ -2066,10 +2038,8 @@ begin
Result := InternalSelectRQL(RQL, MaxRecordCount);
end;
class function TMVCActiveRecordHelper.Select<T>(const SQL: string;
const Params: array of Variant;
const ParamTypes: array of TFieldType;
const Options: TMVCActiveRecordLoadOptions): TObjectList<T>;
class function TMVCActiveRecordHelper.Select<T>(const SQL: string; const Params: array of Variant;
const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions): TObjectList<T>;
var
lDataSet: TDataSet;
lAR: TMVCActiveRecord;
@ -2095,16 +2065,14 @@ begin
end;
end;
class function TMVCActiveRecordHelper.SelectOne<T>(const SQL: string;
const Params: array of Variant; const RaiseExceptionIfNotFound: Boolean): T;
class function TMVCActiveRecordHelper.SelectOne<T>(const SQL: string; const Params: array of Variant;
const RaiseExceptionIfNotFound: Boolean): T;
begin
Result := SelectOne<T>(SQL, Params, [], [], RaiseExceptionIfNotFound);
end;
class function TMVCActiveRecordHelper.SelectOne<T>(const SQL: string;
const Params: array of Variant;
const ParamTypes: array of TFieldType;
const Options: TMVCActiveRecordLoadOptions;
class function TMVCActiveRecordHelper.SelectOne<T>(const SQL: string; const Params: array of Variant;
const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions;
const RaiseExceptionIfNotFound: Boolean): T;
var
lDataSet: TDataSet;
@ -2149,8 +2117,7 @@ begin
end;
end;
class function TMVCActiveRecordHelper.Where<T>(const SQLWhere: string;
const Params: array of Variant;
class function TMVCActiveRecordHelper.Where<T>(const SQLWhere: string; const Params: array of Variant;
const ParamTypes: array of TFieldType): TObjectList<T>;
var
lAR: TMVCActiveRecord;
@ -2183,15 +2150,160 @@ begin
end;
end;
procedure TMVCActiveRecord.SetAttributes(const AttrName: string; const Value: TValue);
var
lProperty: TRttiProperty;
begin
if not TRttiUtils.ExistsProperty(Self, AttrName, lProperty) then
begin
raise EMVCActiveRecord.CreateFmt('Attribute [%s] not found', [AttrName]);
end;
SetPropertyValue(lProperty, Value);
end;
procedure TMVCActiveRecord.SetPropertyValue(const aProp: TRttiProperty; const aValue: TValue);
var
lCurrValue: TValue;
lNullableString: NullableString;
lNullableUInt32: NullableUInt32;
lNullableUInt64: NullableUInt64;
lNullableInt64: NullableInt64;
lNullableBoolean: NullableBoolean;
lNullableTDateTime: NullableTDateTime;
lNullableTDate: NullableTDate;
lNullableTTime: NullableTTime;
begin
if aProp.GetValue(Self).Kind = tkRecord then
begin
lCurrValue := aProp.GetValue(Self);
if lCurrValue.IsType<NullableInt32> then
begin
if aValue.IsType<NullableInt32>() then
begin
lCurrValue := aValue;
end
else
begin
lCurrValue := TValue.From<NullableInt32>(IntToNullableInt(aValue.AsInteger));
end
end
else if lCurrValue.IsType<NullableInt64> then
begin
if aValue.IsType<NullableInt64>() then
begin
lCurrValue := aValue;
end
else
begin
lNullableInt64 := aValue.AsInt64;
lCurrValue := TValue.From<NullableInt64>(lNullableInt64);
end;
end
else if lCurrValue.IsType<NullableString> then
begin
if aValue.IsType<NullableString>() then
begin
lCurrValue := aValue;
end
else
begin
lNullableString := aValue.AsString;
lCurrValue := TValue.From<NullableString>(lNullableString);
end;
end
else if lCurrValue.IsType<NullableUInt32> then
begin
if aValue.IsType<NullableUInt32>() then
begin
lCurrValue := aValue;
end
else
begin
lNullableUInt32 := aValue.AsInteger;
lCurrValue.From<NullableUInt32>(lNullableUInt32);
end;
end
else if lCurrValue.IsType<NullableUInt64> then
begin
if aValue.IsType<NullableUInt64>() then
begin
lCurrValue := aValue;
end
else
begin
lNullableUInt64 := aValue.AsUInt64;
lCurrValue.From<NullableUInt64>(lNullableUInt64);
end;
end
else if lCurrValue.IsType<NullableBoolean> then
begin
if aValue.IsType<NullableBoolean>() then
begin
lCurrValue := aValue;
end
else
begin
lNullableBoolean := aValue.AsBoolean;
lCurrValue.From<NullableBoolean>(lNullableBoolean);
end;
end
else if lCurrValue.IsType<NullableTDateTime> then
begin
if aValue.IsType<NullableTDateTime>() then
begin
lCurrValue := aValue;
end
else
begin
lNullableTDateTime := TDateTime(aValue.AsExtended);
lCurrValue.From<NullableTDateTime>(lNullableTDateTime);
end;
end
else if lCurrValue.IsType<NullableTDate> then
begin
if aValue.IsType<NullableTDate>() then
begin
lCurrValue := aValue;
end
else
begin
lNullableTDate := TDate(aValue.AsExtended);
lCurrValue.From<NullableTDate>(lNullableTDate);
end;
end
else if lCurrValue.IsType<NullableTTime> then
begin
if aValue.IsType<NullableTTime>() then
begin
lCurrValue := aValue;
end
else
begin
lNullableTTime := TTime(aValue.AsExtended);
lCurrValue.From<NullableTTime>(lNullableTTime);
end;
end
else
begin
raise EMVCActiveRecord.Create('Invalid data type for dynamic property access');
end;
aProp.SetValue(Self, lCurrValue);
end
else
begin
aProp.SetValue(Self, aValue)
end;
end;
procedure TMVCActiveRecord.SetPK(const aValue: TValue);
var
lPKValue: TValue;
begin
if fPrimaryKeyFieldName.IsEmpty then
begin
raise Exception.Create('No primary key defined');
end;
if fPrimaryKey.GetValue(Self).Kind = tkRecord then
begin
lPKValue := fPrimaryKey.GetValue(Self);
@ -2248,7 +2360,8 @@ begin
end
else
begin
raise EMVCActiveRecord.Create('Invalid type for primary key [HINT] Double check if TypeInfo(PK) is equal to TypeInfo(Value)');
raise EMVCActiveRecord.Create
('Invalid type for primary key [HINT] Double check if TypeInfo(PK) is equal to TypeInfo(Value)');
end;
fPrimaryKey.SetValue(Self, lPKValue);
end
@ -2407,8 +2520,7 @@ begin
end;
end;
class
function TMVCActiveRecord.All(const aClass: TMVCActiveRecordClass): TObjectList<TMVCActiveRecord>;
class function TMVCActiveRecord.All(const aClass: TMVCActiveRecordClass): TObjectList<TMVCActiveRecord>;
var
lAR: TMVCActiveRecord;
begin
@ -2420,8 +2532,7 @@ begin
end;
end;
class
function TMVCActiveRecordHelper.All<T>: TObjectList<T>;
class function TMVCActiveRecordHelper.All<T>: TObjectList<T>;
var
lAR: TMVCActiveRecord;
begin
@ -2433,15 +2544,13 @@ begin
end;
end;
class
function TMVCActiveRecord.Where(const aClass: TMVCActiveRecordClass; const SQLWhere: string;
class function TMVCActiveRecord.Where(const aClass: TMVCActiveRecordClass; const SQLWhere: string;
const Params: array of Variant): TMVCActiveRecordList;
begin
Result := Where(aClass, SQLWhere, Params, nil);
end;
class
function TMVCActiveRecord.Where(const aClass: TMVCActiveRecordClass; const SQLWhere: string;
class function TMVCActiveRecord.Where(const aClass: TMVCActiveRecordClass; const SQLWhere: string;
const Params: array of Variant; const Connection: TFDConnection): TMVCActiveRecordList;
var
lAR: TMVCActiveRecord;
@ -2454,8 +2563,7 @@ begin
end;
end;
class
function TMVCActiveRecordHelper.Where<T>(const SQLWhere: string; const Params: array of Variant): TObjectList<T>;
class function TMVCActiveRecordHelper.Where<T>(const SQLWhere: string; const Params: array of Variant): TObjectList<T>;
begin
Result := Where<T>(SQLWhere, Params, []);
end;
@ -2567,8 +2675,7 @@ begin
end;
end;
class
function TMVCSQLGeneratorRegistry.Instance: TMVCSQLGeneratorRegistry;
class function TMVCSQLGeneratorRegistry.Instance: TMVCSQLGeneratorRegistry;
begin
if not Assigned(cInstance) then
begin
@ -2645,8 +2752,8 @@ begin
Result := fRQL2SQL;
end;
function TMVCSQLGenerator.GetSequenceValueSQL(
const PKFieldName: string; const SequenceName: string; const Step: Integer = 1): string;
function TMVCSQLGenerator.GetSequenceValueSQL(const PKFieldName: string; const SequenceName: string;
const Step: Integer = 1): string;
begin
Result := '';
end;
@ -2724,12 +2831,8 @@ begin
fHttpErrorCode := http_status.NotFound;
end;
class
function TMVCActiveRecord.ExecQuery(
const SQL: string;
const Values: array of Variant;
const ValueTypes: array of TFieldType;
const Connection: TFDConnection): TDataSet;
class function TMVCActiveRecord.ExecQuery(const SQL: string; const Values: array of Variant;
const ValueTypes: array of TFieldType; const Connection: TFDConnection): TDataSet;
var
lQry: TFDQuery;
begin
@ -2761,9 +2864,7 @@ begin
end;
end;
class
function TMVCActiveRecord.ExecQuery(const SQL: string;
const Values: array of Variant;
class function TMVCActiveRecord.ExecQuery(const SQL: string; const Values: array of Variant;
const ValueTypes: array of TFieldType): TDataSet;
begin
Result := ExecQuery(SQL, Values, ValueTypes, nil);