- Added default filtering for TMVCActiveRecord descendants (more info ASAP)

- Added partitioning for `TMVCActiveRecord descendants` (more info ASAP)

- After a big refactoring (*"I love to delete code" -- cit. Daniele Teti*), support a new SQLGenerator is just 2 (two) methods away!
This commit is contained in:
Daniele Teti 2021-11-21 19:27:06 +01:00
parent 3360dea516
commit 02de5b11ea
19 changed files with 309 additions and 585 deletions

View File

@ -459,6 +459,31 @@ The current beta release is named 3.2.2-nitrogen. If you want to stay on the-edg
- ⚡New! Added `TMVCActiveRecord.Merge<T>(CurrentListOfT, ChangesOfT)` to allow merge between two lists of `TMVCActiveRecord` descendants using `UnitOfWork` design pattern. Check the button "Merge" in demo "activerecord_showcase".
- ⚡New! Added default filtering for `TMVCActiveRecord descendants` (more info ASAP)
- ⚡New! Added partitioning for `TMVCActiveRecord descendants` (more info ASAP)
- ⚡Improved! After a big refactoring (*"I love to delete code" -- cit. Daniele Teti*), support a new SQLGenerator is just 2 (two) methods away! Just as example, this is the current version of `TMVCSQLGeneratorPostgreSQL`
```delphi
type
TMVCSQLGeneratorPostgreSQL = class(TMVCSQLGenerator)
protected
function GetCompilerClass: TRQLCompilerClass; override;
public
function CreateInsertSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function GetSequenceValueSQL(const PKFieldName: string;
const SequenceName: string;
const Step: Integer = 1): string; override;
end;
```
- ⚡New! Added new default parameter to `TMVCActiveRecord.RemoveDefaultConnection` and `TMVCActiveRecord.RemoveConnection` to avoid exceptions in case of not initialized connection.
- ⚡New! Added the new `MVCOwned` attribute which allows to auto-create nested objects in the deserialization phase. This will not change the current behavior, you ned to explocitly define a property (or a field) as `MVCOwned` to allows the serialization to create or destroy object for you.

View File

@ -23,6 +23,10 @@ procedure CreateMySQLPrivateConnDef(AIsPooled: boolean);
var
LParams: TStringList;
begin
{
docker run --detach --env MARIADB_USER=example-user --env MARIADB_PASSWORD=my_cool_secret --env MARIADB_ROOT_PASSWORD=root -p 3306:3306 mariadb:latest
}
LParams := TStringList.Create;
try
LParams.Add('Database=activerecorddb');
@ -31,7 +35,7 @@ begin
LParams.Add('User_Name=root');
LParams.Add('Password=root');
LParams.Add('TinyIntFormat=Boolean'); { it's the default }
LParams.Add('CharacterSet=utf8');
LParams.Add('CharacterSet=utf8mb4'); //not utf8!!
if AIsPooled then
begin
LParams.Add('Pooled=True');
@ -51,6 +55,10 @@ procedure CreateMSSQLServerPrivateConnDef(AIsPooled: boolean);
var
LParams: TStringList;
begin
{
docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=!SA_password!" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest
}
// [ACTIVERECORDB_SQLSERVER]
// Database=activerecorddb
// OSAuthent=Yes
@ -61,8 +69,10 @@ begin
LParams := TStringList.Create;
try
LParams.Add('Database=activerecorddb');
LParams.Add('OSAuthent=Yes');
LParams.Add('Server=DANIELETETI\SQLEXPRESS');
// LParams.Add('OSAuthent=Yes');
LParams.Add('User_Name=sa');
LParams.Add('Password=!SA_password!');
LParams.Add('Server=DANIELETETI');
// LParams.Add('TinyIntFormat=Boolean'); { it's the default }
if AIsPooled then
begin

View File

@ -215,7 +215,7 @@ begin
Log('Entity ' + TCustomer.ClassName + ' is mapped to table ' + lCustomer.TableName);
lCustomer.CompanyName := 'Google Inc.';
lCustomer.City := 'Montain View, CA';
lCustomer.Note := 'Μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος οὐλομένην';
lCustomer.Note := 'Μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος οὐλομένην 😁';
lCustomer.Insert;
lID := lCustomer.ID;
Log('Just inserted Customer ' + lID.ToString);

View File

@ -1,15 +1,15 @@
CREATE TABLE articles (
id integer IDENTITY(1, 1) ,
description varchar(100) NOT NULL,
description nvarchar(100) NOT NULL,
price integer NOT NULL,
CONSTRAINT articles_pkey PRIMARY KEY (id)
);
CREATE TABLE customers (
id integer IDENTITY(1, 1) ,
code varchar(20),
description varchar(200),
city varchar(200),
code nvarchar(20),
description nvarchar(200),
city nvarchar(200),
rating INTEGER,
NOTE nvarchar(max),
CONSTRAINT customers_pk PRIMARY KEY (id)
@ -17,18 +17,20 @@ CREATE TABLE customers (
CREATE TABLE customers_plain (
id integer NOT NULL,
code varchar(20),
description varchar(200),
city varchar(200),
code nvarchar(20),
description nvarchar(200),
city nvarchar(200),
note nvarchar(max),
rating smallint,
creation_time time,
creation_date date,
CONSTRAINT customers_plain_pk PRIMARY KEY (id)
);
CREATE TABLE customers_with_code (
code varchar(20) NOT null primary key,
description varchar(200),
city varchar(200),
code nvarchar(20) NOT null primary key,
description nvarchar(200),
city nvarchar(200),
NOTE nvarchar(max),
rating smallint
);
@ -40,7 +42,7 @@ CREATE TABLE order_details (
unit_price numeric(18,2) NOT NULL,
discount integer DEFAULT 0 NOT NULL ,
quantity integer NOT NULL,
description varchar(200) NOT NULL,
description nvarchar(200) NOT NULL,
total numeric(18,2) NOT NULL,
CONSTRAINT order_details_pkey PRIMARY KEY (id)
);
@ -56,10 +58,10 @@ CREATE TABLE orders (
CREATE TABLE people (
id integer IDENTITY(1, 1) ,
last_name varchar(100) NOT NULL,
first_name varchar(100) NOT NULL,
last_name nvarchar(100) NOT NULL,
first_name nvarchar(100) NOT NULL,
dob date NOT NULL,
full_name varchar(80) NOT NULL,
full_name nvarchar(80) NOT NULL,
is_male bit DEFAULT 1 NOT NULL,
note nvarchar(max),
photo VARBINARY(MAX),
@ -68,11 +70,27 @@ CREATE TABLE people (
create table phones (
id integer IDENTITY(1, 1) ,
phone_number varchar(200) not null,
number_type varchar(200) not null,
phone_number nvarchar(200) not null,
number_type nvarchar(200) not null,
dob date,
id_person integer not null references people(id)
);
ALTER TABLE orders ADD CONSTRAINT orders_customers_fk FOREIGN KEY (id_customer) REFERENCES customers(id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE order_details ADD CONSTRAINT order_details_orders_fk FOREIGN KEY (id_order) REFERENCES orders(id) ON DELETE CASCADE ON UPDATE CASCADE;
CREATE TABLE nullables_test (
f_int2 smallint,
f_int8 bigint,
f_int4 integer,
f_string nvarchar(200),
f_bool bit,
f_date date,
f_time time,
f_datetime datetime,
f_float4 real,
f_float8 double precision,
f_currency numeric(18,4),
f_blob varchar(max)
);

View File

@ -1,5 +1,5 @@
CREATE TABLE articles (
id integer GENERATED BY DEFAULT AS IDENTITY,
id integer NOT NULL AUTO_INCREMENT,
description varchar(100) NOT NULL,
price integer NOT NULL,
CONSTRAINT articles_pkey PRIMARY KEY (id)
@ -23,12 +23,12 @@ CREATE TABLE nullables_test (
CREATE TABLE customers (
id integer GENERATED BY DEFAULT AS IDENTITY,
code varchar(20) NOT NULL,
id integer NOT NULL AUTO_INCREMENT,
code varchar(20) NULL,
description varchar(200),
city varchar(200),
rating INTEGER NULL,
note text DEFAULT NULL,
note text character set "utf8mb4" collate "utf8mb4_unicode_ci" DEFAULT NULL,
CONSTRAINT customers_pk PRIMARY KEY (id)
);
@ -54,7 +54,7 @@ CREATE TABLE customers_with_code (
);
CREATE TABLE order_details (
id integer GENERATED BY DEFAULT AS IDENTITY,
id integer NOT NULL AUTO_INCREMENT,
id_order integer NOT NULL,
id_article integer NOT NULL,
unit_price numeric(18,2) NOT NULL,
@ -66,7 +66,7 @@ CREATE TABLE order_details (
);
CREATE TABLE orders (
id integer GENERATED BY DEFAULT AS IDENTITY,
id integer NOT NULL AUTO_INCREMENT,
id_customer integer NOT NULL,
order_date date NOT NULL,
total numeric(18,4) NOT NULL,
@ -75,19 +75,19 @@ CREATE TABLE orders (
CREATE TABLE people (
id integer GENERATED BY DEFAULT AS IDENTITY,
id integer NOT NULL AUTO_INCREMENT,
last_name varchar(100) NOT NULL,
first_name varchar(100) NOT NULL,
dob date NOT NULL,
full_name varchar(80) NOT NULL,
is_male BOOLEAN DEFAULT TRUE NOT NULL,
note blob sub_type TEXT,
photo blob sub_type binary,
note TEXT,
photo BLOB,
CONSTRAINT people_pkey PRIMARY KEY (id)
);
create table phones (
id integer GENERATED BY DEFAULT AS IDENTITY,
id integer NOT NULL auto_increment primary key,
phone_number varchar(200) not null,
number_type varchar(200) not null,
dob date,

View File

@ -554,29 +554,32 @@ type
function HasSequences: Boolean; virtual;
function HasReturning: Boolean; virtual;
// end-capabilities
// abstract SQL generator methods
function CreateSQLWhereByRQL(const RQL: string; const Mapping: TMVCFieldsMapping;
const UseArtificialLimit: Boolean = True; const UseFilterOnly: Boolean = false;
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; virtual; abstract;
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string;
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;
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual;
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;
// virtual methods with default implementation
function CreateSelectByPKSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual;
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;
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual;
function CreateDeleteAllSQL(const TableName: string): string; virtual;
function CreateSelectCount(const TableName: string): string; virtual;
function CreateUpdateSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual;
function GetSequenceValueSQL(const PKFieldName: string; const SequenceName: string;
const Step: Integer = 1)
: string; virtual;
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.
@ -3062,6 +3065,83 @@ begin
Result := fCompiler.GetParamNameForSQL(FieldName);
end;
function TMVCSQLGenerator.CreateDeleteAllSQL(const TableName: string): string;
begin
Result := 'DELETE FROM ' + GetTableNameForSQL(TableName);
end;
function TMVCSQLGenerator.CreateDeleteSQL(const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := CreateDeleteAllSQL(TableName) + ' WHERE ' + GetFieldNameForSQL(PKFieldName) + '=:' +
GetParamNameForSQL(PKFieldName);
end;
function TMVCSQLGenerator.CreateSelectByPKSQL(const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
if PKFieldName.IsEmpty then
begin
raise EMVCActiveRecord.Create('No primary key provided. [HINT] Define a primary key field adding foPrimaryKey in field options.');
end;
Result := CreateSelectSQL(TableName, Map, PKFieldName, PKOptions) + ' WHERE ' +
GetFieldNameForSQL(PKFieldName) + '= :' + GetParamNameForSQL(PKFieldName) +
GetDefaultSQLFilter(False, True);
end;
function TMVCSQLGenerator.CreateSelectCount(const TableName: string): string;
begin
{do not add SQLFilter here!}
Result := 'SELECT count(*) FROM ' + GetTableNameForSQL(TableName);
end;
function TMVCSQLGenerator.CreateSelectSQL(const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := 'SELECT ' + TableFieldsDelimited(Map, PKFieldName, ',') + ' FROM ' + GetTableNameForSQL(TableName);
end;
function TMVCSQLGenerator.CreateSQLWhereByRQL(const RQL: string;
const Mapping: TMVCFieldsMapping; const UseArtificialLimit,
UseFilterOnly: Boolean; const MaxRecordCount: Int32): string;
begin
GetRQLParser.Execute(MergeDefaultRQLFilter(RQL), Result, GetCompiler, UseArtificialLimit, UseFilterOnly, MaxRecordCount);
end;
function TMVCSQLGenerator.CreateUpdateSQL(const TableName: string;
const Map: TFieldsMap; 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
begin
if lPair.Value.Writeable then
begin
Result := Result + GetFieldNameForSQL(lPair.Value.FieldName) + ' = :' +
GetParamNameForSQL(lPair.Value.FieldName) + ',';
end;
end;
{partition}
for I := 0 to fPartitionInfo.FieldNames.Count - 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
Result := Result + ' where ' + GetFieldNameForSQL(PKFieldName) + '= :' + GetParamNameForSQL(PKFieldName);
end;
end;
destructor TMVCSQLGenerator.Destroy;
begin
fCompiler.Free;

View File

@ -136,7 +136,7 @@ begin
else
lValue := aRQLFIlter.OpRight;
lDBFieldName := GetDatabaseFieldName(aRQLFIlter.OpLeft);
lDBFieldName := GetDatabaseFieldName(aRQLFIlter.OpLeft, True);
case aRQLFIlter.Token of
tkEq:
@ -262,7 +262,7 @@ begin
begin
if I > 0 then
Result := Result + ',';
Result := Result + ' ' + GetDatabaseFieldName(aRQLSort.Fields[I]);
Result := Result + ' ' + GetDatabaseFieldName(aRQLSort.Fields[I], True);
if aRQLSort.Signs[I] = '+' then
Result := Result + ' ASC'
else

View File

@ -101,7 +101,7 @@ begin
else
lValue := aRQLFIlter.OpRight;
lDBFieldName := GetDatabaseFieldName(aRQLFIlter.OpLeft);
lDBFieldName := GetDatabaseFieldName(aRQLFIlter.OpLeft, True);
case aRQLFIlter.Token of
tkEq:
@ -227,7 +227,7 @@ begin
begin
if I > 0 then
Result := Result + ',';
Result := Result + ' ' + GetDatabaseFieldName(aRQLSort.Fields[I]);
Result := Result + ' ' + GetDatabaseFieldName(aRQLSort.Fields[I], True);
if aRQLSort.Signs[I] = '+' then
Result := Result + ' ASC'
else
@ -245,8 +245,8 @@ procedure TRQLMSSQLCompiler.AST2SQL(const aRQLAST: TRQLAbstractSyntaxTree;
var
lBuff: TStringBuilder;
lItem: TRQLCustom;
LFoundSort: Boolean;
LitemSort: TRQLSort;
lFoundSort: Boolean;
lItemSort: TRQLSort;
begin
inherited;
@ -264,16 +264,19 @@ begin
if (lItem is TRQLLimit) and (not LFoundSort) then
begin
LitemSort := TRQLSort.Create;
LitemSort.Add('+', FMapping[0].InstanceFieldName);
lBuff.Append(RQLCustom2SQL(LitemSort));
lItemSort := TRQLSort.Create;
try
lItemSort.Add('+', FMapping[0].InstanceFieldName);
lBuff.Append(RQLCustom2SQL(LitemSort));
finally
lItemSort.Free;
end;
end;
lBuff.Append(RQLCustom2SQL(lItem));
if (lItem is TRQLSort) then
LFoundSort := True;
end;
aSQL := lBuff.ToString;
finally

View File

@ -92,7 +92,7 @@ begin
else
lValue := aRQLFIlter.OpRight;
lDBFieldName := GetDatabaseFieldName(aRQLFIlter.OpLeft);
lDBFieldName := GetDatabaseFieldName(aRQLFIlter.OpLeft, True);
case aRQLFIlter.Token of
tkEq:
@ -218,7 +218,7 @@ begin
begin
if I > 0 then
Result := Result + ',';
Result := Result + ' ' + GetDatabaseFieldName(aRQLSort.Fields[I]);
Result := Result + ' ' + GetDatabaseFieldName(aRQLSort.Fields[I], True);
if aRQLSort.Signs[I] = '+' then
Result := Result + ' ASC'
else

View File

@ -219,7 +219,7 @@ begin
begin
if I > 0 then
Result := Result + ',';
Result := Result + ' ' + GetFieldNameForSQL(GetDatabaseFieldName(aRQLSort.Fields[I]));
Result := Result + ' ' + GetFieldNameForSQL(GetDatabaseFieldName(aRQLSort.Fields[I], True));
if aRQLSort.Signs[I] = '+' then
Result := Result + ' ASC'
else

View File

@ -87,7 +87,7 @@ begin
else
lValue := aRQLFIlter.OpRight;
lDBFieldName := GetDatabaseFieldName(aRQLFIlter.OpLeft);
lDBFieldName := GetDatabaseFieldName(aRQLFIlter.OpLeft, True);
case aRQLFIlter.Token of
tkEq:
@ -213,7 +213,7 @@ begin
begin
if I > 0 then
Result := Result + ',';
Result := Result + ' ' + GetDatabaseFieldName(aRQLSort.Fields[I]);
Result := Result + ' ' + GetDatabaseFieldName(aRQLSort.Fields[I], True);
if aRQLSort.Signs[I] = '+' then
Result := Result + ' ASC'
else

View File

@ -41,41 +41,14 @@ type
protected
function GetCompilerClass: TRQLCompilerClass; override;
public
function GetSequenceValueSQL(
const PKFieldName: string; const SequenceName: string; const Step: Integer): string; override;
function CreateSelectSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateInsertSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateUpdateSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateDeleteSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateDeleteAllSQL(
const TableName: string): string; override;
function CreateSelectByPKSQL(
const TableName: string;
const Map: TFieldsMap; 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: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
function CreateSelectCount(
const TableName: string): string; override;
function GetSequenceValueSQL(const PKFieldName: string;
const SequenceName: string;
const Step: Integer = 1): string; override;
end;
implementation
@ -90,6 +63,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));
@ -100,8 +74,17 @@ begin
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
if lKeyValue.Value.Writeable then
begin
lSB.Append(GetFieldNameForSQL(lKeyValue.Value.FieldName) + ',');
@ -114,6 +97,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
@ -135,65 +126,6 @@ begin
end;
end;
function TMVCSQLGeneratorFirebird.CreateSelectByPKSQL(
const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := CreateSelectSQL(TableName, Map, PKFieldName, PKOptions) + ' WHERE ' +
GetFieldNameForSQL(PKFieldName) + '= :' + GetParamNameForSQL(PKFieldName); // IntToStr(PrimaryKeyValue);
end;
function TMVCSQLGeneratorFirebird.CreateSelectCount(
const TableName: string): string;
begin
Result := 'SELECT count(*) FROM ' + GetTableNameForSQL(TableName);
end;
function TMVCSQLGeneratorFirebird.CreateSelectSQL(const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := 'SELECT ' + TableFieldsDelimited(Map, PKFieldName, ',') + ' FROM ' + GetTableNameForSQL(TableName);
end;
function TMVCSQLGeneratorFirebird.CreateSQLWhereByRQL(
const RQL: string; const Mapping: TMVCFieldsMapping;
const UseArtificialLimit: Boolean = True;
const UseFilterOnly: Boolean = False;
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string;
var
lFirebirdCompiler: TRQLFirebirdCompiler;
begin
lFirebirdCompiler := TRQLFirebirdCompiler.Create(Mapping);
try
GetRQLParser.Execute(RQL, Result, lFirebirdCompiler,
UseArtificialLimit, UseFilterOnly, MaxRecordCount);
finally
lFirebirdCompiler.Free;
end;
end;
function TMVCSQLGeneratorFirebird.CreateUpdateSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
var
lKeyValue: TPair<TRttiField, TFieldInfo>;
begin
Result := 'UPDATE ' + GetTableNameForSQL(TableName) + ' SET ';
for lKeyValue in Map do
begin
if lKeyValue.Value.Writeable then
begin
Result := Result + GetFieldNameForSQL(lKeyValue.Value.FieldName) + ' = :' + GetParamNameForSQL(lKeyValue.Value.FieldName) + ',';
end;
end;
Result[Length(Result)] := ' ';
if not PKFieldName.IsEmpty then
begin
Result := Result + ' where ' + GetFieldNameForSQL(PKFieldName) + '= :' + GetParamNameForSQL(PKFieldName);
end;
end;
function TMVCSQLGeneratorFirebird.GetCompilerClass: TRQLCompilerClass;
begin
Result := TRQLFirebirdCompiler;
@ -205,18 +137,6 @@ begin
Result := Format('select gen_id(%s,%d) %s from rdb$database', [GetFieldNameForSQL(SequenceName), Step, GetFieldNameForSQL(PKFieldName)]);
end;
function TMVCSQLGeneratorFirebird.CreateDeleteAllSQL(
const TableName: string): string;
begin
Result := 'DELETE FROM ' + GetTableNameForSQL(TableName);
end;
function TMVCSQLGeneratorFirebird.CreateDeleteSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := CreateDeleteAllSQL(TableName) + ' WHERE ' + GetFieldNameForSQL(PKFieldName) + '=:' + GetParamNameForSQL(PKFieldName);
end;
initialization
TMVCSQLGeneratorRegistry.Instance.RegisterSQLGenerator('firebird', TMVCSQLGeneratorFirebird);

View File

@ -40,39 +40,11 @@ type
protected
function GetCompilerClass: TRQLCompilerClass; override;
public
function CreateSelectSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateInsertSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateUpdateSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateDeleteSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateSelectByPKSQL(
const TableName: string;
const Map: TFieldsMap; 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: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
function CreateSelectCount(
const TableName: string): string; override;
function CreateDeleteAllSQL(
const TableName: string): string; override;
end;
implementation
@ -87,6 +59,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));
@ -97,6 +70,14 @@ begin
begin
lSB.Append(PKFieldName + ',');
end;
{partition}
for lFieldName in fPartitionInfo.FieldNames do
begin
lSB.Append(GetFieldNameForSQL(lFieldName) + ',');
end;
{end-partition}
for lKeyValue in Map do
begin
if lKeyValue.Value.Writeable then
@ -110,6 +91,14 @@ begin
begin
lSB.Append(':' + 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
@ -130,84 +119,11 @@ begin
end;
end;
function TMVCSQLGeneratorMSSQL.CreateSelectByPKSQL(
const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := CreateSelectSQL(TableName, Map, PKFieldName, PKOptions) + ' WHERE ' +
PKFieldName + '= :' + PKFieldName; // IntToStr(PrimaryKeyValue);
end;
function TMVCSQLGeneratorMSSQL.CreateSelectCount(
const TableName: string): string;
begin
Result := 'SELECT count(*) FROM ' + TableName;
end;
function TMVCSQLGeneratorMSSQL.CreateSelectSQL(const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := 'SELECT ' + TableFieldsDelimited(Map, PKFieldName, ',') + ' FROM ' + TableName;
end;
function TMVCSQLGeneratorMSSQL.CreateSQLWhereByRQL(
const RQL: string; const Mapping: TMVCFieldsMapping;
const UseArtificialLimit: Boolean = True;
const UseFilterOnly: Boolean = False;
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string;
var
lMSSQLCompiler: TRQLMSSQLCompiler;
begin
lMSSQLCompiler := TRQLMSSQLCompiler.Create(Mapping);
try
GetRQLParser.Execute(RQL, Result, lMSSQLCompiler, UseArtificialLimit, UseFilterOnly, MaxRecordCount);
finally
lMSSQLCompiler.Free;
end;
end;
function TMVCSQLGeneratorMSSQL.CreateUpdateSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
var
lKeyValue: TPair<TRttiField, TFieldInfo>;
begin
Result := 'UPDATE ' + TableName + ' SET ';
for lKeyValue in Map do
begin
if lKeyValue.Value.Writeable then
begin
Result := Result + lKeyValue.Value.FieldName + ' = :' + lKeyValue.Value.FieldName + ',';
end;
end;
Result[Length(Result)] := ' ';
if not PKFieldName.IsEmpty then
begin
Result := Result + ' where ' + PKFieldName + '= :' + PKFieldName;
end;
end;
function TMVCSQLGeneratorMSSQL.GetCompilerClass: TRQLCompilerClass;
begin
Result := TRQLMSSQLCompiler;
end;
function TMVCSQLGeneratorMSSQL.CreateDeleteAllSQL(
const TableName: string): string;
begin
Result := 'DELETE FROM ' + TableName;
end;
function TMVCSQLGeneratorMSSQL.CreateDeleteSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := 'DELETE FROM ' + TableName + ' WHERE ' + PKFieldName + '=:' + PKFieldName;
end;
initialization
TMVCSQLGeneratorRegistry.Instance.RegisterSQLGenerator('mssql', TMVCSQLGeneratorMSSQL);

View File

@ -40,39 +40,11 @@ type
protected
function GetCompilerClass: TRQLCompilerClass; override;
public
function CreateSelectSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateInsertSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateUpdateSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateDeleteSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateDeleteAllSQL(
const TableName: string): string; override;
function CreateSelectByPKSQL(
const TableName: string;
const Map: TFieldsMap; 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: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
function CreateSelectCount(
const TableName: string): string; override;
end;
implementation
@ -87,6 +59,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));
@ -97,6 +70,14 @@ begin
begin
lSB.Append(PKFieldName + ',');
end;
{partition}
for lFieldName in fPartitionInfo.FieldNames do
begin
lSB.Append(GetFieldNameForSQL(lFieldName) + ',');
end;
{end-partition}
for lKeyValue in Map do
begin
if lKeyValue.Value.Writeable then
@ -111,6 +92,14 @@ begin
begin
lSB.Append(':' + 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
@ -131,81 +120,11 @@ begin
end;
end;
function TMVCSQLGeneratorMySQL.CreateSelectByPKSQL(
const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := CreateSelectSQL(TableName, Map, PKFieldName, PKOptions) + ' WHERE ' +
PKFieldName + '= :' + PKFieldName; // IntToStr(PrimaryKeyValue);
end;
function TMVCSQLGeneratorMySQL.CreateSelectCount(
const TableName: string): string;
begin
Result := 'SELECT count(*) FROM ' + TableName;
end;
function TMVCSQLGeneratorMySQL.CreateSelectSQL(const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := 'SELECT ' + TableFieldsDelimited(Map, PKFieldName, ',') + ' FROM ' + TableName;
end;
function TMVCSQLGeneratorMySQL.CreateSQLWhereByRQL(
const RQL: string; const Mapping: TMVCFieldsMapping;
const UseArtificialLimit: Boolean = True;
const UseFilterOnly: Boolean = False;
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string;
var
lMySQLCompiler: TRQLMySQLCompiler;
begin
lMySQLCompiler := TRQLMySQLCompiler.Create(Mapping);
try
GetRQLParser.Execute(RQL, Result, lMySQLCompiler, UseArtificialLimit, UseFilterOnly, MaxRecordCount);
finally
lMySQLCompiler.Free;
end;
end;
function TMVCSQLGeneratorMySQL.CreateUpdateSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
var
lKeyValue: TPair<TRttiField, TFieldInfo>;
begin
Result := 'UPDATE ' + TableName + ' SET ';
for lKeyValue in Map do
begin
if lKeyValue.Value.Writeable then
begin
Result := Result + lKeyValue.Value.FieldName + ' = :' + lKeyValue.Value.FieldName + ',';
end;
end;
Result[Length(Result)] := ' ';
if not PKFieldName.IsEmpty then
begin
Result := Result + ' where ' + PKFieldName + '= :' + PKFieldName;
end;
end;
function TMVCSQLGeneratorMySQL.GetCompilerClass: TRQLCompilerClass;
begin
Result := TRQLMySQLCompiler;
end;
function TMVCSQLGeneratorMySQL.CreateDeleteAllSQL(
const TableName: string): string;
begin
Result := 'DELETE FROM ' + TableName;
end;
function TMVCSQLGeneratorMySQL.CreateDeleteSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := CreateDeleteAllSQL(TableName) + ' WHERE ' + PKFieldName + '=:' + PKFieldName;
end;
initialization
TMVCSQLGeneratorRegistry.Instance.RegisterSQLGenerator('mysql', TMVCSQLGeneratorMySQL);

View File

@ -29,8 +29,6 @@ interface
uses
System.Rtti,
System.Generics.Collections,
FireDAC.Phys.FB,
FireDAC.Phys.FBDef,
MVCFramework.ActiveRecord,
MVCFramework.Commons,
MVCFramework.RQL.Parser;
@ -40,40 +38,11 @@ type
protected
function GetCompilerClass: TRQLCompilerClass; override;
public
function CreateSelectSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateInsertSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateUpdateSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateDeleteSQL(
const TableName: string;
const Map: TFieldsMap;
const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateDeleteAllSQL(
const TableName: string): string; override;
function CreateSelectByPKSQL(
const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateSQLWhereByRQL(
const RQL: string;
const Mapping: TMVCFieldsMapping;
const UseArtificialLimit: Boolean;
const UseFilterOnly: Boolean;
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
function CreateSelectCount(
const TableName: string): string; override;
function GetSequenceValueSQL(const PKFieldName: string;
const SequenceName: string;
const Step: Integer = 1): string; override;
@ -159,82 +128,6 @@ begin
end;
end;
function TMVCSQLGeneratorPostgreSQL.CreateSelectByPKSQL(
const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
if PKFieldName.IsEmpty then
begin
raise EMVCActiveRecord.Create('No primary key provided. [HINT] Define a primary key field adding foPrimaryKey in field options.');
end;
Result := CreateSelectSQL(TableName, Map, PKFieldName, PKOptions) + ' WHERE ' +
GetFieldNameForSQL(PKFieldName) + '= :' + GetParamNameForSQL(PKFieldName) +
GetDefaultSQLFilter(False, True); // IntToStr(PrimaryKeyValue);
end;
function TMVCSQLGeneratorPostgreSQL.CreateSelectCount(
const TableName: string): string;
begin
{do not add SQLFilter here!}
Result := 'SELECT count(*) FROM ' + GetTableNameForSQL(TableName); // + GetDefaultSQLFilter(True);
end;
function TMVCSQLGeneratorPostgreSQL.CreateSelectSQL(const TableName: string;
const Map: TFieldsMap; const PKFieldName: string;
const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := 'SELECT ' + TableFieldsDelimited(Map, PKFieldName, ',') + ' FROM ' + GetTableNameForSQL(TableName);
end;
function TMVCSQLGeneratorPostgreSQL.CreateSQLWhereByRQL(
const RQL: string;
const Mapping: TMVCFieldsMapping;
const UseArtificialLimit: Boolean;
const UseFilterOnly: Boolean;
const MaxRecordCount: Int32): string;
var
lPostgreSQLCompiler: TRQLPostgreSQLCompiler;
begin
lPostgreSQLCompiler := TRQLPostgreSQLCompiler.Create(Mapping);
try
GetRQLParser.Execute(MergeDefaultRQLFilter(RQL), Result, lPostgreSQLCompiler,
UseArtificialLimit, UseFilterOnly, MaxRecordCount);
finally
lPostgreSQLCompiler.Free;
end;
end;
function TMVCSQLGeneratorPostgreSQL.CreateUpdateSQL(const TableName: string; const Map: TFieldsMap;
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
begin
if lPair.Value.Writeable then
begin
Result := Result + GetFieldNameForSQL(lPair.Value.FieldName) + ' = :' +
GetParamNameForSQL(lPair.Value.FieldName) + ',';
end;
end;
{partition}
for I := 0 to fPartitionInfo.FieldNames.Count - 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
Result := Result + ' where ' + GetFieldNameForSQL(PKFieldName) + '= :' + GetParamNameForSQL(PKFieldName);
end;
end;
function TMVCSQLGeneratorPostgreSQL.GetCompilerClass: TRQLCompilerClass;
begin
Result := TRQLPostgreSQLCompiler;
@ -246,19 +139,6 @@ begin
Result := Format('SELECT nextval(''%s'') %s', [SequenceName, GetFieldNameForSQL(PKFieldName)]);
end;
function TMVCSQLGeneratorPostgreSQL.CreateDeleteAllSQL(
const TableName: string): string;
begin
Result := 'DELETE FROM ' + GetTableNameForSQL(TableName); // + GetDefaultSQLFilter(True);
end;
function TMVCSQLGeneratorPostgreSQL.CreateDeleteSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := CreateDeleteAllSQL(TableName) + ' WHERE ' + GetFieldNameForSQL(PKFieldName) + '=:' +
GetParamNameForSQL(PKFieldName);
end;
initialization
TMVCSQLGeneratorRegistry.Instance.RegisterSQLGenerator('postgresql', TMVCSQLGeneratorPostgreSQL);

View File

@ -38,21 +38,8 @@ type
protected
function GetCompilerClass: TRQLCompilerClass; override;
public
function CreateSelectSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateInsertSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateUpdateSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateDeleteSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string; override;
function CreateDeleteAllSQL(const TableName: string): string; override;
function CreateSelectByPKSQL(const TableName: string; const Map: TFieldsMap;
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: Int32 = TMVCConstants.MAX_RECORD_COUNT): string; override;
function CreateSelectCount(const TableName: string): string; override;
function HasSequences: Boolean; override;
end;
@ -68,6 +55,7 @@ var
lKeyValue: TPair<TRttiField, TFieldInfo>;
lSB: TStringBuilder;
lPKInInsert: Boolean;
lFieldName: String;
begin
lPKInInsert := (not PKFieldName.IsEmpty) and
(not(TMVCActiveRecordFieldOption.foAutoGenerated in PKOptions));
@ -79,6 +67,14 @@ begin
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 lKeyValue.Value.Writeable then
@ -92,6 +88,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
@ -112,64 +116,6 @@ begin
end;
end;
function TMVCSQLGeneratorSQLite.CreateSelectByPKSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := CreateSelectSQL(TableName, Map, PKFieldName, PKOptions) + ' WHERE ' +
GetFieldNameForSQL(PKFieldName) + '= :' + GetParamNameForSQL(PKFieldName);
// IntToStr(PrimaryKeyValue);
end;
function TMVCSQLGeneratorSQLite.CreateSelectCount(const TableName: string): string;
begin
Result := 'SELECT count(*) FROM ' + GetTableNameForSQL(TableName);
end;
function TMVCSQLGeneratorSQLite.CreateSelectSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := 'SELECT ' + TableFieldsDelimited(Map, PKFieldName, ',') + ' FROM ' +
GetTableNameForSQL(TableName);
end;
function TMVCSQLGeneratorSQLite.CreateSQLWhereByRQL(const RQL: string;
const Mapping: TMVCFieldsMapping; const UseArtificialLimit: Boolean = True;
const UseFilterOnly: Boolean = False;
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string;
var
lSQLiteCompiler: TRQLSQLiteCompiler;
begin
lSQLiteCompiler := TRQLSQLiteCompiler.Create(Mapping);
try
GetRQLParser.Execute(RQL, Result, lSQLiteCompiler,
UseArtificialLimit, UseFilterOnly, MaxRecordCount);
finally
lSQLiteCompiler.Free;
end;
end;
function TMVCSQLGeneratorSQLite.CreateUpdateSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
var
lKeyValue: TPair<TRttiField, TFieldInfo>;
begin
Result := 'UPDATE ' + GetTableNameForSQL(TableName) + ' SET ';
for lKeyValue in Map do
begin
if lKeyValue.Value.Writeable then
begin
Result := Result + GetFieldNameForSQL(lKeyValue.Value.FieldName) + ' = :' +
GetParamNameForSQL(lKeyValue.Value.FieldName) + ',';
end;
end;
Result[Length(Result)] := ' ';
if not PKFieldName.IsEmpty then
begin
Result := Result + ' where ' + GetFieldNameForSQL(PKFieldName) + '= :' +
GetParamNameForSQL(PKFieldName);
end;
end;
function TMVCSQLGeneratorSQLite.GetCompilerClass: TRQLCompilerClass;
begin
Result := TRQLSQLiteCompiler;
@ -180,18 +126,6 @@ begin
Result := False;
end;
function TMVCSQLGeneratorSQLite.CreateDeleteAllSQL(const TableName: string): string;
begin
Result := 'DELETE FROM ' + GetTableNameForSQL(TableName);
end;
function TMVCSQLGeneratorSQLite.CreateDeleteSQL(const TableName: string; const Map: TFieldsMap;
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
begin
Result := CreateDeleteAllSQL(TableName) + ' WHERE ' + GetFieldNameForSQL(PKFieldName) + '=:' +
GetParamNameForSQL(PKFieldName);
end;
initialization
TMVCSQLGeneratorRegistry.Instance.RegisterSQLGenerator('sqlite', TMVCSQLGeneratorSQLite);

View File

@ -1203,7 +1203,7 @@ procedure TTestActiveRecordBase.TestPartitioningCRUD;
var
lRMCustomer: TRomeBasedCustomer;
lNYCustomer: TNewYorkBasedCustomer;
lIDRome, lIDNewYork: Integer;
lIDRome: Integer;
begin
Assert.AreEqual(Int64(0), TMVCActiveRecord.Count<TRomeBasedCustomer>());
lRMCustomer := TRomeBasedCustomer.Create;
@ -1221,7 +1221,6 @@ begin
lNYCustomer.CompanyName := 'bit Time Professionals NY';
lRMCustomer.Note := 'note2';
lNYCustomer.Insert;
lIDNewYork := lNYCustomer.ID;
finally
lNYCustomer.Free;
end;
@ -1263,10 +1262,10 @@ end;
procedure TTestActiveRecordBase.TestPartitioningDelete;
begin
TMVCActiveRecord.DeleteAll(TCustomer);
var lID1 := CreateACustomer('Daniele', 'Rome', 1);
var lID2 := CreateACustomer('Jack', 'Rome', 2);
var lID3 := CreateACustomer('Bruce', 'Tokyo', 3);
var lID4 := CreateACustomer('John', 'New York', 4);
CreateACustomer('Daniele', 'Rome', 1);
CreateACustomer('Jack', 'Rome', 2);
CreateACustomer('Bruce', 'Tokyo', 3);
CreateACustomer('John', 'New York', 4);
var lID5 := CreateACustomer('Scott', 'New York', 5);
var lGoodNewYorkCustomer := TMVCActiveRecord.GetByPK<TNewYorkBasedGoodCustomer>(lID5);
@ -1286,11 +1285,11 @@ end;
procedure TTestActiveRecordBase.TestPartitioningDeleteByRQL;
begin
TMVCActiveRecord.DeleteAll(TCustomer);
var lID1 := CreateACustomer('Daniele', 'Rome', 1);
var lID2 := CreateACustomer('Jack', 'Rome', 2);
var lID3 := CreateACustomer('Bruce', 'Tokyo', 3);
var lID4 := CreateACustomer('John', 'New York', 4);
var lID5 := CreateACustomer('Scott', 'New York', 5);
CreateACustomer('Daniele', 'Rome', 1);
CreateACustomer('Jack', 'Rome', 2);
CreateACustomer('Bruce', 'Tokyo', 3);
CreateACustomer('John', 'New York', 4);
CreateACustomer('Scott', 'New York', 5);
Assert.AreEqual(Int64(2), TMVCActiveRecord.Count(TNewYorkBasedCustomer));
TMVCActiveRecord.DeleteRQL(TNewYorkBasedCustomer, 'eq(CompanyName,"John")');
@ -1304,9 +1303,9 @@ procedure TTestActiveRecordBase.TestPartitioningGetByPK;
begin
TMVCActiveRecord.DeleteAll(TCustomer);
var lID1 := CreateACustomer('Daniele', 'Rome', 1);
var lID2 := CreateACustomer('Jack', 'Rome', 2);
var lID3 := CreateACustomer('Bruce', 'Tokyo', 3);
var lID4 := CreateACustomer('John', 'New York', 4);
CreateACustomer('Jack', 'Rome', 2);
CreateACustomer('Bruce', 'Tokyo', 3);
CreateACustomer('John', 'New York', 4);
var lID5 := CreateACustomer('Scott', 'New York', 5);
var lRomeCustomer := TMVCActiveRecord.GetByPK<TRomeBasedCustomer>(lID1);
@ -1380,10 +1379,6 @@ begin
end;
procedure TTestActiveRecordBase.TestPartitioningSelectByWhere;
var
lRMCustomer: TRomeBasedCustomer;
lNYCustomer: TNewYorkBasedCustomer;
lIDRome, lIDNewYork: Integer;
begin
Assert.AreEqual(Int64(0), TMVCActiveRecord.Count<TRomeBasedCustomer>());
CreateACustomer('Daniele','Rome',1);

View File

@ -54,7 +54,19 @@ uses
MVCFramework.Commons in '..\..\..\sources\MVCFramework.Commons.pas',
MVCFramework.Serializer.JsonDataObjects.CustomTypes in '..\..\..\sources\MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas',
MVCFramework.SQLGenerators.Firebird in '..\..\..\sources\MVCFramework.SQLGenerators.Firebird.pas',
MVCFramework.Utils in '..\..\..\sources\MVCFramework.Utils.pas';
MVCFramework.Utils in '..\..\..\sources\MVCFramework.Utils.pas',
MVCFramework.SQLGenerators.Interbase in '..\..\..\sources\MVCFramework.SQLGenerators.Interbase.pas',
MVCFramework.SQLGenerators.MSSQL in '..\..\..\sources\MVCFramework.SQLGenerators.MSSQL.pas',
MVCFramework.SQLGenerators.MySQL in '..\..\..\sources\MVCFramework.SQLGenerators.MySQL.pas',
MVCFramework.SQLGenerators.PostgreSQL in '..\..\..\sources\MVCFramework.SQLGenerators.PostgreSQL.pas',
MVCFramework.SQLGenerators.Sqlite in '..\..\..\sources\MVCFramework.SQLGenerators.Sqlite.pas',
MVCFramework.RQL.AST2FirebirdSQL in '..\..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas',
MVCFramework.RQL.AST2InterbaseSQL in '..\..\..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas',
MVCFramework.RQL.AST2MSSQL in '..\..\..\sources\MVCFramework.RQL.AST2MSSQL.pas',
MVCFramework.RQL.AST2MySQL in '..\..\..\sources\MVCFramework.RQL.AST2MySQL.pas',
MVCFramework.RQL.AST2PostgreSQL in '..\..\..\sources\MVCFramework.RQL.AST2PostgreSQL.pas',
MVCFramework.RQL.AST2SQLite in '..\..\..\sources\MVCFramework.RQL.AST2SQLite.pas',
MVCFramework.RQL.Parser in '..\..\..\sources\MVCFramework.RQL.Parser.pas';
{$R *.RES}

View File

@ -219,6 +219,18 @@
<DCCReference Include="..\..\..\sources\MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.SQLGenerators.Firebird.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.Utils.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.SQLGenerators.Interbase.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.SQLGenerators.MSSQL.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.SQLGenerators.MySQL.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.SQLGenerators.PostgreSQL.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.SQLGenerators.Sqlite.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.RQL.AST2MSSQL.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.RQL.AST2MySQL.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.RQL.AST2PostgreSQL.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.RQL.AST2SQLite.pas"/>
<DCCReference Include="..\..\..\sources\MVCFramework.RQL.Parser.pas"/>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
@ -309,7 +321,7 @@
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">
<DeployFile LocalName="bin\DMVCFrameworkTests.exe" Configuration="TESTINSIGHT" Class="ProjectOutput">
<DeployFile LocalName="Win32\Debug\DMVCFrameworkTests.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>DMVCFrameworkTests.exe</RemoteName>
<Overwrite>true</Overwrite>
@ -333,13 +345,13 @@
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\iossim32\libcgunwind.1.0.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.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">
<DeployFile LocalName="$(BDS)\Redist\iossim32\libcgunwind.1.0.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
@ -361,7 +373,7 @@
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="Win32\Debug\DMVCFrameworkTests.exe" Configuration="Debug" Class="ProjectOutput">
<DeployFile LocalName="bin\DMVCFrameworkTests.exe" Configuration="TESTINSIGHT" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>DMVCFrameworkTests.exe</RemoteName>
<Overwrite>true</Overwrite>