mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 07:45:54 +01:00
+ Fixed a bug in RQL' MaxRecordCount
+ Implemented Table Partitioning (WIP)
This commit is contained in:
parent
49518a311b
commit
5550819fca
21
README.md
21
README.md
@ -569,23 +569,40 @@ The current beta release is named 3.2.2-nitrogen. If you want to stay on the-edg
|
||||
end;
|
||||
```
|
||||
|
||||
|
||||
### Bug Fixes in 3.2.2-nitrogen
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/484 (thanks to [João Antônio Duarte](https://github.com/joaoduarte19))
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/472 (thanks to [João Antônio Duarte](https://github.com/joaoduarte19))
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/470 (thanks to [João Antônio Duarte](https://github.com/joaoduarte19))
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/453 (thanks to [João Antônio Duarte](https://github.com/joaoduarte19))
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/455 (thanks to [João Antônio Duarte](https://github.com/joaoduarte19))
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/461
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/489 (thanks to [drcrck](https://github.com/drcrck) for his initial analisys)
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/493 (thanks to [DelphiMan68](https://github.com/DelphiMan68) for his initial analisys)
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/451
|
||||
|
||||
- Fix for nil objects in lists during serialization
|
||||
- Uniformed behavior in `Update` and `Delete` method in `TMVCActiveRecord`. Now these methods raise an exception if the record doesn't exists anymore in the table (update or delete statements return `AffectedRows` = 0). The behavior can be altered using the new parameter in the call, which by default is `true`. WARNING! This change could raise some incompatibilities with the previous version, however this is the correct behavior. Consider the previous one a "incorrect behavior to fix".
|
||||
|
||||
- Fix a very subtle bug in `MaxRecordCount` parameter for RQL based methods in `TMVCActiveRecord`
|
||||
|
||||
- Uniformed behavior in `Update` and `Delete` method in `TMVCActiveRecord`. Now these methods raise an exception if the record doesn't exists anymore in the table (update or delete statements return `AffectedRows` = 0). The behavior can be altered using the new parameter in the call, which by default is `true`.
|
||||
|
||||
> WARNING! This change could raise some incompatibilities with the previous version, however this is the correct behavior. Consider the previous one a "incorrect behavior to fix".
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/489
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/518 (Thanks to [Microcom-Bjarne](https://github.com/Microcom-Bjarne))
|
||||
|
||||
- Fix https://github.com/danieleteti/delphimvcframework/issues/526 (Thanks to [David Moorhouse](https://github.com/fastbike))
|
||||
|
||||
- Fix *fileupload* sample
|
||||
|
||||
## Older Releases
|
||||
|
@ -133,11 +133,47 @@ type
|
||||
property Note: string read fNote write fNote;
|
||||
end;
|
||||
|
||||
[MVCNameCase(ncLowerCase)]
|
||||
[MVCTable('customers')]
|
||||
TPartitionedCustomer = class(TCustomEntity)
|
||||
private
|
||||
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
|
||||
fID: NullableInt64;
|
||||
[MVCTableField('code')]
|
||||
fCode: NullableString;
|
||||
[MVCTableField('description')]
|
||||
fCompanyName: NullableString;
|
||||
[MVCTableField('city')]
|
||||
fCity: string;
|
||||
[MVCTableField('note')]
|
||||
fNote: string;
|
||||
public
|
||||
function ToString: String; override;
|
||||
property ID: NullableInt64 read fID write fID;
|
||||
property Code: NullableString read fCode write fCode;
|
||||
property CompanyName: NullableString read fCompanyName write fCompanyName;
|
||||
property City: string read fCity write fCity;
|
||||
property Note: string read fNote write fNote;
|
||||
end;
|
||||
|
||||
|
||||
[MVCNameCase(ncLowerCase)]
|
||||
[MVCTable('customers', 'ge(Rating,4)')]
|
||||
TGoodCustomer = class(TCustomer)
|
||||
end;
|
||||
|
||||
[MVCTable('customers')]
|
||||
[MVCPartition('rating=(integer)1')]
|
||||
TCustomerWithRate1 = class(TPartitionedCustomer)
|
||||
end;
|
||||
|
||||
|
||||
[MVCTable('customers')]
|
||||
[MVCPartition('rating=(integer)2')]
|
||||
TCustomerWithRate2 = class(TPartitionedCustomer)
|
||||
end;
|
||||
|
||||
|
||||
|
||||
[MVCNameCase(ncLowerCase)]
|
||||
[MVCTable('customers', 'le(Rating,3)')]
|
||||
@ -570,4 +606,15 @@ begin
|
||||
'').Replace('}', '').Substring(0, 20)));
|
||||
end;
|
||||
|
||||
{ TPartitionedCustomer }
|
||||
|
||||
function TPartitionedCustomer.ToString: String;
|
||||
begin
|
||||
Result := '';
|
||||
if PKIsNull then
|
||||
Result := '<null>';
|
||||
Result := Format('[ID: %6s][CODE: %6s][CompanyName: %18s][City: %16s][Note: %s]',[
|
||||
Result, fCode.ValueOrDefault, fCompanyName.ValueOrDefault, fCity, fNote]);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -2,8 +2,8 @@ object MainForm: TMainForm
|
||||
Left = 0
|
||||
Top = 0
|
||||
Caption = 'TMVCActiveRecord - ShowCase'
|
||||
ClientHeight = 758
|
||||
ClientWidth = 1054
|
||||
ClientHeight = 569
|
||||
ClientWidth = 1104
|
||||
Color = clBtnFace
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
@ -14,8 +14,8 @@ object MainForm: TMainForm
|
||||
OnShow = FormShow
|
||||
PixelsPerInch = 96
|
||||
DesignSize = (
|
||||
1054
|
||||
758)
|
||||
1104
|
||||
569)
|
||||
TextHeight = 13
|
||||
object btnCRUD: TButton
|
||||
Left = 8
|
||||
@ -36,10 +36,10 @@ object MainForm: TMainForm
|
||||
OnClick = btnSelectClick
|
||||
end
|
||||
object Memo1: TMemo
|
||||
Left = 135
|
||||
Left = 280
|
||||
Top = 8
|
||||
Width = 911
|
||||
Height = 742
|
||||
Width = 816
|
||||
Height = 553
|
||||
Anchors = [akLeft, akTop, akRight, akBottom]
|
||||
Ctl3D = True
|
||||
DoubleBuffered = True
|
||||
@ -56,7 +56,8 @@ object MainForm: TMainForm
|
||||
TabOrder = 2
|
||||
WantReturns = False
|
||||
WordWrap = False
|
||||
ExplicitWidth = 492
|
||||
ExplicitWidth = 766
|
||||
ExplicitHeight = 754
|
||||
end
|
||||
object btnRelations: TButton
|
||||
Left = 8
|
||||
@ -86,10 +87,10 @@ object MainForm: TMainForm
|
||||
OnClick = btnValidationClick
|
||||
end
|
||||
object btnMultiThreading: TButton
|
||||
Left = 8
|
||||
Top = 403
|
||||
Left = 144
|
||||
Top = 8
|
||||
Width = 121
|
||||
Height = 34
|
||||
Height = 33
|
||||
Caption = 'Multi Threading'
|
||||
TabOrder = 6
|
||||
OnClick = btnMultiThreadingClick
|
||||
@ -113,10 +114,10 @@ object MainForm: TMainForm
|
||||
OnClick = btnTransientFieldsClick
|
||||
end
|
||||
object btnNullTest: TButton
|
||||
Left = 8
|
||||
Top = 443
|
||||
Left = 144
|
||||
Top = 47
|
||||
Width = 121
|
||||
Height = 34
|
||||
Height = 33
|
||||
Caption = 'Nullables'
|
||||
TabOrder = 9
|
||||
OnClick = btnNullTestClick
|
||||
@ -150,17 +151,17 @@ object MainForm: TMainForm
|
||||
OnClick = btnWithSpacesClick
|
||||
end
|
||||
object btnCountWithRQL: TButton
|
||||
Left = 8
|
||||
Top = 483
|
||||
Left = 144
|
||||
Top = 86
|
||||
Width = 121
|
||||
Height = 34
|
||||
Height = 33
|
||||
Caption = 'Count with RQL'
|
||||
TabOrder = 13
|
||||
OnClick = btnCountWithRQLClick
|
||||
end
|
||||
object btnReadAndWriteOnly: TButton
|
||||
Left = 8
|
||||
Top = 523
|
||||
Left = 144
|
||||
Top = 125
|
||||
Width = 121
|
||||
Height = 33
|
||||
Caption = 'R/O, R/W'
|
||||
@ -168,8 +169,8 @@ object MainForm: TMainForm
|
||||
OnClick = btnReadAndWriteOnlyClick
|
||||
end
|
||||
object btnClientGeneratedPK: TButton
|
||||
Left = 8
|
||||
Top = 562
|
||||
Left = 144
|
||||
Top = 164
|
||||
Width = 121
|
||||
Height = 33
|
||||
Caption = 'Client Generated PKs'
|
||||
@ -177,8 +178,8 @@ object MainForm: TMainForm
|
||||
OnClick = btnClientGeneratedPKClick
|
||||
end
|
||||
object btnAttributes: TButton
|
||||
Left = 8
|
||||
Top = 599
|
||||
Left = 144
|
||||
Top = 203
|
||||
Width = 121
|
||||
Height = 33
|
||||
Caption = 'Attributes'
|
||||
@ -186,34 +187,43 @@ object MainForm: TMainForm
|
||||
OnClick = btnAttributesClick
|
||||
end
|
||||
object btnJSON_XML_Types: TButton
|
||||
Left = 8
|
||||
Top = 638
|
||||
Left = 144
|
||||
Top = 242
|
||||
Width = 121
|
||||
Height = 33
|
||||
Height = 35
|
||||
Caption = 'JSON && XML'
|
||||
TabOrder = 17
|
||||
OnClick = btnJSON_XML_TypesClick
|
||||
end
|
||||
object btnMerge: TButton
|
||||
Left = 8
|
||||
Top = 677
|
||||
Left = 144
|
||||
Top = 283
|
||||
Width = 121
|
||||
Height = 33
|
||||
Height = 34
|
||||
Caption = 'Merge'
|
||||
TabOrder = 18
|
||||
OnClick = btnMergeClick
|
||||
end
|
||||
object btnTableFilter: TButton
|
||||
Left = 8
|
||||
Top = 716
|
||||
Left = 144
|
||||
Top = 323
|
||||
Width = 121
|
||||
Height = 33
|
||||
Height = 34
|
||||
Caption = 'Table Filter'
|
||||
TabOrder = 19
|
||||
OnClick = btnTableFilterClick
|
||||
end
|
||||
object btnPartitioning: TButton
|
||||
Left = 144
|
||||
Top = 363
|
||||
Width = 121
|
||||
Height = 33
|
||||
Caption = 'Table Partitioning'
|
||||
TabOrder = 20
|
||||
OnClick = btnPartitioningClick
|
||||
end
|
||||
object FDConnection1: TFDConnection
|
||||
Left = 192
|
||||
Top = 56
|
||||
Left = 56
|
||||
Top = 408
|
||||
end
|
||||
end
|
||||
|
@ -23,8 +23,11 @@ uses
|
||||
FireDAC.Stan.Async,
|
||||
FireDAC.Phys,
|
||||
FireDAC.VCLUI.Wait,
|
||||
Data.DB, FireDAC.Comp.Client, MVCFramework.Nullables,
|
||||
MVCFramework.ActiveRecord, System.Generics.Collections;
|
||||
Data.DB,
|
||||
FireDAC.Comp.Client,
|
||||
MVCFramework.Nullables,
|
||||
MVCFramework.ActiveRecord,
|
||||
System.Generics.Collections;
|
||||
|
||||
type
|
||||
TMainForm = class(TForm)
|
||||
@ -49,6 +52,7 @@ type
|
||||
btnJSON_XML_Types: TButton;
|
||||
btnMerge: TButton;
|
||||
btnTableFilter: TButton;
|
||||
btnPartitioning: TButton;
|
||||
procedure btnCRUDClick(Sender: TObject);
|
||||
procedure btnInheritanceClick(Sender: TObject);
|
||||
procedure btnMultiThreadingClick(Sender: TObject);
|
||||
@ -71,6 +75,7 @@ type
|
||||
procedure btnJSON_XML_TypesClick(Sender: TObject);
|
||||
procedure btnMergeClick(Sender: TObject);
|
||||
procedure btnTableFilterClick(Sender: TObject);
|
||||
procedure btnPartitioningClick(Sender: TObject);
|
||||
private
|
||||
procedure Log(const Value: string);
|
||||
procedure LoadCustomers;
|
||||
@ -92,7 +97,9 @@ uses
|
||||
MVCFramework.DataSet.Utils,
|
||||
MVCFramework.RQL.Parser,
|
||||
System.Math,
|
||||
FDConnectionConfigU, EngineChoiceFormU, System.Rtti;
|
||||
FDConnectionConfigU,
|
||||
EngineChoiceFormU,
|
||||
System.Rtti;
|
||||
|
||||
const
|
||||
Cities: array [0 .. 4] of string = ('Rome', 'New York', 'London', 'Melbourne', 'Berlin');
|
||||
@ -763,6 +770,44 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnPartitioningClick(Sender: TObject);
|
||||
begin
|
||||
TMVCActiveRecord.DeleteAll(TCustomerWithRate1);
|
||||
Assert(TMVCActiveRecord.Count(TCustomerWithRate1) = 0);
|
||||
TMVCActiveRecord.DeleteAll(TCustomerWithRate2);
|
||||
Assert(TMVCActiveRecord.Count(TCustomerWithRate2) = 0);
|
||||
var lCust1 := TCustomerWithRate1.Create;
|
||||
try
|
||||
lCust1.City := 'Rome';
|
||||
lCust1.Code := '123';
|
||||
lCust1.Store;
|
||||
finally
|
||||
lCust1.Free;
|
||||
end;
|
||||
var lCust2 := TCustomerWithRate2.Create;
|
||||
try
|
||||
lCust2.City := 'Rome';
|
||||
lCust2.Code := '456';
|
||||
lCust2.Store;
|
||||
Assert(TMVCActiveRecord.GetByPK<TCustomerWithRate1>(lCust2.ID, False) = nil);
|
||||
finally
|
||||
lCust2.Free;
|
||||
end;
|
||||
|
||||
var lList := TMVCActiveRecord.SelectRQL<TCustomerWithRate1>('eq(city,"Rome")',-1);
|
||||
try
|
||||
Assert(lList.Count = 1);
|
||||
Assert(lList[0].Code = '123');
|
||||
finally
|
||||
lList.Free;
|
||||
end;
|
||||
|
||||
Assert(TMVCActiveRecord.Count(TCustomerWithRate1) = 1);
|
||||
Assert(TMVCActiveRecord.Count(TCustomerWithRate1, 'eq(code,"xxx")') = 0);
|
||||
Assert(TMVCActiveRecord.Count(TCustomerWithRate2) = 1);
|
||||
Assert(TMVCActiveRecord.Count(TCustomerWithRate2, 'eq(code,"xxx")') = 0);
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnReadAndWriteOnlyClick(Sender: TObject);
|
||||
var
|
||||
lArtWO, lArtWO2: TArticleWithWriteOnlyFields;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{28115991-DA41-4172-924A-7FCD5AC95F77}</ProjectGuid>
|
||||
<ProjectVersion>18.8</ProjectVersion>
|
||||
<ProjectVersion>19.3</ProjectVersion>
|
||||
<FrameworkType>None</FrameworkType>
|
||||
<MainSource>FilesUploadDemo.dpr</MainSource>
|
||||
<Base>True</Base>
|
||||
@ -23,13 +23,8 @@
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="('$(Platform)'=='OSX32' and '$(Base)'=='true') or '$(Base_OSX32)'!=''">
|
||||
<Base_OSX32>true</Base_OSX32>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="('$(Platform)'=='OSX64' and '$(Base)'=='true') or '$(Base_OSX64)'!=''">
|
||||
<Base_OSX64>true</Base_OSX64>
|
||||
<PropertyGroup Condition="('$(Platform)'=='OSXARM64' and '$(Base)'=='true') or '$(Base_OSXARM64)'!=''">
|
||||
<Base_OSXARM64>true</Base_OSXARM64>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
</PropertyGroup>
|
||||
@ -104,6 +99,7 @@
|
||||
<Android_NotificationIcon48>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png</Android_NotificationIcon48>
|
||||
<Android_NotificationIcon72>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png</Android_NotificationIcon72>
|
||||
<Android_NotificationIcon96>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png</Android_NotificationIcon96>
|
||||
<Android_LauncherIcon192>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png</Android_LauncherIcon192>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base_Android64)'!=''">
|
||||
<VerInfo_Keys>package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=</VerInfo_Keys>
|
||||
@ -136,17 +132,14 @@
|
||||
<Android_NotificationIcon48>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png</Android_NotificationIcon48>
|
||||
<Android_NotificationIcon72>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png</Android_NotificationIcon72>
|
||||
<Android_NotificationIcon96>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png</Android_NotificationIcon96>
|
||||
<Android_LauncherIcon192>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png</Android_LauncherIcon192>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base_OSX32)'!=''">
|
||||
<BT_BuildType>Debug</BT_BuildType>
|
||||
<VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts</VerInfo_Keys>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base_OSX64)'!=''">
|
||||
<VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts</VerInfo_Keys>
|
||||
<BT_BuildType>Debug</BT_BuildType>
|
||||
<Base_OSX32>true</Base_OSX32>
|
||||
<PropertyGroup Condition="'$(Base_OSXARM64)'!=''">
|
||||
<Base_OSX64>true</Base_OSX64>
|
||||
<CfgParent>Base</CfgParent>
|
||||
<Base>true</Base>
|
||||
<BT_BuildType>Debug</BT_BuildType>
|
||||
<Base_OSX32>true</Base_OSX32>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Base_Win32)'!=''">
|
||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||
@ -185,10 +178,6 @@
|
||||
<DCCReference Include="FileUploadControllerU.pas"/>
|
||||
<DCCReference Include="..\serversideviewcustom\MVCFramework.View.Renderers.TemplatePro.pas"/>
|
||||
<DCCReference Include="..\serversideviewcustom\lib\TemplateProU.pas"/>
|
||||
<BuildConfiguration Include="Release">
|
||||
<Key>Cfg_2</Key>
|
||||
<CfgParent>Base</CfgParent>
|
||||
</BuildConfiguration>
|
||||
<BuildConfiguration Include="Base">
|
||||
<Key>Base</Key>
|
||||
</BuildConfiguration>
|
||||
@ -196,6 +185,10 @@
|
||||
<Key>Cfg_1</Key>
|
||||
<CfgParent>Base</CfgParent>
|
||||
</BuildConfiguration>
|
||||
<BuildConfiguration Include="Release">
|
||||
<Key>Cfg_2</Key>
|
||||
<CfgParent>Base</CfgParent>
|
||||
</BuildConfiguration>
|
||||
</ItemGroup>
|
||||
<ProjectExtensions>
|
||||
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
|
||||
@ -252,42 +245,42 @@
|
||||
</Excluded_Packages>
|
||||
</Delphi.Personality>
|
||||
<Deployment Version="3">
|
||||
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
|
||||
<Platform Name="OSX32">
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="$(BDS)\Redist\osx64\libcgsqlite3.dylib" Class="DependencyModule">
|
||||
<Platform Name="OSX64">
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule">
|
||||
<Platform Name="iOSSimulator">
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
|
||||
<Platform Name="iOSSimulator">
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libpcre.dylib" Class="DependencyModule">
|
||||
<Platform Name="iOSSimulator">
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
|
||||
<Platform Name="iOSSimulator">
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule">
|
||||
<Platform Name="OSX32">
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
|
||||
<Platform Name="OSX32">
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="Win32\Debug\FilesUploadDemo.exe" Configuration="Debug" Class="ProjectOutput">
|
||||
<Platform Name="Win32">
|
||||
<RemoteName>FilesUploadDemo.exe</RemoteName>
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="$(BDS)\Redist\osx64\libcgsqlite3.dylib" Class="DependencyModule">
|
||||
<Platform Name="OSX64">
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployClass Name="AdditionalDebugSymbols">
|
||||
<Platform Name="OSX32">
|
||||
<Operation>1</Operation>
|
||||
@ -296,6 +289,16 @@
|
||||
<Operation>0</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="AndroidClasses">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>classes</RemoteDir>
|
||||
<Operation>64</Operation>
|
||||
</Platform>
|
||||
<Platform Name="Android64">
|
||||
<RemoteDir>classes</RemoteDir>
|
||||
<Operation>64</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="AndroidClassesDexFile">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>classes</RemoteDir>
|
||||
@ -424,6 +427,16 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_LauncherIcon192">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="Android64">
|
||||
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_LauncherIcon36">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-ldpi</RemoteDir>
|
||||
@ -584,6 +597,10 @@
|
||||
<Operation>1</Operation>
|
||||
<Extensions>.framework</Extensions>
|
||||
</Platform>
|
||||
<Platform Name="OSXARM64">
|
||||
<Operation>1</Operation>
|
||||
<Extensions>.framework</Extensions>
|
||||
</Platform>
|
||||
<Platform Name="Win32">
|
||||
<Operation>0</Operation>
|
||||
</Platform>
|
||||
@ -597,6 +614,10 @@
|
||||
<Operation>1</Operation>
|
||||
<Extensions>.dylib</Extensions>
|
||||
</Platform>
|
||||
<Platform Name="OSXARM64">
|
||||
<Operation>1</Operation>
|
||||
<Extensions>.dylib</Extensions>
|
||||
</Platform>
|
||||
<Platform Name="Win32">
|
||||
<Operation>0</Operation>
|
||||
<Extensions>.dll;.bpl</Extensions>
|
||||
@ -623,6 +644,10 @@
|
||||
<Operation>1</Operation>
|
||||
<Extensions>.dylib</Extensions>
|
||||
</Platform>
|
||||
<Platform Name="OSXARM64">
|
||||
<Operation>1</Operation>
|
||||
<Extensions>.dylib</Extensions>
|
||||
</Platform>
|
||||
<Platform Name="Win32">
|
||||
<Operation>0</Operation>
|
||||
<Extensions>.bpl</Extensions>
|
||||
@ -650,10 +675,39 @@
|
||||
<Platform Name="OSX64">
|
||||
<Operation>0</Operation>
|
||||
</Platform>
|
||||
<Platform Name="OSXARM64">
|
||||
<Operation>0</Operation>
|
||||
</Platform>
|
||||
<Platform Name="Win32">
|
||||
<Operation>0</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iOS_AppStore1024">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_AppIcon152">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_AppIcon167">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1024">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -786,6 +840,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>
|
||||
@ -808,6 +872,66 @@
|
||||
<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="iPad_Notification40">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Setting58">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_SpotLight80">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_AppIcon120">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_AppIcon180">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1125">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -907,6 +1031,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>
|
||||
@ -918,6 +1052,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>
|
||||
@ -962,6 +1106,86 @@
|
||||
<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="iPhone_Notification40">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Notification60">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Setting58">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Setting87">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Spotlight120">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Spotlight80">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="ProjectAndroidManifest">
|
||||
<Platform Name="Android">
|
||||
<Operation>1</Operation>
|
||||
@ -983,6 +1207,7 @@
|
||||
<DeployClass Name="ProjectiOSDeviceResourceRules"/>
|
||||
<DeployClass Name="ProjectiOSEntitlements"/>
|
||||
<DeployClass Name="ProjectiOSInfoPList"/>
|
||||
<DeployClass Name="ProjectiOSLaunchScreen"/>
|
||||
<DeployClass Name="ProjectiOSResource">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -1006,6 +1231,10 @@
|
||||
<RemoteDir>Contents\Resources</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="OSXARM64">
|
||||
<RemoteDir>Contents\Resources</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Required="true" Name="ProjectOutput">
|
||||
<Platform Name="Android">
|
||||
@ -1034,6 +1263,9 @@
|
||||
<Platform Name="OSX64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="OSXARM64">
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="Win32">
|
||||
<Operation>0</Operation>
|
||||
</Platform>
|
||||
@ -1072,23 +1304,23 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
|
||||
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
|
||||
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="OSX64" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
|
||||
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
|
||||
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
|
||||
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
|
||||
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
|
||||
</Deployment>
|
||||
<Platforms>
|
||||
<Platform value="Android">False</Platform>
|
||||
<Platform value="Android64">False</Platform>
|
||||
<Platform value="Linux64">True</Platform>
|
||||
<Platform value="OSX32">False</Platform>
|
||||
<Platform value="OSX64">False</Platform>
|
||||
<Platform value="OSXARM64">False</Platform>
|
||||
<Platform value="Win32">True</Platform>
|
||||
<Platform value="Win64">False</Platform>
|
||||
</Platforms>
|
||||
|
@ -70,6 +70,11 @@ type
|
||||
TMVCActiveRecordLoadOption = (loIgnoreNotExistentFields);
|
||||
TMVCActiveRecordLoadOptions = set of TMVCActiveRecordLoadOption;
|
||||
|
||||
TPartionFieldNames = TArray<String>;
|
||||
TPartionFieldValues = TArray<String>;
|
||||
TPartionFieldTypes = TArray<TFieldType>;
|
||||
|
||||
|
||||
IMVCEntityProcessor = interface
|
||||
['{E7CD11E6-9FF9-46D2-B7B0-DA5B38EAA14E}']
|
||||
procedure GetEntities(const Context: TWebContext; const Renderer: TMVCRenderer;
|
||||
@ -123,6 +128,13 @@ type
|
||||
constructor Create(aName: string; aRQLFilter: String); overload;
|
||||
end;
|
||||
|
||||
MVCPartitionAttribute = class(MVCActiveRecordCustomAttribute)
|
||||
public
|
||||
PartitionClause: String;
|
||||
constructor Create(const PartitionClause: String);
|
||||
end;
|
||||
|
||||
|
||||
MVCTableFieldAttribute = class(MVCActiveRecordCustomAttribute)
|
||||
public
|
||||
FieldName: string;
|
||||
@ -145,6 +157,16 @@ type
|
||||
|
||||
TMVCSQLGenerator = class;
|
||||
|
||||
TPartitionInfo = class
|
||||
FieldNames: TPartionFieldNames;
|
||||
FieldValues: TPartionFieldValues;
|
||||
FieldTypes: TPartionFieldTypes;
|
||||
RQLFilter: String;
|
||||
SQLFilter: String;
|
||||
constructor Create;
|
||||
procedure InitializeFilterStrings(const SQLGenerator: TMVCSQLGenerator);
|
||||
end;
|
||||
|
||||
TMVCActiveRecordList = class(TObjectList<TMVCActiveRecord>)
|
||||
public
|
||||
constructor Create; virtual;
|
||||
@ -179,6 +201,7 @@ type
|
||||
fPrimaryKey: TRTTIField;
|
||||
fBackendDriver: string;
|
||||
fMapping: TMVCFieldsMapping;
|
||||
fPartitionInfo: TPartitionInfo;
|
||||
function GetBackEnd: string;
|
||||
function GetConnection: TFDConnection;
|
||||
procedure InitTableInfo;
|
||||
@ -490,16 +513,19 @@ type
|
||||
fCompiler: TRQLCompiler;
|
||||
fRQL2SQL: TRQL2SQL;
|
||||
protected
|
||||
fPartitionInfo: TPartitionInfo;
|
||||
function GetDefaultSQLFilter(const IncludeWhereClause: Boolean; const IncludeAndClauseBeforeFilter: Boolean = False): String; //inline;
|
||||
function MergeDefaultRQLFilter(const RQL: String): String; //inline;
|
||||
function GetRQLParser(const MaxRecordCount: Int32): TRQL2SQL;
|
||||
function MergeRQL(const RQL1, RQL2: String): String;
|
||||
function MergeSQLFilter(const SQL1, SQL2: String): String;
|
||||
function GetRQLParser: TRQL2SQL;
|
||||
function GetCompiler: TRQLCompiler;
|
||||
function GetCompilerClass: TRQLCompilerClass; virtual; abstract;
|
||||
function GetMapping: TMVCFieldsMapping;
|
||||
function TableFieldsDelimited(const Map: TFieldsMap; const PKFieldName: string;
|
||||
const Delimiter: string): string;
|
||||
public
|
||||
constructor Create(Mapping: TMVCFieldsMapping; const DefaultRQLFilter: string); virtual;
|
||||
constructor Create(Mapping: TMVCFieldsMapping; const DefaultRQLFilter: string; const PartitionInfo: TPartitionInfo); virtual;
|
||||
destructor Destroy; override;
|
||||
// capabilities
|
||||
function HasSequences: Boolean; virtual;
|
||||
@ -507,7 +533,7 @@ type
|
||||
// end-capabilities
|
||||
function CreateSQLWhereByRQL(const RQL: string; const Mapping: TMVCFieldsMapping;
|
||||
const UseArtificialLimit: Boolean = True; const UseFilterOnly: Boolean = false;
|
||||
const MaxRecordCount: UInt32 = TMVCConstants.MAX_RECORD_COUNT): string; virtual; abstract;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; virtual; abstract;
|
||||
function CreateSelectSQL(const TableName: string; const Map: TFieldsMap;
|
||||
const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
|
||||
@ -618,6 +644,44 @@ var
|
||||
gConnections: IMVCActiveRecordConnections;
|
||||
gLock: TObject;
|
||||
|
||||
function ParsePartitionClause(const PartitionClause: String): TPartitionInfo;
|
||||
var
|
||||
lPieces, lItems: TArray<String>;
|
||||
lPiece: String;
|
||||
begin
|
||||
{
|
||||
Needs to parse [MVCPartition('rating=(integer)4;classname=(string)persona')]
|
||||
}
|
||||
Result := TPartitionInfo.Create;
|
||||
try
|
||||
lPieces := PartitionClause.Split([';']);
|
||||
for lPiece in lPieces do
|
||||
begin
|
||||
lItems := lPiece.Split(['=','(',')'], TStringSplitOptions.ExcludeEmpty);
|
||||
if Length(lItems)<>3 then
|
||||
begin
|
||||
raise EMVCActiveRecord.Create('Invalid partitioning clause: ' + lPiece + '. [HINT] Paritioning must be in the form: "[fieldname1=(integer|string)value1]"');
|
||||
end;
|
||||
|
||||
Insert(lItems[0], Result.FieldNames,0);
|
||||
if lItems[1]='integer' then
|
||||
Insert(ftInteger, Result.FieldTypes,0)
|
||||
else if lItems[1]='string' then
|
||||
begin
|
||||
Insert(ftString, Result.FieldTypes,0)
|
||||
end
|
||||
else
|
||||
begin
|
||||
raise EMVCActiveRecord.Create('Unknown data type in partitioning: ' + lItems[1] + '. [HINT] data type can be "integer" or "string"');
|
||||
end;
|
||||
Insert(lItems[2], Result.FieldValues,0);
|
||||
end;
|
||||
except
|
||||
Result.Free;
|
||||
raise;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetBackEndByConnection(aConnection: TFDConnection): string;
|
||||
begin
|
||||
case Ord(aConnection.RDBMSKind) of
|
||||
@ -920,6 +984,7 @@ begin
|
||||
fMap.Free;
|
||||
fSQLGenerator.Free;
|
||||
fRQL2SQL.Free;
|
||||
fPartitionInfo.Free;
|
||||
fConn := nil; // do not free it!!
|
||||
inherited;
|
||||
end;
|
||||
@ -938,6 +1003,7 @@ var
|
||||
lValue: TValue;
|
||||
lSQL: string;
|
||||
lHandled: Boolean;
|
||||
I: Integer;
|
||||
begin
|
||||
lQry := TFDQuery.Create(nil);
|
||||
try
|
||||
@ -951,6 +1017,22 @@ begin
|
||||
MapObjectToParams(lQry.Params, lHandled);
|
||||
if not lHandled then
|
||||
begin
|
||||
{partitioning}
|
||||
for I := 0 to Length(fPartitionInfo.FieldNames)-1 do
|
||||
begin
|
||||
lPar := lQry.FindParam(SQLGenerator.GetParamNameForSQL(fPartitionInfo.FieldNames[I]));
|
||||
if lPar <> nil then
|
||||
begin
|
||||
if fPartitionInfo.FieldTypes[I] = ftInteger then
|
||||
lValue := StrToInt(fPartitionInfo.FieldValues[I])
|
||||
else
|
||||
lValue := fPartitionInfo.FieldValues[I];
|
||||
//lPar.DataTypeName := fPartitionInfo.FieldValues[I];
|
||||
MapTValueToParam(lValue, lPar);
|
||||
end
|
||||
end;
|
||||
{end-partitioning}
|
||||
|
||||
for lPair in fMap do
|
||||
begin
|
||||
lPar := lQry.FindParam(SQLGenerator.GetParamNameForSQL(lPair.Value.FieldName));
|
||||
@ -1041,6 +1123,7 @@ var
|
||||
lFieldInfo: TFieldInfo;
|
||||
lPrimaryFieldTypeAsStr: string;
|
||||
begin
|
||||
fPartitionInfo := nil;
|
||||
fEntityAllowedActions := [TMVCEntityAction.eaCreate, TMVCEntityAction.eaRetrieve,
|
||||
TMVCEntityAction.eaUpdate,
|
||||
TMVCEntityAction.eaDelete];
|
||||
@ -1059,8 +1142,19 @@ begin
|
||||
begin
|
||||
fEntityAllowedActions := MVCEntityActionsAttribute(lAttribute).EntityAllowedActions;
|
||||
end;
|
||||
if lAttribute is MVCPartitionAttribute then
|
||||
begin
|
||||
fPartitionInfo := ParsePartitionClause(MVCPartitionAttribute(lAttribute).PartitionClause);
|
||||
Continue;
|
||||
end;
|
||||
end;
|
||||
|
||||
if fPartitionInfo = nil then
|
||||
begin
|
||||
fPartitionInfo := TPartitionInfo.Create;
|
||||
end;
|
||||
|
||||
|
||||
if fTableName = '' then
|
||||
begin
|
||||
if [eaCreate, eaUpdate, eaDelete] * fEntityAllowedActions <> [] then
|
||||
@ -1133,6 +1227,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
fMap.EndUpdates;
|
||||
fPartitionInfo.InitializeFilterStrings(SQLGenerator);
|
||||
Assert(fMap.WritableFieldsCount + fMap.ReadableFieldsCount > 0,
|
||||
'No fields defined [HINT] Use MVCTableField in private fields');
|
||||
end;
|
||||
@ -2273,9 +2368,8 @@ var
|
||||
begin
|
||||
lAR := T.Create;
|
||||
try
|
||||
lSQL := lAR.SQLGenerator.CreateSQLWhereByRQL(RQL, lAR.GetMapping, MaxRecordCount > -1, false,
|
||||
MaxRecordCount).Trim;
|
||||
// LogD(Format('RQL [%s] => SQL [%s]', [RQL, lSQL]));
|
||||
lSQL := lAR.SQLGenerator.CreateSQLWhereByRQL(RQL, lAR.GetMapping,
|
||||
MaxRecordCount > -1, False, MaxRecordCount).Trim;
|
||||
lSQL := TMVCSQLGenerator.RemoveInitialWhereKeyword(lSQL);
|
||||
Result := Where<T>(lSQL, []);
|
||||
finally
|
||||
@ -2574,7 +2668,7 @@ begin
|
||||
begin
|
||||
GetConnection.Connected := True;
|
||||
fSQLGenerator := TMVCSQLGeneratorRegistry.Instance.GetSQLGenerator(GetBackEnd)
|
||||
.Create(GetMapping, fDefaultRQLFilter);
|
||||
.Create(GetMapping, fDefaultRQLFilter, fPartitionInfo);
|
||||
end;
|
||||
Result := fSQLGenerator;
|
||||
end;
|
||||
@ -2942,15 +3036,16 @@ end;
|
||||
|
||||
{ TMVCSQLGenerator }
|
||||
|
||||
constructor TMVCSQLGenerator.Create(Mapping: TMVCFieldsMapping; const DefaultRQLFilter: string);
|
||||
constructor TMVCSQLGenerator.Create(Mapping: TMVCFieldsMapping; const DefaultRQLFilter: string; const PartitionInfo: TPartitionInfo);
|
||||
begin
|
||||
inherited Create;
|
||||
fMapping := Mapping;
|
||||
fDefaultRQLFilter := DefaultRQLFilter;
|
||||
fPartitionInfo := PartitionInfo;
|
||||
GetCompiler;
|
||||
if not fDefaultRQLFilter.IsEmpty then
|
||||
begin
|
||||
GetRQLParser(-1).Execute(fDefaultRQLFilter,fDefaultSQLFilter, GetCompiler, False, True);
|
||||
GetRQLParser.Execute(fDefaultRQLFilter,fDefaultSQLFilter, GetCompiler, False, True);
|
||||
fDefaultSQLFilter := TMVCSQLGenerator.RemoveInitialWhereKeyword(fDefaultSQLFilter);
|
||||
end;
|
||||
end;
|
||||
@ -2983,19 +3078,17 @@ end;
|
||||
|
||||
function TMVCSQLGenerator.GetDefaultSQLFilter(const IncludeWhereClause: Boolean; const IncludeAndClauseBeforeFilter: Boolean): String;
|
||||
begin
|
||||
Result := '';
|
||||
if not fDefaultSQLFilter.IsEmpty then
|
||||
Result := MergeSQLFilter(fPartitionInfo.SQLFilter, fDefaultSQLFilter);
|
||||
if not Result.IsEmpty then
|
||||
begin
|
||||
if IncludeWhereClause then
|
||||
begin
|
||||
Result := ' WHERE ' + fDefaultSQLFilter
|
||||
Result := ' WHERE ' + Result;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if IncludeAndClauseBeforeFilter then
|
||||
Result := ' and ' + fDefaultSQLFilter
|
||||
else
|
||||
Result := fDefaultSQLFilter;
|
||||
Result := ' and ' + Result;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -3005,11 +3098,11 @@ begin
|
||||
Result := fCompiler.GetFieldNameForSQL(FieldName);
|
||||
end;
|
||||
|
||||
function TMVCSQLGenerator.GetRQLParser(const MaxRecordCount: Int32): TRQL2SQL;
|
||||
function TMVCSQLGenerator.GetRQLParser: TRQL2SQL;
|
||||
begin
|
||||
if fRQL2SQL = nil then
|
||||
begin
|
||||
fRQL2SQL := TRQL2SQL.Create(MaxRecordCount);
|
||||
fRQL2SQL := TRQL2SQL.Create;
|
||||
end;
|
||||
Result := fRQL2SQL;
|
||||
end;
|
||||
@ -3063,6 +3156,41 @@ begin
|
||||
begin
|
||||
Result := RQL;
|
||||
end;
|
||||
Result := MergeRQL(Result, fPartitionInfo.RQLFilter);
|
||||
end;
|
||||
|
||||
function TMVCSQLGenerator.MergeRQL(const RQL1, RQL2: String): String;
|
||||
begin
|
||||
if RQL1+RQL2 = '' then
|
||||
begin
|
||||
Exit('');
|
||||
end;
|
||||
if RQL1.IsEmpty and (not RQL2.IsEmpty) then
|
||||
begin
|
||||
Exit(RQL2);
|
||||
end;
|
||||
if RQL2.IsEmpty and (not RQL1.IsEmpty) then
|
||||
begin
|
||||
Exit(RQL1);
|
||||
end;
|
||||
Result := 'and(' + RQL1 + ',' + RQL2 + ')';
|
||||
end;
|
||||
|
||||
function TMVCSQLGenerator.MergeSQLFilter(const SQL1, SQL2: String): String;
|
||||
begin
|
||||
if SQL1 + SQL2 = '' then
|
||||
begin
|
||||
Exit('');
|
||||
end;
|
||||
if SQL1.IsEmpty and (not SQL2.IsEmpty) then
|
||||
begin
|
||||
Exit(SQL2);
|
||||
end;
|
||||
if SQL2.IsEmpty and (not SQL1.IsEmpty) then
|
||||
begin
|
||||
Exit(SQL1);
|
||||
end;
|
||||
Result := '((' + SQL1 + ') and (' + SQL2 + '))';
|
||||
end;
|
||||
|
||||
class function TMVCSQLGenerator.RemoveInitialWhereKeyword(
|
||||
@ -3412,6 +3540,47 @@ begin
|
||||
RQLFilter := aRQLFilter;
|
||||
end;
|
||||
|
||||
{ MVCPartitionAttribute }
|
||||
|
||||
constructor MVCPartitionAttribute.Create(const PartitionClause: String);
|
||||
begin
|
||||
inherited Create;
|
||||
Self.PartitionClause := PartitionClause;
|
||||
end;
|
||||
|
||||
{ TPartitionInfo }
|
||||
|
||||
constructor TPartitionInfo.Create;
|
||||
begin
|
||||
inherited;
|
||||
SetLength(FieldNames, 0);
|
||||
SetLength(FieldValues, 0);
|
||||
SetLength(FieldTypes, 0);
|
||||
end;
|
||||
|
||||
procedure TPartitionInfo.InitializeFilterStrings(
|
||||
const SQLGenerator: TMVCSQLGenerator);
|
||||
var
|
||||
lFieldCount, I: Integer;
|
||||
begin
|
||||
RQLFilter := '';
|
||||
lFieldCount := Length(FieldNames);
|
||||
if lFieldCount > 0 then
|
||||
begin
|
||||
for I := 0 to lFieldCount - 1 do
|
||||
begin
|
||||
RQLFilter := RQLFilter + 'eq(' + FieldNames[i] + ',' + FieldValues[i] + '),';
|
||||
end;
|
||||
RQLFilter := RQLFilter.Remove(RQLFilter.Length - 1,1);
|
||||
if lFieldCount > 1 then
|
||||
begin
|
||||
RQLFilter := 'and(' + RQLFilter + ')';
|
||||
end;
|
||||
end;
|
||||
SQLGenerator.GetRQLParser.Execute(RQLFilter, SQLFilter,SQLGenerator.GetCompiler,False, True);
|
||||
SQLFilter := TMVCSQLGenerator.RemoveInitialWhereKeyword(SQLFilter);
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
gLock := TObject.Create;
|
||||
|
@ -123,7 +123,7 @@ type
|
||||
DEFAULT_MAX_REQUEST_SIZE = OneMiB * 5; // 5 MiB
|
||||
HATEOAS_PROP_NAME = 'links';
|
||||
X_HTTP_Method_Override = 'X-HTTP-Method-Override';
|
||||
MAX_RECORD_COUNT = 20;
|
||||
MAX_RECORD_COUNT = 100;
|
||||
end;
|
||||
|
||||
HATEOAS = record
|
||||
|
@ -86,7 +86,7 @@ begin
|
||||
else
|
||||
lValue := aRQLFIlter.OpRight;
|
||||
|
||||
lDBFieldName := GetDatabaseFieldName(aRQLFIlter.OpLeft);
|
||||
lDBFieldName := GetDatabaseFieldName(aRQLFIlter.OpLeft, True);
|
||||
|
||||
case aRQLFIlter.Token of
|
||||
tkEq:
|
||||
|
@ -91,7 +91,7 @@ type
|
||||
private
|
||||
fMapping: TMVCFieldsMapping;
|
||||
protected
|
||||
function GetDatabaseFieldName(const RQLPropertyName: string): string;
|
||||
function GetDatabaseFieldName(const RQLPropertyName: string; const UsePropertyNameIfAttributeDoesntExists: Boolean = False): string;
|
||||
function QuoteStringArray(const aStringArray: TArray<string>): TArray<string>;
|
||||
public
|
||||
constructor Create(const Mapping: TMVCFieldsMapping); virtual;
|
||||
@ -179,16 +179,15 @@ type
|
||||
fInputLength: Integer;
|
||||
fCurr: Char;
|
||||
fCurrToken: TRQLToken;
|
||||
fMaxRecordCount: Int64;
|
||||
protected
|
||||
/// /// RQL Sections
|
||||
function ParseFilters: Boolean;
|
||||
function ParseSort: Boolean;
|
||||
function ParseLimit: Boolean;
|
||||
function ParseLimit(const MaxRecordCount: Integer): Boolean;
|
||||
/// ///RQL functions
|
||||
procedure ParseBinOperator(const aToken: TRQLToken; const aAST: TObjectList<TRQLCustom>);
|
||||
procedure ParseLogicOperator(const aToken: TRQLToken; const aAST: TObjectList<TRQLCustom>);
|
||||
procedure ParseSortLimit(const Required: Boolean);
|
||||
procedure ParseSortLimit(const Required: Boolean; const MaxRecordCount: Integer);
|
||||
/// //Parser utils
|
||||
function MatchFieldName(out lFieldName: string): Boolean;
|
||||
function MatchFieldStringValue(out lFieldValue: string): Boolean;
|
||||
@ -208,14 +207,15 @@ type
|
||||
procedure EatWhiteSpaces;
|
||||
procedure CheckEOF(const Token: TRQLToken);
|
||||
public
|
||||
constructor Create(const MaxRecordCount: Integer = -1);
|
||||
constructor Create; virtual;
|
||||
destructor Destroy; override;
|
||||
procedure Execute(
|
||||
const RQL: string;
|
||||
out SQL: string;
|
||||
const RQLCompiler: TRQLCompiler;
|
||||
const SetArtificialLimit: Boolean = true;
|
||||
const UseFilterOnly: Boolean = False);
|
||||
const UseFilterOnly: Boolean = False;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT);
|
||||
end;
|
||||
|
||||
TRQLCompilerRegistry = class sealed
|
||||
@ -268,11 +268,10 @@ begin
|
||||
Error('Unexpected end of expression');
|
||||
end;
|
||||
|
||||
constructor TRQL2SQL.Create(const MaxRecordCount: Integer);
|
||||
constructor TRQL2SQL.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
fAST := TRQLAbstractSyntaxTree.Create;
|
||||
fMaxRecordCount := MaxRecordCount;
|
||||
end;
|
||||
|
||||
destructor TRQL2SQL.Destroy;
|
||||
@ -321,7 +320,8 @@ procedure TRQL2SQL.Execute(
|
||||
out SQL: string;
|
||||
const RQLCompiler: TRQLCompiler;
|
||||
const SetArtificialLimit: Boolean;
|
||||
const UseFilterOnly: Boolean);
|
||||
const UseFilterOnly: Boolean;
|
||||
const MaxRecordCount: Int32);
|
||||
var
|
||||
lLimit: TRQLLimit;
|
||||
lRQLItem: TRQLCustom;
|
||||
@ -345,25 +345,25 @@ begin
|
||||
fAST.Insert(0, TRQLWhere.Create);
|
||||
if GetToken = tkSemicolon then
|
||||
begin
|
||||
ParseSortLimit(true);
|
||||
ParseSortLimit(true, MaxRecordCount);
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
ParseSortLimit(False);
|
||||
ParseSortLimit(False, MaxRecordCount);
|
||||
end;
|
||||
EatWhiteSpaces;
|
||||
if GetToken <> tkEOF then
|
||||
Error('Expected EOF');
|
||||
|
||||
// add artificial limit
|
||||
if SetArtificialLimit and (fMaxRecordCount > -1) and (not fAST.TreeContainsToken(tkLimit, lRQLItem)) then
|
||||
if SetArtificialLimit and (MaxRecordCount > -1) and (not fAST.TreeContainsToken(tkLimit, lRQLItem)) then
|
||||
begin
|
||||
lLimit := TRQLLimit.Create;
|
||||
fAST.Add(lLimit);
|
||||
lLimit.Token := tkLimit;
|
||||
lLimit.Start := 0;
|
||||
lLimit.Count := fMaxRecordCount;
|
||||
lLimit.Count := MaxRecordCount;
|
||||
end;
|
||||
|
||||
|
||||
@ -686,7 +686,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TRQL2SQL.ParseLimit: Boolean;
|
||||
function TRQL2SQL.ParseLimit(const MaxRecordCount: Integer): Boolean;
|
||||
var
|
||||
lStart: string;
|
||||
lCount: string;
|
||||
@ -717,9 +717,9 @@ begin
|
||||
fAST.Add(lRQLLimit);
|
||||
lRQLLimit.Token := tkLimit;
|
||||
lRQLLimit.Start := StrToInt64(lStart); // XE7 compat
|
||||
if fMaxRecordCount > -1 then
|
||||
if MaxRecordCount > -1 then
|
||||
begin
|
||||
lRQLLimit.Count := Min(StrToInt64(lCount), fMaxRecordCount);
|
||||
lRQLLimit.Count := Min(StrToInt64(lCount), MaxRecordCount);
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -810,7 +810,7 @@ begin
|
||||
Error('Expected ")"');
|
||||
end;
|
||||
|
||||
procedure TRQL2SQL.ParseSortLimit(const Required: Boolean);
|
||||
procedure TRQL2SQL.ParseSortLimit(const Required: Boolean; const MaxRecordCount: Integer);
|
||||
var
|
||||
lFoundSort: Boolean;
|
||||
lFoundLimit: Boolean;
|
||||
@ -823,7 +823,7 @@ begin
|
||||
begin
|
||||
BackToLastPos;
|
||||
end;
|
||||
lFoundLimit := ParseLimit;
|
||||
lFoundLimit := ParseLimit(MaxRecordCount);
|
||||
if Required and (not(lFoundSort or lFoundLimit)) then
|
||||
Error('Expected "sort" and/or "limit"');
|
||||
end;
|
||||
@ -1151,7 +1151,7 @@ begin
|
||||
end;
|
||||
|
||||
function TRQLCompiler.GetDatabaseFieldName(
|
||||
const RQLPropertyName: string): string;
|
||||
const RQLPropertyName: string; const UsePropertyNameIfAttributeDoesntExists: Boolean): string;
|
||||
var
|
||||
lField: TMVCFieldMap;
|
||||
lRQLProperty: string;
|
||||
@ -1171,8 +1171,11 @@ begin
|
||||
Exit(GetFieldNameForSQL(lField.DatabaseFieldName));
|
||||
end;
|
||||
{ TODO -oDanieleT -cGeneral : Here we should consider also MVCNameAs attribute to find the name }
|
||||
raise ERQLException.CreateFmt('Property %s does not exist or is transient and cannot be used in RQL',
|
||||
[RQLPropertyName]);
|
||||
if UsePropertyNameIfAttributeDoesntExists then
|
||||
Exit(GetFieldNameForSQL(RQLPropertyName))
|
||||
else
|
||||
raise ERQLException.CreateFmt('Property %s does not exist or is transient and cannot be used in RQL',
|
||||
[RQLPropertyName]);
|
||||
end;
|
||||
|
||||
function TRQLCompiler.GetFieldNameForSQL(const FieldName: string): string;
|
||||
|
@ -73,7 +73,7 @@ type
|
||||
const RQL: string; const Mapping: TMVCFieldsMapping;
|
||||
const UseArtificialLimit: Boolean = True;
|
||||
const UseFilterOnly: Boolean = False;
|
||||
const MaxRecordCount: UInt32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
|
||||
function CreateSelectCount(
|
||||
const TableName: string): string; override;
|
||||
end;
|
||||
@ -161,13 +161,14 @@ function TMVCSQLGeneratorFirebird.CreateSQLWhereByRQL(
|
||||
const RQL: string; const Mapping: TMVCFieldsMapping;
|
||||
const UseArtificialLimit: Boolean = True;
|
||||
const UseFilterOnly: Boolean = False;
|
||||
const MaxRecordCount: UInt32 = TMVCConstants.MAX_RECORD_COUNT): string;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string;
|
||||
var
|
||||
lFirebirdCompiler: TRQLFirebirdCompiler;
|
||||
begin
|
||||
lFirebirdCompiler := TRQLFirebirdCompiler.Create(Mapping);
|
||||
try
|
||||
GetRQLParser(MaxRecordCount).Execute(RQL, Result, lFirebirdCompiler, UseArtificialLimit, UseFilterOnly);
|
||||
GetRQLParser.Execute(RQL, Result, lFirebirdCompiler,
|
||||
UseArtificialLimit, UseFilterOnly, MaxRecordCount);
|
||||
finally
|
||||
lFirebirdCompiler.Free;
|
||||
end;
|
||||
|
@ -68,7 +68,7 @@ type
|
||||
const RQL: string; const Mapping: TMVCFieldsMapping;
|
||||
const UseArtificialLimit: Boolean = True;
|
||||
const UseFilterOnly: Boolean = False;
|
||||
const MaxRecordCount: UInt32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
|
||||
function CreateSelectCount(
|
||||
const TableName: string): string; override;
|
||||
function CreateDeleteAllSQL(
|
||||
@ -156,13 +156,13 @@ function TMVCSQLGeneratorMSSQL.CreateSQLWhereByRQL(
|
||||
const RQL: string; const Mapping: TMVCFieldsMapping;
|
||||
const UseArtificialLimit: Boolean = True;
|
||||
const UseFilterOnly: Boolean = False;
|
||||
const MaxRecordCount: UInt32 = TMVCConstants.MAX_RECORD_COUNT): string;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string;
|
||||
var
|
||||
lMSSQLCompiler: TRQLMSSQLCompiler;
|
||||
begin
|
||||
lMSSQLCompiler := TRQLMSSQLCompiler.Create(Mapping);
|
||||
try
|
||||
GetRQLParser(MaxRecordCount).Execute(RQL, Result, lMSSQLCompiler, UseArtificialLimit, UseFilterOnly);
|
||||
GetRQLParser.Execute(RQL, Result, lMSSQLCompiler, UseArtificialLimit, UseFilterOnly, MaxRecordCount);
|
||||
finally
|
||||
lMSSQLCompiler.Free;
|
||||
end;
|
||||
|
@ -70,7 +70,7 @@ type
|
||||
const RQL: string; const Mapping: TMVCFieldsMapping;
|
||||
const UseArtificialLimit: Boolean = True;
|
||||
const UseFilterOnly: Boolean = False;
|
||||
const MaxRecordCount: UInt32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
|
||||
function CreateSelectCount(
|
||||
const TableName: string): string; override;
|
||||
end;
|
||||
@ -157,13 +157,13 @@ function TMVCSQLGeneratorMySQL.CreateSQLWhereByRQL(
|
||||
const RQL: string; const Mapping: TMVCFieldsMapping;
|
||||
const UseArtificialLimit: Boolean = True;
|
||||
const UseFilterOnly: Boolean = False;
|
||||
const MaxRecordCount: UInt32 = TMVCConstants.MAX_RECORD_COUNT): string;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string;
|
||||
var
|
||||
lMySQLCompiler: TRQLMySQLCompiler;
|
||||
begin
|
||||
lMySQLCompiler := TRQLMySQLCompiler.Create(Mapping);
|
||||
try
|
||||
GetRQLParser(MaxRecordCount).Execute(RQL, Result, lMySQLCompiler, UseArtificialLimit, UseFilterOnly);
|
||||
GetRQLParser.Execute(RQL, Result, lMySQLCompiler, UseArtificialLimit, UseFilterOnly, MaxRecordCount);
|
||||
finally
|
||||
lMySQLCompiler.Free;
|
||||
end;
|
||||
|
@ -71,7 +71,7 @@ type
|
||||
const Mapping: TMVCFieldsMapping;
|
||||
const UseArtificialLimit: Boolean;
|
||||
const UseFilterOnly: Boolean;
|
||||
const MaxRecordCount: UInt32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
|
||||
function CreateSelectCount(
|
||||
const TableName: string): string; override;
|
||||
function GetSequenceValueSQL(const PKFieldName: string;
|
||||
@ -98,6 +98,7 @@ var
|
||||
lKeyValue: TPair<TRttiField, TFieldInfo>;
|
||||
lSB: TStringBuilder;
|
||||
lPKInInsert: Boolean;
|
||||
lFieldName: String;
|
||||
begin
|
||||
lPKInInsert := (not PKFieldName.IsEmpty) and (not(TMVCActiveRecordFieldOption.foAutoGenerated in PKOptions));
|
||||
lPKInInsert := lPKInInsert and (not(TMVCActiveRecordFieldOption.foReadOnly in PKOptions));
|
||||
@ -109,6 +110,13 @@ begin
|
||||
lSB.Append(GetFieldNameForSQL(PKFieldName) + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
for lFieldName in fPartitionInfo.FieldNames do
|
||||
begin
|
||||
lSB.Append(GetFieldNameForSQL(lFieldName) + ',');
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
begin
|
||||
// if not(foTransient in lKeyValue.Value.FieldOptions) then
|
||||
@ -123,6 +131,14 @@ begin
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(PKFieldName) + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
for lFieldName in fPartitionInfo.FieldNames do
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(lFieldName) + ',');
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
@ -177,13 +193,14 @@ function TMVCSQLGeneratorPostgreSQL.CreateSQLWhereByRQL(
|
||||
const Mapping: TMVCFieldsMapping;
|
||||
const UseArtificialLimit: Boolean;
|
||||
const UseFilterOnly: Boolean;
|
||||
const MaxRecordCount: UInt32): string;
|
||||
const MaxRecordCount: Int32): string;
|
||||
var
|
||||
lPostgreSQLCompiler: TRQLPostgreSQLCompiler;
|
||||
begin
|
||||
lPostgreSQLCompiler := TRQLPostgreSQLCompiler.Create(Mapping);
|
||||
try
|
||||
GetRQLParser(MaxRecordCount).Execute(MergeDefaultRQLFilter(RQL), Result, lPostgreSQLCompiler, UseArtificialLimit, UseFilterOnly);
|
||||
GetRQLParser.Execute(MergeDefaultRQLFilter(RQL), Result, lPostgreSQLCompiler,
|
||||
UseArtificialLimit, UseFilterOnly, MaxRecordCount);
|
||||
finally
|
||||
lPostgreSQLCompiler.Free;
|
||||
end;
|
||||
@ -193,6 +210,7 @@ function TMVCSQLGeneratorPostgreSQL.CreateUpdateSQL(const TableName: string; con
|
||||
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
|
||||
var
|
||||
lPair: TPair<TRttiField, TFieldInfo>;
|
||||
I: Integer;
|
||||
begin
|
||||
Result := 'UPDATE ' + GetTableNameForSQL(TableName) + ' SET ';
|
||||
for lPair in Map do
|
||||
@ -203,6 +221,13 @@ begin
|
||||
GetParamNameForSQL(lPair.Value.FieldName) + ',';
|
||||
end;
|
||||
end;
|
||||
{partition}
|
||||
for I := 0 to Length(fPartitionInfo.FieldNames) - 1 do
|
||||
begin
|
||||
Result := Result + GetFieldNameForSQL(fPartitionInfo.FieldNames[I]) + ' = :' +
|
||||
GetParamNameForSQL(fPartitionInfo.FieldNames[I]) + ',';
|
||||
end;
|
||||
{end-partitioning}
|
||||
Result[Length(Result)] := ' ';
|
||||
if not PKFieldName.IsEmpty then
|
||||
begin
|
||||
|
@ -51,7 +51,7 @@ type
|
||||
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string; override;
|
||||
function CreateSQLWhereByRQL(const RQL: string; const Mapping: TMVCFieldsMapping;
|
||||
const UseArtificialLimit: Boolean = True; const UseFilterOnly: Boolean = False;
|
||||
const MaxRecordCount: UInt32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
|
||||
function CreateSelectCount(const TableName: string): string; override;
|
||||
function HasSequences: Boolean; override;
|
||||
end;
|
||||
@ -135,14 +135,14 @@ end;
|
||||
function TMVCSQLGeneratorSQLite.CreateSQLWhereByRQL(const RQL: string;
|
||||
const Mapping: TMVCFieldsMapping; const UseArtificialLimit: Boolean = True;
|
||||
const UseFilterOnly: Boolean = False;
|
||||
const MaxRecordCount: UInt32 = TMVCConstants.MAX_RECORD_COUNT): string;
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string;
|
||||
var
|
||||
lSQLiteCompiler: TRQLSQLiteCompiler;
|
||||
begin
|
||||
lSQLiteCompiler := TRQLSQLiteCompiler.Create(Mapping);
|
||||
try
|
||||
GetRQLParser(MaxRecordCount).Execute(RQL, Result, lSQLiteCompiler, UseArtificialLimit,
|
||||
UseFilterOnly);
|
||||
GetRQLParser.Execute(RQL, Result, lSQLiteCompiler,
|
||||
UseArtificialLimit, UseFilterOnly, MaxRecordCount);
|
||||
finally
|
||||
lSQLiteCompiler.Free;
|
||||
end;
|
||||
|
@ -4,7 +4,7 @@
|
||||
<ProjectVersion>19.3</ProjectVersion>
|
||||
<FrameworkType>VCL</FrameworkType>
|
||||
<Base>True</Base>
|
||||
<Config Condition="'$(Config)'==''">Debug</Config>
|
||||
<Config Condition="'$(Config)'==''">TESTINSIGHT</Config>
|
||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||
<TargetedPlatforms>1</TargetedPlatforms>
|
||||
<AppType>Console</AppType>
|
||||
@ -120,7 +120,6 @@
|
||||
<DCC_UsePackage>FireDACSqliteDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;IndyIPCommon;CloudService;DBXMSSQLDriver;FmxTeeUI;FireDACIBDriver;FireDACDBXDriver;inetdbxpress;webdsnap;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;vclactnband;bindengine;soaprtl;bindcompdbx;FMXTee;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;VclSmp;FireDACMSSQLDriver;FireDAC;VCLRESTComponents;Intraweb;DBXInformixDriver;DataSnapConnectors;FireDACDataSnapDriver;dsnapcon;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;FireDACMSAccDriver;DataSnapIndy10ServerTransport;dbexpress;IndyIPClient;$(DCC_UsePackage)</DCC_UsePackage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_1)'!=''">
|
||||
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
|
||||
<DCC_DebugDCUs>true</DCC_DebugDCUs>
|
||||
<DCC_Optimize>false</DCC_Optimize>
|
||||
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
|
||||
@ -157,7 +156,6 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_2)'!=''">
|
||||
<DCC_ExeOutput>.\bin</DCC_ExeOutput>
|
||||
<DCC_Define>TESTINSIGHT;$(DCC_Define)</DCC_Define>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
|
||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<TargetedPlatforms>129</TargetedPlatforms>
|
||||
<AppType>Console</AppType>
|
||||
<FrameworkType>None</FrameworkType>
|
||||
<ProjectVersion>19.2</ProjectVersion>
|
||||
<ProjectVersion>19.3</ProjectVersion>
|
||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
||||
@ -159,6 +159,12 @@
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="bin\customers.json" Configuration="CI" Class="File">
|
||||
<Platform Name="Linux64">
|
||||
<RemoteName>customers.json</RemoteName>
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libpcre.dylib" Class="DependencyModule">
|
||||
<Platform Name="iOSSimulator">
|
||||
<Overwrite>true</Overwrite>
|
||||
@ -180,12 +186,6 @@
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="bin\customers.json" Configuration="CI" Class="File">
|
||||
<Platform Name="Linux64">
|
||||
<RemoteName>customers.json</RemoteName>
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="TestServer" Configuration="CI" Class="ProjectOutput">
|
||||
<Platform Name="Linux64">
|
||||
<RemoteName>TestServer</RemoteName>
|
||||
|
Loading…
Reference in New Issue
Block a user