#1 2014-12-01 14:07:33

AntonE
Member
Registered: 2012-02-03
Posts: 74

mORMot to Nested TClientdataset... and back again. ORMCDS unit

I wrote a unit to convert TSQLRecord and it's sub-arrays/records to Nested TClientdatasets.

Some key features:

  • Create TClientdataset hierarchy dynamically based on data.

  • Also work with static TClientDatasets+Static fields.

  • Handle sub-TSQLRecord lists. (See sample)

  • Convert Set of ENUM to/from multiple Boolean fields for grid checkboxes

  • Most importantly: Apply delta-changes back to mORMot. i.e. only changed fields.

  • (With RTTI adjustments), should work on any platform that support TClientdataset, e.g. Intraweb

It is very first version so not tested on insert/delete yet nor many types of data, guaranteed to be buggy & lacking at this stage, but working.

ftp://ftp.true.co.za/ORMCDS.7z (Working in Delphi XE4 with JEDI installed for TJvDBUltimGrid, change to TDBGrid if needed.)

In demo:
Choose Static or Dynamic demo, select 'Load' to load data, edit any field or nested data, click 'Apply'.
Best is to see code to get more info.
My first try with RTTI and new at mORMot so I'm sure it could have been done more elegantly with mORMot's RTTI built-support.
Also not optimized for speed but should be pretty fast.

Regards
Antone

Last edited by AntonE (2014-12-01 16:15:08)

Offline

#2 2014-12-01 15:45:10

miab3
Member
From: Poland
Registered: 2014-10-01
Posts: 188

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

@AntonE,

Nice, but could you use the convention?

ATypeInfo^.TypeData^.ClassType => GetTypeData(ATypeInfo).ClassType
BInfo.CDS.RecNo.ToString => IntToStr(BInfo.CDS.RecNo)

Older Delphi (eg. XE2) does not compile this.

Michal

Last edited by miab3 (2014-12-01 15:46:14)

Offline

#3 2014-12-01 16:17:22

AntonE
Member
Registered: 2012-02-03
Posts: 74

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

Thanks for that, I updated the files.

Offline

#4 2014-12-03 07:28:18

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,662
Website

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

Nice.
I've uploaded this project to the "Third party" folder.
See http://synopse.info/fossil/info/6babeae8b2

May be a good start to enhance our TSynVirtualDataSet so that it would support updates.

Offline

#5 2014-12-03 18:36:55

AntonE
Member
Registered: 2012-02-03
Posts: 74

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

Ok, I've improved quite a bit since that version, will upload soon.
I'll check out TSynVirtualDataset. smile
AntonE

Offline

#6 2014-12-16 14:53:50

AntonE
Member
Registered: 2012-02-03
Posts: 74

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

I uploaded an updated version to that same link above.
Fixed a few bugs a.o. adding/deleting items in a DynArray.
However, I have a problem with memory leaks using DynArrays, but only when resizing them. It seems when a copy is made, I'm not deferencing the old copy properly.
If I run FastMM4 in FullDebugMode I even get error that memory that is freed are referenced and the app crash. Without FullDebugMode I get AnsiString memory leaks (when resizing arrays) but the app works fine. (Win32). In ORMCDS.pas lines 537 onwards is where the trouble lies I think.
I've tried various methods, using mORMot TDynArray and Rtti but it seems it's in the usage of TValue that old reference to array does not get cleaned up, so not production ready yet. smile

Regards

Offline

#7 2014-12-16 17:43:08

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,662
Website

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

You should better not use TValue kind of storage, but directly the RTTI functions available in mORMot.pas.

Offline

#8 2014-12-17 10:00:22

AntonE
Member
Registered: 2012-02-03
Posts: 74

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

Hey Arnaud, thanks for doing this to my little unit. smile

I'm redoing it in a more mORMot way using TSQLPropInfoRtti family.
How do I get a DynArray element type from TSQLPropInfoRTTIDynArray ?
Once I have an instance, I can get it from TDynArray.ElemType but I need to construct from TSQLRecordClass.
...or must I still use Delphi Rtti to get that?

Also, if a DynArray have Record as element type, how do I get TSQLPropInfoRecordRTTI for that type? I can only see how to construct TSQLPropInfoRecordRTTI as a new member, don't know how to reference it for arbitrary type.

Thanks
Regards

Last edited by AntonE (2014-12-17 11:00:42)

Offline

#9 2014-12-17 11:15:12

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,662
Website

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

Sorry for the mind crash...

Take a look at the following section of mORMot.pas:

{ ************ some RTTI and SQL mapping routines }

and use directly PClassProp and PPropInfo to work with objects, and our PTypeInfo as a low-level object type, instead of TypInfo.pas.
BTW using these structures instead of the Delphi RTTI.pas unit would also make your code FPC compatible, or also work with older versions of Delphi. smile

Offline

#10 2014-12-17 19:21:21

AntonE
Member
Registered: 2012-02-03
Posts: 74

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

I'm afraid I'm still a bit in the dark with mORMot's Rtti. Using TSQLRecord is easy with PPropInfo, etc.
But how do I enumerate a record type similar to this with mORMot's built-in functions ?:

function EnumRecordType(ATypeInfo:PTypeInfo):RawUTF8;
var Ctx : TRttiContext;
    Rec : TRttiRecordType;
    Fld : TRttiField;
begin
 Ctx:=TRttiContext.Create;
 Rec:=TRttiRecordType(Ctx.GetType(ATypeInfo));
 for Fld in Rec.GetFields do
  Result:=Result+Fld.Name+' : '+Fld.FieldType.Handle^.Name+#13#10;
 Ctx.Free;
end;

Trying to use code below but do not know how to get record field names:

function EnumRecordType(ATypeInfo:PTypeInfo):RawUTF8;
var RecType  : PRecordType;
    RecField : PRecordField;
begin;
 RecType:=ATypeInfo^.RecordType;
 for I:=0 to Pred(RecType.Count) do
  begin
   RecField:=@RecType.Fields[i];
   (*How to get field name, not just type name*)
   Result:=Result+RecField^.TypeInfo^.{Field?}Name+' : '+RecField^.TypeInfo^.Name;
   case RecField^.TypeInfo^.Kind of
    tkDynArray   : begin

                   end;
   end;
  end;

TSQLPropInfoRecordRTTI seems to have the fields/methods I need but it is only used as an object's published properties? Or how can I instantiate it for any record type?

Thanks
AntonE

Offline

#11 2014-12-18 09:24:46

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,662
Website

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

The property name is at PClassProp level AFAIR.

PClassProp is to be used with published class properties, not records.

Offline

#12 2014-12-18 11:13:30

Kobe
Member
Registered: 2013-04-08
Posts: 38

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

Sorry to post here. But there is an error when you try to create a new Post new topic on this forum:

An error was encountered
Error: Could not connect to smtp host "217.70.184.11" (110) (Connection timed out).

Last edited by Kobe (2014-12-18 11:15:45)

Offline

#13 2014-12-18 11:35:33

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,662
Website

Re: mORMot to Nested TClientdataset... and back again. ORMCDS unit

The DNS client of our linux box was just not working any more.
After a server reboot, should be fixed now.
smile

Offline

Board footer

Powered by FluxBB