mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 15:55:54 +01:00
New feature: ObjectVersioning for TMVCActiveRecord - see foVersion
- TMVCActiveRecord.TableName is now readonly
This commit is contained in:
parent
7c7443d0b2
commit
a2f190df44
@ -681,6 +681,35 @@ type
|
||||
end;
|
||||
|
||||
|
||||
[MVCNameCase(ncLowerCase)]
|
||||
[MVCTable('customers_with_version')]
|
||||
TCustomerWithVersion = class(TCustomEntity)
|
||||
private
|
||||
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
|
||||
fID: NullableInt64;
|
||||
[MVCTableField('code')]
|
||||
fCode: NullableString;
|
||||
[MVCTableField('description')]
|
||||
fCompanyName: NullableString;
|
||||
[MVCTableField('city')]
|
||||
fCity: string;
|
||||
[MVCTableField('rating')]
|
||||
fRating: NullableInt32;
|
||||
[MVCTableField('note')]
|
||||
fNote: string;
|
||||
[MVCTableField('objversion', [foVersion])]
|
||||
fObjVersion: Integer;
|
||||
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 Rating: NullableInt32 read fRating write fRating;
|
||||
property Note: string read fNote write fNote;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
@ -896,4 +925,17 @@ begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
{ TCustomerWithVersion }
|
||||
|
||||
function TCustomerWithVersion.ToString: String;
|
||||
begin
|
||||
Result := '';
|
||||
if PKIsNull then
|
||||
Result := '<null>'
|
||||
else
|
||||
Result := fID.ValueOrDefault.ToString;
|
||||
Result := Format('[ID: %6s][CODE: %6s][CompanyName: %18s][City: %16s][Rating: %3d][Note: %s][Version: %d]',[
|
||||
Result, fCode.ValueOrDefault, fCompanyName.ValueOrDefault, fCity, fRating.ValueOrDefault, fNote, fObjVersion]);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -2,8 +2,8 @@ object MainForm: TMainForm
|
||||
Left = 0
|
||||
Top = 0
|
||||
Caption = 'TMVCActiveRecord - ShowCase'
|
||||
ClientHeight = 593
|
||||
ClientWidth = 1104
|
||||
ClientHeight = 626
|
||||
ClientWidth = 1094
|
||||
Color = clBtnFace
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
@ -13,8 +13,8 @@ object MainForm: TMainForm
|
||||
OnDestroy = FormDestroy
|
||||
OnShow = FormShow
|
||||
DesignSize = (
|
||||
1104
|
||||
593)
|
||||
1094
|
||||
626)
|
||||
TextHeight = 13
|
||||
object btnCRUD: TButton
|
||||
Left = 8
|
||||
@ -37,8 +37,8 @@ object MainForm: TMainForm
|
||||
object Memo1: TMemo
|
||||
Left = 280
|
||||
Top = 8
|
||||
Width = 816
|
||||
Height = 577
|
||||
Width = 806
|
||||
Height = 610
|
||||
Anchors = [akLeft, akTop, akRight, akBottom]
|
||||
Ctl3D = True
|
||||
DoubleBuffered = True
|
||||
@ -55,8 +55,8 @@ object MainForm: TMainForm
|
||||
TabOrder = 2
|
||||
WantReturns = False
|
||||
WordWrap = False
|
||||
ExplicitWidth = 812
|
||||
ExplicitHeight = 576
|
||||
ExplicitWidth = 802
|
||||
ExplicitHeight = 609
|
||||
end
|
||||
object btnRelations: TButton
|
||||
Left = 8
|
||||
@ -294,6 +294,15 @@ object MainForm: TMainForm
|
||||
TabOrder = 28
|
||||
OnClick = btnIntegersAsBoolClick
|
||||
end
|
||||
object btnObjectVersion: TButton
|
||||
Left = 8
|
||||
Top = 562
|
||||
Width = 121
|
||||
Height = 34
|
||||
Caption = 'Object Version'
|
||||
TabOrder = 29
|
||||
OnClick = btnObjectVersionClick
|
||||
end
|
||||
object FDConnection1: TFDConnection
|
||||
Left = 312
|
||||
Top = 40
|
||||
|
@ -61,6 +61,7 @@ type
|
||||
btnNamedQuery: TButton;
|
||||
btnVirtualEntities: TButton;
|
||||
btnIntegersAsBool: TButton;
|
||||
btnObjectVersion: TButton;
|
||||
procedure btnCRUDClick(Sender: TObject);
|
||||
procedure btnInheritanceClick(Sender: TObject);
|
||||
procedure btnMultiThreadingClick(Sender: TObject);
|
||||
@ -92,6 +93,7 @@ type
|
||||
procedure btnNamedQueryClick(Sender: TObject);
|
||||
procedure btnVirtualEntitiesClick(Sender: TObject);
|
||||
procedure btnIntegersAsBoolClick(Sender: TObject);
|
||||
procedure btnObjectVersionClick(Sender: TObject);
|
||||
private
|
||||
procedure Log(const Value: string);
|
||||
procedure LoadCustomers(const HowManyCustomers: Integer = 50);
|
||||
@ -1951,6 +1953,33 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnObjectVersionClick(Sender: TObject);
|
||||
begin
|
||||
var lID: NullableInt64;
|
||||
var lCust := TCustomerWithVersion.Create();
|
||||
try
|
||||
Log('Entity ' + TCustomerWithVersion.ClassName + ' is mapped to table ' + lCust.TableName);
|
||||
lCust.CompanyName := 'Google Inc.';
|
||||
lCust.City := 'Montain View, CA';
|
||||
lCust.Note := 'Μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος οὐλομένην 😁';
|
||||
lCust.Insert;
|
||||
lID := lCust.ID;
|
||||
Log('Just inserted CustomerWithVersion ' + lID.ValueOrDefault.ToString);
|
||||
lCust.Store;
|
||||
finally
|
||||
lCust.Free;
|
||||
end;
|
||||
|
||||
|
||||
lCust := TMVCActiveRecord.GetByPK<TCustomerWithVersion>(lID);
|
||||
try
|
||||
lCust.CompanyName := 'Alphabet Inc.';
|
||||
lCust.Store;
|
||||
finally
|
||||
lCust.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnOOPClick(Sender: TObject);
|
||||
begin
|
||||
Log('** OOP with ActiveRecord (person, employee, manager)');
|
||||
|
Binary file not shown.
Binary file not shown.
@ -101,5 +101,16 @@ create table integers_as_booleans (
|
||||
done_int smallint not null
|
||||
);
|
||||
|
||||
CREATE TABLE customers_with_version (
|
||||
id bigint generated by default as identity NOT NULL,
|
||||
code varchar(20),
|
||||
description varchar(200),
|
||||
city varchar(200),
|
||||
note varchar(1000),
|
||||
rating integer,
|
||||
objversion integer
|
||||
);
|
||||
|
||||
|
||||
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;
|
||||
|
@ -117,6 +117,22 @@ CREATE TABLE "customers with spaces" (
|
||||
CONSTRAINT cust_with_space_pk PRIMARY KEY ("id with spaces")
|
||||
);
|
||||
|
||||
create table integers_as_booleans (
|
||||
id bigint generated by default as identity primary key,
|
||||
done_bool boolean not null,
|
||||
done_int smallint not null
|
||||
);
|
||||
|
||||
CREATE TABLE customers_with_version (
|
||||
id bigint generated by default as identity NOT NULL,
|
||||
code varchar(20),
|
||||
description varchar(200),
|
||||
city varchar(200),
|
||||
note varchar(1000),
|
||||
rating integer,
|
||||
objversion integer
|
||||
);
|
||||
|
||||
|
||||
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;
|
||||
|
@ -115,5 +115,15 @@ create table integers_as_booleans (
|
||||
done_int smallint not null
|
||||
);
|
||||
|
||||
CREATE TABLE customers_with_version (
|
||||
id bigint not null auto_increment primary key,
|
||||
code varchar(20),
|
||||
description varchar(200),
|
||||
city varchar(200),
|
||||
note varchar(1000),
|
||||
rating integer,
|
||||
objversion integer
|
||||
);
|
||||
|
||||
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;
|
||||
|
@ -131,6 +131,19 @@ CREATE TABLE public.customers (
|
||||
|
||||
ALTER TABLE public.customers OWNER TO postgres;
|
||||
|
||||
|
||||
CREATE TABLE public.customers_with_version (
|
||||
id bigint generated by default as identity NOT NULL,
|
||||
code character varying(20),
|
||||
description character varying(200),
|
||||
city character varying(200),
|
||||
note text,
|
||||
rating integer,
|
||||
objversion integer
|
||||
);
|
||||
|
||||
ALTER TABLE public.customers_with_version OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- TOC entry 205 (class 1259 OID 58864)
|
||||
-- Name: customers with spaces; Type: TABLE; Schema: public; Owner: postgres
|
||||
|
@ -63,7 +63,9 @@ type
|
||||
TMVCActiveRecordFieldOption = (foPrimaryKey, { it's the primary key of the mapped table }
|
||||
foAutoGenerated, { not written, read - similar to readonly }
|
||||
foReadOnly, { not written, read }
|
||||
foWriteOnly); { written, not read }
|
||||
foWriteOnly, { written, not read }
|
||||
foVersion {used for versioning, only one field with foVersion is allowed in class}
|
||||
);
|
||||
TMVCActiveRecordFieldOptions = set of TMVCActiveRecordFieldOption;
|
||||
TMVCEntityAction = (eaCreate, eaRetrieve, eaUpdate, eaDelete);
|
||||
TMVCEntityActions = set of TMVCEntityAction;
|
||||
@ -95,11 +97,10 @@ type
|
||||
|
||||
TFieldInfo = class
|
||||
public
|
||||
// TableName: string;
|
||||
FieldName: string;
|
||||
FieldOptions: TMVCActiveRecordFieldOptions;
|
||||
DataTypeName: string;
|
||||
Writeable, Readable: Boolean;
|
||||
Writeable, Readable, IsVersion: Boolean;
|
||||
procedure EndUpdates;
|
||||
end;
|
||||
|
||||
@ -213,16 +214,19 @@ type
|
||||
end;
|
||||
|
||||
TMVCTableMap = class
|
||||
protected
|
||||
public
|
||||
fPartitionInfoInternal: TPartitionInfo;
|
||||
fEntityAllowedActions: TMVCEntityActions;
|
||||
fTableName: string;
|
||||
fTableName: String;
|
||||
fVersionFieldName: String;
|
||||
fIsVersioned: Boolean;
|
||||
fPartitionClause: String;
|
||||
fRTTIType: TRttiInstanceType;
|
||||
fObjAttributes: TArray<TCustomAttribute>;
|
||||
fDefaultRQLFilter: string;
|
||||
fMap: TFieldsMap;
|
||||
fPrimaryKey: TRTTIField;
|
||||
fVersionRTTIField: TRttiField;
|
||||
fMapping: TMVCFieldsMapping;
|
||||
fPropsAttributes: TArray<TCustomAttribute>;
|
||||
fProps: TArray<TRTTIField>;
|
||||
@ -243,15 +247,15 @@ type
|
||||
fConn: TFDConnection;
|
||||
fSQLGenerator: TMVCSQLGenerator;
|
||||
fRQL2SQL: TRQL2SQL;
|
||||
fCustomTableName: String;
|
||||
procedure MapTValueToParam(aValue: TValue; const aParam: TFDParam);
|
||||
function MapNullableTValueToParam(aValue: TValue; const aParam: TFDParam): Boolean;
|
||||
function GetPrimaryKeyIsAutogenerated: Boolean;
|
||||
procedure SetPrimaryKeyIsAutogenerated(const Value: Boolean);
|
||||
procedure SetTableName(const Value: string);
|
||||
function GetAttributes(const AttrName: string): TValue;
|
||||
procedure SetAttributes(const AttrName: string; const Value: TValue);
|
||||
function GetTableName: string;
|
||||
procedure AdvanceVersioning(const TableMap: TMVCTableMap; const ARInstance: TMVCActiveRecord);
|
||||
procedure SetInitialObjVersion(const TableMap: TMVCTableMap; const ARInstance: TMVCActiveRecord);
|
||||
protected
|
||||
fBackendDriver: string;
|
||||
fTableMap: TMVCTableMap;
|
||||
@ -413,8 +417,7 @@ type
|
||||
|
||||
[MVCDoNotSerialize]
|
||||
property TableName: string
|
||||
read GetTableName
|
||||
write SetTableName;
|
||||
read GetTableName;
|
||||
|
||||
[MVCDoNotSerialize]
|
||||
property PrimaryKeyIsAutogenerated: Boolean
|
||||
@ -791,18 +794,15 @@ type
|
||||
const MaxRecordCount: Int32 = TMVCConstants.MAX_RECORD_COUNT): string;
|
||||
function CreateSelectSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual;
|
||||
function CreateInsertSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual; abstract;
|
||||
function CreateInsertSQL(const TableMap: TMVCTableMap; const ARInstance: TMVCActiveRecord): string; virtual; abstract;
|
||||
|
||||
// virtual methods with default implementation
|
||||
function CreateSelectByPKSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual;
|
||||
function CreateDeleteSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string; virtual;
|
||||
function CreateDeleteSQL(const TableMap: TMVCTableMap; const ARInstance: TMVCActiveRecord): 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 CreateUpdateSQL(const TableMap: TMVCTableMap; const ARInstance: TMVCActiveRecord): string; virtual;
|
||||
function GetSequenceValueSQL(const PKFieldName: string; const SequenceName: string; const Step: Integer = 1)
|
||||
: string; virtual;
|
||||
|
||||
@ -895,6 +895,10 @@ function ActiveRecordTableMapRegistry: IMVCActiveRecordTableMap;
|
||||
function ActiveRecordMappingRegistry: IMVCEntitiesRegistry;
|
||||
function GetBackEndByConnection(aConnection: TFDConnection): string;
|
||||
|
||||
const
|
||||
OBJECT_VERSION_STARTING_VALUE = '1';
|
||||
OBJECT_VERSION_STARTING_VALUE_AS_INT: Int64 = 1;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@ -1564,6 +1568,17 @@ begin
|
||||
lFieldInfo.FieldName := MVCTableFieldAttribute(lAttribute).FieldName;
|
||||
lFieldInfo.FieldOptions := MVCTableFieldAttribute(lAttribute).FieldOptions;
|
||||
lFieldInfo.DataTypeName := MVCTableFieldAttribute(lAttribute).DataTypeName;
|
||||
|
||||
if foVersion in lFieldInfo.FieldOptions then
|
||||
begin
|
||||
if not lTableMap.fVersionFieldName.IsEmpty then
|
||||
begin
|
||||
raise EMVCActiveRecord.Create('Only one version field is allowed for table - Currently at least fields [' + lTableMap.fVersionFieldName + '] and [' + lFieldInfo.FieldName + '] are marked as foVersion');
|
||||
end;
|
||||
lTableMap.fVersionRTTIField := lRTTIField;
|
||||
lTableMap.fVersionFieldName := lFieldInfo.FieldName;
|
||||
lTableMap.fIsVersioned := True;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -1620,9 +1635,13 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
SQL := SQLGenerator.CreateInsertSQL(TableName, fTableMap.fMap,
|
||||
fTableMap.fPrimaryKeyFieldName, fTableMap.fPrimaryKeyOptions);
|
||||
SQL := SQLGenerator.CreateInsertSQL(fTableMap, Self);
|
||||
ExecNonQuery(SQL, True);
|
||||
if fTableMap.fIsVersioned then
|
||||
begin
|
||||
{ in case of INSERT version is defined by constants }
|
||||
SetInitialObjVersion(fTableMap, Self);
|
||||
end;
|
||||
OnAfterInsert;
|
||||
OnAfterInsertOrUpdate;
|
||||
end;
|
||||
@ -2030,10 +2049,7 @@ end;
|
||||
|
||||
function TMVCActiveRecord.GetTableName: string;
|
||||
begin
|
||||
if fCustomTableName.IsEmpty then
|
||||
Result := fTableMap.fTableName
|
||||
else
|
||||
Result := fCustomTableName;
|
||||
end;
|
||||
|
||||
function TMVCActiveRecord.CheckAction(const aEntityAction: TMVCEntityAction; const aRaiseException: Boolean): Boolean;
|
||||
@ -2184,14 +2200,21 @@ begin
|
||||
OnBeforeDelete;
|
||||
if not Assigned(fTableMap.fPrimaryKey) then
|
||||
raise Exception.CreateFmt('Cannot delete %s without a primary key', [ClassName]);
|
||||
SQL := SQLGenerator.CreateDeleteSQL(TableName, fTableMap.fMap,
|
||||
fTableMap.fPrimaryKeyFieldName, fTableMap.fPrimaryKeyOptions);
|
||||
SQL := SQLGenerator.CreateDeleteSQL(fTableMap, Self);
|
||||
lAffectedRows := ExecNonQuery(SQL, false);
|
||||
if (lAffectedRows = 0) and RaiseExceptionIfNotFound then
|
||||
begin
|
||||
if fTableMap.fIsVersioned then
|
||||
begin
|
||||
raise EMVCActiveRecordNotFound.CreateFmt('No record deleted for key [Entity: %s][PK: %s][Version: %d]',
|
||||
[ClassName, fTableMap.fPrimaryKeyFieldName, fTableMap.fVersionRTTIField.GetValue(Self).AsInt64]);
|
||||
end
|
||||
else
|
||||
begin
|
||||
raise EMVCActiveRecordNotFound.CreateFmt('No record deleted for key [Entity: %s][PK: %s]',
|
||||
[ClassName, fTableMap.fPrimaryKeyFieldName]);
|
||||
end;
|
||||
end;
|
||||
OnAfterDelete;
|
||||
end;
|
||||
|
||||
@ -3340,16 +3363,10 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMVCActiveRecord.SetTableName(const Value: string);
|
||||
procedure TMVCActiveRecord.SetInitialObjVersion(const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord);
|
||||
begin
|
||||
if Value = fTableMap.fTableName then
|
||||
begin
|
||||
fCustomTableName := '';
|
||||
end
|
||||
else
|
||||
begin
|
||||
fCustomTableName := Value;
|
||||
end;
|
||||
TableMap.fVersionRTTIField.SetValue(ARInstance, OBJECT_VERSION_STARTING_VALUE_AS_INT);
|
||||
end;
|
||||
|
||||
function TMVCActiveRecord.SQLGenerator: TMVCSQLGenerator;
|
||||
@ -3460,14 +3477,25 @@ begin
|
||||
raise EMVCActiveRecord.CreateFmt
|
||||
('Cannot update an entity if no fields are writeable. Class [%s] mapped on table [%s]', [ClassName, TableName]);
|
||||
end;
|
||||
SQL := SQLGenerator.CreateUpdateSQL(TableName, fTableMap.fMap,
|
||||
fTableMap.fPrimaryKeyFieldName, fTableMap.fPrimaryKeyOptions);
|
||||
SQL := SQLGenerator.CreateUpdateSQL(fTableMap, Self);
|
||||
lAffectedRows := ExecNonQuery(SQL, false);
|
||||
if (lAffectedRows = 0) and RaiseExceptionIfNotFound then
|
||||
begin
|
||||
if fTableMap.fIsVersioned then
|
||||
begin
|
||||
raise EMVCActiveRecordNotFound.CreateFmt('No record updated for key [Entity: %s][PK: %s][Version: %d]',
|
||||
[ClassName, fTableMap.fPrimaryKeyFieldName, fTableMap.fVersionRTTIField.GetValue(Self).AsInt64]);
|
||||
end
|
||||
else
|
||||
begin
|
||||
raise EMVCActiveRecordNotFound.CreateFmt('No record updated for key [Entity: %s][PK: %s]',
|
||||
[ClassName, fTableMap.fPrimaryKeyFieldName]);
|
||||
end;
|
||||
end;
|
||||
if fTableMap.fIsVersioned then
|
||||
begin
|
||||
AdvanceVersioning(fTableMap, Self);
|
||||
end;
|
||||
OnAfterUpdate;
|
||||
OnAfterInsertOrUpdate;
|
||||
end;
|
||||
@ -3511,6 +3539,15 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMVCActiveRecord.AdvanceVersioning(const TableMap: TMVCTableMap; const ARInstance: TMVCActiveRecord);
|
||||
var
|
||||
lCurrVersion: Int64;
|
||||
begin
|
||||
lCurrVersion := TableMap.fVersionRTTIField.GetValue(ARInstance).AsInt64;
|
||||
Inc(lCurrVersion);
|
||||
TableMap.fVersionRTTIField.SetValue(ARInstance, lCurrVersion);
|
||||
end;
|
||||
|
||||
procedure TMVCActiveRecord.Assign(ActiveRecord: TMVCActiveRecord);
|
||||
begin
|
||||
//do nothing
|
||||
@ -3790,11 +3827,14 @@ begin
|
||||
Result := 'DELETE FROM ' + GetTableNameForSQL(TableName);
|
||||
end;
|
||||
|
||||
function TMVCSQLGenerator.CreateDeleteSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string;
|
||||
function TMVCSQLGenerator.CreateDeleteSQL(const TableMap: TMVCTableMap; const ARInstance: TMVCActiveRecord): string;
|
||||
begin
|
||||
Result := CreateDeleteAllSQL(TableName) + ' WHERE ' + GetFieldNameForSQL(PKFieldName) + '=:' +
|
||||
GetParamNameForSQL(PKFieldName);
|
||||
Result := CreateDeleteAllSQL(TableMap.fTableName) + ' WHERE ' + GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName) + '=:' +
|
||||
GetParamNameForSQL(TableMap.fPrimaryKeyFieldName);
|
||||
if TableMap.fIsVersioned then
|
||||
begin
|
||||
Result := Result + ' and ' + GetFieldNameForSQL(TableMap.fVersionFieldName) + ' = ' + IntToStr(TableMap.fVersionRTTIField.GetValue(ARInstance).AsInt64);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TMVCSQLGenerator.CreateSelectByPKSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
|
||||
@ -3829,16 +3869,19 @@ begin
|
||||
MaxRecordCount);
|
||||
end;
|
||||
|
||||
function TMVCSQLGenerator.CreateUpdateSQL(const TableName: string; const Map: TFieldsMap; const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string;
|
||||
function TMVCSQLGenerator.CreateUpdateSQL(const TableMap: TMVCTableMap; const ARInstance: TMVCActiveRecord): string;
|
||||
var
|
||||
lPair: TPair<TRTTIField, TFieldInfo>;
|
||||
// I: Integer;
|
||||
begin
|
||||
Result := 'UPDATE ' + GetTableNameForSQL(TableName) + ' SET ';
|
||||
for lPair in Map do
|
||||
Result := 'UPDATE ' + GetTableNameForSQL(TableMap.fTableName) + ' SET ';
|
||||
for lPair in TableMap.fMap do
|
||||
begin
|
||||
if lPair.Value.Writeable then
|
||||
if lPair.Value.IsVersion then
|
||||
begin
|
||||
Result := Result + GetFieldNameForSQL(lPair.Value.FieldName) + ' = :' +
|
||||
GetParamNameForSQL(lPair.Value.FieldName) + ' + 1,';
|
||||
end else if lPair.Value.Writeable then
|
||||
begin
|
||||
Result := Result + GetFieldNameForSQL(lPair.Value.FieldName) + ' = :' +
|
||||
GetParamNameForSQL(lPair.Value.FieldName) + ',';
|
||||
@ -3852,9 +3895,14 @@ begin
|
||||
// end;
|
||||
{ end-partitioning }
|
||||
Result[Length(Result)] := ' ';
|
||||
if not PKFieldName.IsEmpty then
|
||||
if not TableMap.fPrimaryKeyFieldName.IsEmpty then
|
||||
begin
|
||||
Result := Result + ' where ' + GetFieldNameForSQL(PKFieldName) + '= :' + GetParamNameForSQL(PKFieldName);
|
||||
Result := Result + ' where ' +
|
||||
GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName) + '= :' + GetParamNameForSQL(TableMap.fPrimaryKeyFieldName);
|
||||
if TableMap.fIsVersioned then
|
||||
begin
|
||||
Result := Result + ' and ' + GetFieldNameForSQL(TableMap.fVersionFieldName) + ' = ' + TableMap.fVersionRTTIField.GetValue(ARInstance).AsInt64.ToString
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -4175,6 +4223,7 @@ begin
|
||||
Writeable := ((FieldOptions * [foReadOnly, foAutoGenerated]) = []);
|
||||
Readable := (FieldOptions * [foWriteOnly]) = [];
|
||||
end;
|
||||
IsVersion := foVersion in FieldOptions;
|
||||
end;
|
||||
|
||||
{ TMVCUnitOfWork<T> }
|
||||
@ -4550,6 +4599,8 @@ constructor TMVCTableMap.Create;
|
||||
begin
|
||||
inherited;
|
||||
fMap := TFieldsMap.Create;
|
||||
fIsVersioned := False;
|
||||
fVersionFieldName := '';
|
||||
end;
|
||||
|
||||
destructor TMVCTableMap.Destroy;
|
||||
|
@ -42,10 +42,8 @@ type
|
||||
function GetCompilerClass: TRQLCompilerClass; override;
|
||||
public
|
||||
function CreateInsertSQL(
|
||||
const TableName: string;
|
||||
const Map: TFieldsMap;
|
||||
const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
|
||||
const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord): string; override;
|
||||
function GetSequenceValueSQL(const PKFieldName: string;
|
||||
const SequenceName: string;
|
||||
const Step: Integer = 1): string; override;
|
||||
@ -57,22 +55,22 @@ uses
|
||||
System.SysUtils,
|
||||
MVCFramework.RQL.AST2FirebirdSQL;
|
||||
|
||||
function TMVCSQLGeneratorFirebird.CreateInsertSQL(const TableName: string; const Map: TFieldsMap;
|
||||
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
|
||||
function TMVCSQLGeneratorFirebird.CreateInsertSQL(const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord): string;
|
||||
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));
|
||||
lPKInInsert := (not TableMap.fPrimaryKeyFieldName.IsEmpty) and (not(TMVCActiveRecordFieldOption.foAutoGenerated in TableMap.fPrimaryKeyOptions));
|
||||
lPKInInsert := lPKInInsert and (not(TMVCActiveRecordFieldOption.foReadOnly in TableMap.fPrimaryKeyOptions));
|
||||
lSB := TStringBuilder.Create;
|
||||
try
|
||||
lSB.Append('INSERT INTO ' + GetTableNameForSQL(TableName) + ' (');
|
||||
lSB.Append('INSERT INTO ' + GetTableNameForSQL(TableMap.fTableName) + ' (');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(GetFieldNameForSQL(PKFieldName) + ',');
|
||||
lSB.Append(GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName) + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -82,7 +80,7 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
// if not(foTransient in lKeyValue.Value.FieldOptions) then
|
||||
if lKeyValue.Value.Writeable then
|
||||
@ -95,7 +93,7 @@ begin
|
||||
lSB.Append(') values (');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(PKFieldName) + ',');
|
||||
lSB.Append(':' + GetParamNameForSQL(TableMap.fPrimaryKeyFieldName) + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -105,9 +103,12 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
if lKeyValue.Value.IsVersion then
|
||||
begin
|
||||
lSB.Append(OBJECT_VERSION_STARTING_VALUE + ',');
|
||||
end else if lKeyValue.Value.Writeable then
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(lKeyValue.Value.FieldName) + ',');
|
||||
end;
|
||||
@ -116,9 +117,9 @@ begin
|
||||
lSB.Remove(lSB.Length - 1, 1);
|
||||
lSB.Append(')');
|
||||
|
||||
if TMVCActiveRecordFieldOption.foAutoGenerated in PKOptions then
|
||||
if TMVCActiveRecordFieldOption.foAutoGenerated in TableMap.fPrimaryKeyOptions then
|
||||
begin
|
||||
lSB.Append(' RETURNING ' + GetFieldNameForSQL(PKFieldName));
|
||||
lSB.Append(' RETURNING ' + GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName));
|
||||
end;
|
||||
Result := lSB.ToString;
|
||||
finally
|
||||
|
@ -39,10 +39,9 @@ uses
|
||||
type
|
||||
TMVCSQLGeneratorInterbase = class(TMVCSQLGeneratorFirebird)
|
||||
public
|
||||
function CreateInsertSQL(const TableName: string;
|
||||
const Map: TFieldsMap;
|
||||
const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
|
||||
function CreateInsertSQL(
|
||||
const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord): string; override;
|
||||
function HasReturning: Boolean; override;
|
||||
end;
|
||||
|
||||
@ -53,24 +52,23 @@ uses
|
||||
|
||||
{ TMVCSQLGeneratorInterbase }
|
||||
|
||||
function TMVCSQLGeneratorInterbase.CreateInsertSQL(const TableName: string;
|
||||
const Map: TFieldsMap;
|
||||
const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string;
|
||||
function TMVCSQLGeneratorInterbase.CreateInsertSQL(
|
||||
const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord): string;
|
||||
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));
|
||||
lPKInInsert := (not TableMap.fPrimaryKeyFieldName.IsEmpty);
|
||||
lPKInInsert := lPKInInsert and (not(TMVCActiveRecordFieldOption.foReadOnly in TableMap.fPrimaryKeyOptions));
|
||||
lSB := TStringBuilder.Create;
|
||||
try
|
||||
lSB.Append('INSERT INTO ' + GetTableNameForSQL(TableName) + '(');
|
||||
lSB.Append('INSERT INTO ' + GetTableNameForSQL(TableMap.fTableName) + '(');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(GetFieldNameForSQL(PKFieldName) + ',');
|
||||
lSB.Append(GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName) + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -80,7 +78,7 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
begin
|
||||
@ -92,7 +90,7 @@ begin
|
||||
lSB.Append(') values (');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(PKFieldName) + ',');
|
||||
lSB.Append(':' + GetParamNameForSQL(TableMap.fPrimaryKeyFieldName) + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -102,9 +100,12 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
if lKeyValue.Value.IsVersion then
|
||||
begin
|
||||
lSB.Append(OBJECT_VERSION_STARTING_VALUE + ',');
|
||||
end else if lKeyValue.Value.Writeable then
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(lKeyValue.Value.FieldName) + ',');
|
||||
end;
|
||||
|
@ -41,10 +41,8 @@ type
|
||||
function GetCompilerClass: TRQLCompilerClass; override;
|
||||
public
|
||||
function CreateInsertSQL(
|
||||
const TableName: string;
|
||||
const Map: TFieldsMap;
|
||||
const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
|
||||
const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord): string; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -53,22 +51,23 @@ uses
|
||||
System.SysUtils,
|
||||
MVCFramework.RQL.AST2MSSQL;
|
||||
|
||||
function TMVCSQLGeneratorMSSQL.CreateInsertSQL(const TableName: string; const Map: TFieldsMap;
|
||||
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
|
||||
function TMVCSQLGeneratorMSSQL.CreateInsertSQL(
|
||||
const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord): string;
|
||||
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));
|
||||
lPKInInsert := (not TableMap.fPrimaryKeyFieldName.IsEmpty) and (not(TMVCActiveRecordFieldOption.foAutoGenerated in TableMap.fPrimaryKeyOptions));
|
||||
lPKInInsert := lPKInInsert and (not(TMVCActiveRecordFieldOption.foReadOnly in TableMap.fPrimaryKeyOptions));
|
||||
lSB := TStringBuilder.Create;
|
||||
try
|
||||
lSB.Append('INSERT INTO ' + TableName + '(');
|
||||
lSB.Append('INSERT INTO ' + TableMap.fTableName + '(');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(PKFieldName + ',');
|
||||
lSB.Append(TableMap.fPrimaryKeyFieldName + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -78,7 +77,7 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
begin
|
||||
@ -89,7 +88,7 @@ begin
|
||||
lSB.Append(') values (');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(':' + PKFieldName + ',');
|
||||
lSB.Append(':' + TableMap.fPrimaryKeyFieldName + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -99,9 +98,12 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
if lKeyValue.Value.IsVersion then
|
||||
begin
|
||||
lSB.Append(OBJECT_VERSION_STARTING_VALUE + ',');
|
||||
end else if lKeyValue.Value.Writeable then
|
||||
begin
|
||||
lSB.Append(':' + lKeyValue.Value.FieldName + ',');
|
||||
end;
|
||||
@ -109,9 +111,9 @@ begin
|
||||
lSB.Remove(lSB.Length - 1, 1);
|
||||
lSB.Append(')');
|
||||
|
||||
if TMVCActiveRecordFieldOption.foAutoGenerated in PKOptions then
|
||||
if TMVCActiveRecordFieldOption.foAutoGenerated in TableMap.fPrimaryKeyOptions then
|
||||
begin
|
||||
lSB.Append(';SELECT SCOPE_IDENTITY() as ' + PKFieldName);
|
||||
lSB.Append(';SELECT SCOPE_IDENTITY() as ' + TableMap.fPrimaryKeyFieldName);
|
||||
end;
|
||||
Result := lSB.ToString;
|
||||
finally
|
||||
|
@ -41,10 +41,9 @@ type
|
||||
function GetCompilerClass: TRQLCompilerClass; override;
|
||||
public
|
||||
function CreateInsertSQL(
|
||||
const TableName: string;
|
||||
const Map: TFieldsMap;
|
||||
const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
|
||||
const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord
|
||||
): string; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -53,22 +52,24 @@ uses
|
||||
System.SysUtils,
|
||||
MVCFramework.RQL.AST2MySQL;
|
||||
|
||||
function TMVCSQLGeneratorMySQL.CreateInsertSQL(const TableName: string; const Map: TFieldsMap;
|
||||
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
|
||||
function TMVCSQLGeneratorMySQL.CreateInsertSQL(
|
||||
const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord
|
||||
): string;
|
||||
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));
|
||||
lPKInInsert := (not TableMap.fPrimaryKeyFieldName.IsEmpty) and (not(TMVCActiveRecordFieldOption.foAutoGenerated in TableMap.fPrimaryKeyOptions));
|
||||
lPKInInsert := lPKInInsert and (not(TMVCActiveRecordFieldOption.foReadOnly in TableMap.fPrimaryKeyOptions));
|
||||
lSB := TStringBuilder.Create;
|
||||
try
|
||||
lSB.Append('INSERT INTO ' + TableName + '(');
|
||||
lSB.Append('INSERT INTO ' + TableMap.fTableName + '(');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(PKFieldName + ',');
|
||||
lSB.Append(TableMap.fPrimaryKeyFieldName + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -78,7 +79,7 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
begin
|
||||
@ -90,7 +91,7 @@ begin
|
||||
lSB.Append(') values (');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(':' + PKFieldName + ',');
|
||||
lSB.Append(':' + TableMap.fPrimaryKeyFieldName + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -100,19 +101,22 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
if lKeyValue.Value.IsVersion then
|
||||
begin
|
||||
lSB.Append(':' + lKeyValue.Value.FieldName + ',');
|
||||
lSB.Append(OBJECT_VERSION_STARTING_VALUE + ',');
|
||||
end else if lKeyValue.Value.Writeable then
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(lKeyValue.Value.FieldName) + ',');
|
||||
end;
|
||||
end;
|
||||
lSB.Remove(lSB.Length - 1, 1);
|
||||
lSB.Append(')');
|
||||
|
||||
if TMVCActiveRecordFieldOption.foAutoGenerated in PKOptions then
|
||||
if TMVCActiveRecordFieldOption.foAutoGenerated in TableMap.fPrimaryKeyOptions then
|
||||
begin
|
||||
lSB.Append(';SELECT LAST_INSERT_ID() as ' + PKFieldName);
|
||||
lSB.Append(';SELECT LAST_INSERT_ID() as ' + TableMap.fPrimaryKeyFieldName);
|
||||
end;
|
||||
Result := lSB.ToString;
|
||||
finally
|
||||
|
@ -40,10 +40,7 @@ type
|
||||
public
|
||||
function HasNativeUUID: Boolean; override;
|
||||
function CreateInsertSQL(
|
||||
const TableName: string;
|
||||
const Map: TFieldsMap;
|
||||
const PKFieldName: string;
|
||||
const PKOptions: TMVCActiveRecordFieldOptions): string; override;
|
||||
const TableMap: TMVCTableMap; const ARInstance: TMVCActiveRecord): string; override;
|
||||
function GetSequenceValueSQL(const PKFieldName: string;
|
||||
const SequenceName: string;
|
||||
const Step: Integer = 1): string; override;
|
||||
@ -62,22 +59,21 @@ uses
|
||||
System.SysUtils,
|
||||
MVCFramework.RQL.AST2PostgreSQL;
|
||||
|
||||
function TMVCSQLGeneratorPostgreSQL.CreateInsertSQL(const TableName: string; const Map: TFieldsMap;
|
||||
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
|
||||
function TMVCSQLGeneratorPostgreSQL.CreateInsertSQL(const TableMap: TMVCTableMap; const ARInstance: TMVCActiveRecord): string;
|
||||
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));
|
||||
lPKInInsert := (not TableMap.fPrimaryKeyFieldName.IsEmpty) and (not(TMVCActiveRecordFieldOption.foAutoGenerated in TableMap.fPrimaryKeyOptions));
|
||||
lPKInInsert := lPKInInsert and (not(TMVCActiveRecordFieldOption.foReadOnly in TableMap.fPrimaryKeyOptions));
|
||||
lSB := TStringBuilder.Create;
|
||||
try
|
||||
lSB.Append('INSERT INTO ' + GetTableNameForSQL(TableName) + ' (');
|
||||
lSB.Append('INSERT INTO ' + GetTableNameForSQL(TableMap.fTableName) + ' (');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(GetFieldNameForSQL(PKFieldName) + ',');
|
||||
lSB.Append(GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName) + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -87,7 +83,7 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
// if not(foTransient in lKeyValue.Value.FieldOptions) then
|
||||
if lKeyValue.Value.Writeable then
|
||||
@ -99,7 +95,7 @@ begin
|
||||
lSB.Append(') values (');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(PKFieldName) + ',');
|
||||
lSB.Append(':' + GetParamNameForSQL(TableMap.fPrimaryKeyFieldName) + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -109,9 +105,12 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
if lKeyValue.Value.IsVersion then
|
||||
begin
|
||||
lSB.Append(OBJECT_VERSION_STARTING_VALUE + ',');
|
||||
end else if lKeyValue.Value.Writeable then
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(lKeyValue.Value.FieldName) + ',');
|
||||
end;
|
||||
@ -119,9 +118,9 @@ begin
|
||||
lSB.Remove(lSB.Length - 1, 1);
|
||||
lSB.Append(')');
|
||||
|
||||
if TMVCActiveRecordFieldOption.foAutoGenerated in PKOptions then
|
||||
if TMVCActiveRecordFieldOption.foAutoGenerated in TableMap.fPrimaryKeyOptions then
|
||||
begin
|
||||
lSB.Append(' RETURNING ' + GetFieldNameForSQL(PKFieldName));
|
||||
lSB.Append(' RETURNING ' + GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName));
|
||||
end;
|
||||
Result := lSB.ToString;
|
||||
finally
|
||||
|
@ -38,8 +38,9 @@ type
|
||||
protected
|
||||
function GetCompilerClass: TRQLCompilerClass; override;
|
||||
public
|
||||
function CreateInsertSQL(const TableName: string; const Map: TFieldsMap;
|
||||
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string; override;
|
||||
function CreateInsertSQL(
|
||||
const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord): string; override;
|
||||
function HasSequences: Boolean; override;
|
||||
end;
|
||||
|
||||
@ -49,23 +50,24 @@ uses
|
||||
System.SysUtils,
|
||||
MVCFramework.RQL.AST2SQLite;
|
||||
|
||||
function TMVCSQLGeneratorSQLite.CreateInsertSQL(const TableName: string; const Map: TFieldsMap;
|
||||
const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string;
|
||||
function TMVCSQLGeneratorSQLite.CreateInsertSQL(
|
||||
const TableMap: TMVCTableMap;
|
||||
const ARInstance: TMVCActiveRecord): string;
|
||||
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));
|
||||
lPKInInsert := (not TableMap.fPrimaryKeyFieldName.IsEmpty) and
|
||||
(not(TMVCActiveRecordFieldOption.foAutoGenerated in TableMap.fPrimaryKeyOptions));
|
||||
lPKInInsert := lPKInInsert and (not(TMVCActiveRecordFieldOption.foReadOnly in TableMap.fPrimaryKeyOptions));
|
||||
lSB := TStringBuilder.Create;
|
||||
try
|
||||
lSB.Append('INSERT INTO ' + GetTableNameForSQL(TableName) + ' (');
|
||||
lSB.Append('INSERT INTO ' + GetTableNameForSQL(TableMap.fTableName) + ' (');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(GetFieldNameForSQL(PKFieldName) + ',');
|
||||
lSB.Append(GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName) + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -75,7 +77,7 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
begin
|
||||
@ -86,7 +88,7 @@ begin
|
||||
lSB.Append(') values (');
|
||||
if lPKInInsert then
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(PKFieldName) + ',');
|
||||
lSB.Append(':' + GetParamNameForSQL(TableMap.fPrimaryKeyFieldName) + ',');
|
||||
end;
|
||||
|
||||
{partition}
|
||||
@ -96,9 +98,12 @@ begin
|
||||
end;
|
||||
{end-partition}
|
||||
|
||||
for lKeyValue in Map do
|
||||
for lKeyValue in TableMap.fMap do
|
||||
begin
|
||||
if lKeyValue.Value.Writeable then
|
||||
if lKeyValue.Value.IsVersion then
|
||||
begin
|
||||
lSB.Append(OBJECT_VERSION_STARTING_VALUE + ',');
|
||||
end else if lKeyValue.Value.Writeable then
|
||||
begin
|
||||
lSB.Append(':' + GetParamNameForSQL(lKeyValue.Value.FieldName) + ',');
|
||||
end;
|
||||
@ -106,9 +111,9 @@ begin
|
||||
lSB.Remove(lSB.Length - 1, 1);
|
||||
lSB.Append(')');
|
||||
|
||||
if TMVCActiveRecordFieldOption.foAutoGenerated in PKOptions then
|
||||
if TMVCActiveRecordFieldOption.foAutoGenerated in TableMap.fPrimaryKeyOptions then
|
||||
begin
|
||||
lSB.Append(' ; SELECT last_insert_rowid() as ' + GetFieldNameForSQL(PKFieldName) + ';');
|
||||
lSB.Append(' ; SELECT last_insert_rowid() as ' + GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName) + ';');
|
||||
end;
|
||||
Result := lSB.ToString;
|
||||
finally
|
||||
|
@ -64,8 +64,6 @@ type
|
||||
[Test]
|
||||
procedure TestCRUDWithGUID;
|
||||
[Test]
|
||||
procedure TestCRUDWithTableChange;
|
||||
[Test]
|
||||
procedure TestCRUDStringPK;
|
||||
[Test]
|
||||
procedure TestSelectWithExceptions;
|
||||
@ -477,49 +475,6 @@ begin
|
||||
Assert.IsNull(lCustomer);
|
||||
end;
|
||||
|
||||
procedure TTestActiveRecordBase.TestCRUDWithTableChange;
|
||||
var
|
||||
lCustomer: TCustomer;
|
||||
lID: Integer;
|
||||
begin
|
||||
Assert.AreEqual(Int64(0), TMVCActiveRecord.Count<TCustomer>());
|
||||
AfterDataLoad;
|
||||
lCustomer := TCustomer.Create;
|
||||
try
|
||||
lCustomer.CompanyName := 'bit Time Professionals';
|
||||
lCustomer.City := 'Rome, IT';
|
||||
lCustomer.Note := 'note1';
|
||||
lCustomer.CreationTime := Time;
|
||||
lCustomer.CreationDate := Date;
|
||||
lCustomer.ID := -1; { don't be fooled by the default! }
|
||||
lCustomer.Insert;
|
||||
lID := lCustomer.ID;
|
||||
Assert.AreEqual(1, lID);
|
||||
finally
|
||||
lCustomer.Free;
|
||||
end;
|
||||
|
||||
// the same changing tablename
|
||||
|
||||
lCustomer := TCustomer.Create;
|
||||
try
|
||||
Assert.AreEqual('customers', lCustomer.TableName);
|
||||
lCustomer.TableName := 'customers2';
|
||||
lCustomer.CompanyName := 'bit Time Professionals';
|
||||
lCustomer.City := 'Rome, IT';
|
||||
lCustomer.Note := 'note1';
|
||||
lCustomer.CreationTime := Time;
|
||||
lCustomer.CreationDate := Date;
|
||||
lCustomer.ID := -1; { don't be fooled by the default! }
|
||||
lCustomer.Insert;
|
||||
lID := lCustomer.ID;
|
||||
Assert.AreEqual(1, lID);
|
||||
Assert.IsTrue(lCustomer.LoadByPK(lID));
|
||||
finally
|
||||
lCustomer.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTestActiveRecordBase.TestDefaultFilteringCount;
|
||||
begin
|
||||
TMVCActiveRecord.DeleteAll(TCustomer);
|
||||
|
Loading…
Reference in New Issue
Block a user