mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 07:45:54 +01:00
Added MVCActiveRecord feature which allows to map a boolean object attribute to integer field on the actual table.
This commit is contained in:
parent
88127a7b44
commit
ec9140f2a7
@ -601,6 +601,25 @@ type
|
||||
end;
|
||||
|
||||
|
||||
[MVCTable('integers_as_booleans')]
|
||||
TIntegersAsBooleans = class(TMVCActiveRecord)
|
||||
private
|
||||
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
|
||||
FID: NullableInt64;
|
||||
[MVCTableField('done_int', 'int2')]
|
||||
FDoneAsInteger: Integer;
|
||||
[MVCTableField('done_bool')]
|
||||
FDoneAsBoolean: Boolean;
|
||||
procedure SetDoneAsBoolean(const Value: Boolean);
|
||||
procedure SetDoneAsInteger(const Value: Integer);
|
||||
procedure SetID(const Value: NullableInt64);
|
||||
public
|
||||
property ID: NullableInt64 read FID write SetID;
|
||||
property DoneAsBoolean: Boolean read FDoneAsBoolean write SetDoneAsBoolean;
|
||||
property DoneAsInteger: Integer read FDoneAsInteger write SetDoneAsInteger;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
@ -785,4 +804,21 @@ begin
|
||||
fFullName := GetFullName;
|
||||
end;
|
||||
|
||||
{ TIntegersAsBooleans }
|
||||
|
||||
procedure TIntegersAsBooleans.SetDoneAsBoolean(const Value: Boolean);
|
||||
begin
|
||||
FDoneAsBoolean := Value;
|
||||
end;
|
||||
|
||||
procedure TIntegersAsBooleans.SetDoneAsInteger(const Value: Integer);
|
||||
begin
|
||||
FDoneAsInteger := Value;
|
||||
end;
|
||||
|
||||
procedure TIntegersAsBooleans.SetID(const Value: NullableInt64);
|
||||
begin
|
||||
FID := Value;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -2,7 +2,7 @@ object MainForm: TMainForm
|
||||
Left = 0
|
||||
Top = 0
|
||||
Caption = 'TMVCActiveRecord - ShowCase'
|
||||
ClientHeight = 569
|
||||
ClientHeight = 593
|
||||
ClientWidth = 1104
|
||||
Color = clBtnFace
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
@ -14,7 +14,7 @@ object MainForm: TMainForm
|
||||
OnShow = FormShow
|
||||
DesignSize = (
|
||||
1104
|
||||
569)
|
||||
593)
|
||||
TextHeight = 13
|
||||
object btnCRUD: TButton
|
||||
Left = 8
|
||||
@ -38,7 +38,7 @@ object MainForm: TMainForm
|
||||
Left = 280
|
||||
Top = 8
|
||||
Width = 816
|
||||
Height = 553
|
||||
Height = 577
|
||||
Anchors = [akLeft, akTop, akRight, akBottom]
|
||||
Ctl3D = True
|
||||
DoubleBuffered = True
|
||||
@ -56,7 +56,7 @@ object MainForm: TMainForm
|
||||
WantReturns = False
|
||||
WordWrap = False
|
||||
ExplicitWidth = 812
|
||||
ExplicitHeight = 552
|
||||
ExplicitHeight = 576
|
||||
end
|
||||
object btnRelations: TButton
|
||||
Left = 8
|
||||
@ -285,6 +285,15 @@ object MainForm: TMainForm
|
||||
TabOrder = 27
|
||||
OnClick = btnVirtualEntitiesClick
|
||||
end
|
||||
object btnIntegersAsBool: TButton
|
||||
Left = 8
|
||||
Top = 522
|
||||
Width = 121
|
||||
Height = 34
|
||||
Caption = 'Integers As Booleans'
|
||||
TabOrder = 28
|
||||
OnClick = btnIntegersAsBoolClick
|
||||
end
|
||||
object FDConnection1: TFDConnection
|
||||
Left = 312
|
||||
Top = 40
|
||||
|
@ -60,6 +60,7 @@ type
|
||||
btnRefresh: TButton;
|
||||
btnNamedQuery: TButton;
|
||||
btnVirtualEntities: TButton;
|
||||
btnIntegersAsBool: TButton;
|
||||
procedure btnCRUDClick(Sender: TObject);
|
||||
procedure btnInheritanceClick(Sender: TObject);
|
||||
procedure btnMultiThreadingClick(Sender: TObject);
|
||||
@ -90,6 +91,7 @@ type
|
||||
procedure btnRefreshClick(Sender: TObject);
|
||||
procedure btnNamedQueryClick(Sender: TObject);
|
||||
procedure btnVirtualEntitiesClick(Sender: TObject);
|
||||
procedure btnIntegersAsBoolClick(Sender: TObject);
|
||||
private
|
||||
procedure Log(const Value: string);
|
||||
procedure LoadCustomers;
|
||||
@ -388,10 +390,15 @@ begin
|
||||
lCustWithGUID.LoadByPK(lIDGUID);
|
||||
lCustWithGUID.Code.Value := '😉9012🙂';
|
||||
lCustWithGUID.Update;
|
||||
|
||||
lCustWithGUID.GUID := TGUID.NewGuid;
|
||||
lCustWithGUID.Insert;
|
||||
finally
|
||||
lCustWithGUID.Free;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
lCustWithGUID := TMVCActiveRecord.GetByPK<TCustomerWithGUID>(lIDGUID);
|
||||
try
|
||||
lCustWithGUID.Delete;
|
||||
@ -481,6 +488,55 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnIntegersAsBoolClick(Sender: TObject);
|
||||
begin
|
||||
Log('** Bool as Integer');
|
||||
Log(' Only in the mapping layer it is possibile to map an integer field used ');
|
||||
Log(' as boolean with values (0,1) as a boolean property');
|
||||
Log(' --> (False is stored as 0, True is stored as 1) <--');
|
||||
TMVCActiveRecord.DeleteAll(TIntegersAsBooleans);
|
||||
|
||||
for var I := 0 to 1 do
|
||||
begin
|
||||
for var b := False to True do
|
||||
begin
|
||||
var lTest1 := TIntegersAsBooleans.Create;
|
||||
try
|
||||
lTest1.DoneAsBoolean := b;
|
||||
lTest1.DoneAsInteger := I;
|
||||
lTest1.Store;
|
||||
finally
|
||||
lTest1.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ** WARNING **
|
||||
While mapping layer recognize a boolean stored as integer, queries must still
|
||||
use the actual type (integer) instead of the mapped types}
|
||||
Assert(2 = TMVCActiveRecord.Count<TIntegersAsBooleans>('eq(doneasboolean,true)'));
|
||||
Assert(2 = TMVCActiveRecord.Count<TIntegersAsBooleans>('eq(doneasinteger,1)')); {the boolean attribute as integer}
|
||||
Assert(1 = TMVCActiveRecord.Count<TIntegersAsBooleans>('and(eq(doneasboolean,true),eq(doneasinteger,1))'));
|
||||
Assert(1 = TMVCActiveRecord.Count<TIntegersAsBooleans>('and(eq(doneasboolean,false),eq(doneasinteger,0))'));
|
||||
|
||||
var lList := TMVCActiveRecord.SelectRQL<TIntegersAsBooleans>('sort(+id)', 10);
|
||||
try
|
||||
Assert(lList.Count = 4);
|
||||
var lIdx := 0;
|
||||
for var I := 0 to 1 do
|
||||
begin
|
||||
for var b := False to True do
|
||||
begin
|
||||
Assert(b = lList[lIdx].DoneAsBoolean);
|
||||
Assert(I = lList[lIdx].DoneAsInteger);
|
||||
Inc(lIdx);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
lList.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnJSON_XML_TypesClick(Sender: TObject);
|
||||
var
|
||||
lCTypes: TComplexTypes;
|
||||
|
Binary file not shown.
@ -95,5 +95,11 @@ create table phones (
|
||||
id_person integer not null references people(id)
|
||||
);
|
||||
|
||||
create table integers_as_booleans (
|
||||
id bigint generated by default as identity primary key,
|
||||
done_bool boolean not null,
|
||||
done_int smallint not null
|
||||
);
|
||||
|
||||
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;
|
||||
|
@ -97,3 +97,8 @@ CREATE TABLE nullables_test (
|
||||
f_blob varchar(max)
|
||||
);
|
||||
|
||||
create table integers_as_booleans (
|
||||
id bigint not null identity primary key,
|
||||
done_bool bit not null,
|
||||
done_int smallint not null
|
||||
);
|
@ -55,7 +55,7 @@ CREATE TABLE customers_with_code (
|
||||
|
||||
|
||||
CREATE TABLE customers_with_guid (
|
||||
idguid binary(16) NOT NULL,
|
||||
idguid char(36) NOT NULL,
|
||||
code varchar(20) NULL,
|
||||
description varchar(200) NULL,
|
||||
city varchar(200) NULL,
|
||||
@ -109,5 +109,11 @@ create table phones (
|
||||
id_person integer not null references people(id)
|
||||
);
|
||||
|
||||
create table integers_as_booleans (
|
||||
id bigint not null auto_increment primary key,
|
||||
done_bool boolean not null,
|
||||
done_int smallint not null
|
||||
);
|
||||
|
||||
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;
|
||||
|
@ -392,6 +392,14 @@ CREATE TABLE public.phones (
|
||||
|
||||
ALTER TABLE public.phones OWNER TO postgres;
|
||||
|
||||
|
||||
|
||||
create table integers_as_booleans (
|
||||
id bigint not null generated by default as identity primary key,
|
||||
done_bool boolean not null default false,
|
||||
done_int smallint not null default 0
|
||||
);
|
||||
|
||||
--
|
||||
-- TOC entry 217 (class 1259 OID 58912)
|
||||
-- Name: phones_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
|
||||
|
@ -1139,16 +1139,17 @@ begin
|
||||
end;
|
||||
ftInteger, ftSmallint, ftShortint, ftByte:
|
||||
begin
|
||||
// sqlite doesn't support boolean, so are identified as integers
|
||||
// so we need to do some more checks...
|
||||
// recognize "smallintegers" mapped to boolean attribute
|
||||
if (aRTTIField.FieldType.TypeKind = tkEnumeration) and (aRTTIField.FieldType.Handle = TypeInfo(Boolean)) then
|
||||
begin
|
||||
aRTTIField.SetValue(AObject, AField.AsInteger = 1);
|
||||
end
|
||||
else if (aRTTIField.FieldType.TypeKind = tkEnumeration) then
|
||||
// general enumerations
|
||||
else if (aRTTIField.FieldType.TypeKind = tkEnumeration) then
|
||||
begin
|
||||
TValue(AField.AsInteger).ExtractRawData(PByte(Pointer(AObject)) + aRTTIField.Offset);
|
||||
end
|
||||
// plain integers
|
||||
else
|
||||
begin
|
||||
aRTTIField.SetValue(AObject, AField.AsInteger);
|
||||
|
Loading…
Reference in New Issue
Block a user