#1 2021-11-25 20:27:15

dcoun
Member
From: Crete, Greece
Registered: 2020-02-18
Posts: 416

tlist<record> inside a Torm/Tsqlrecord

Project Project1.exe raised exception class EOrmException with message 'TOrmPropInfoRtti.CreateFrom: Unhandled oftUnknown/rkClass type for property objs'.

I am getting the above error when trying to use the following object

type
Dobjs= packed record iu:integer; nam:string; end;

TOrmtest = class(TOrm)
    private
      FName: RawUTF8;
      Fobjs:tlist<Dobjs>;
    published
      property Name: RawUTF8 index 50 read FName write FName stored AS_UNIQUE;
      property objs: tlist<Dobjs> read Fobjs write Fobjs;
  end;

how can I use a Tlist<record> in a TOrm/TSQLrecord? Should I register it somewhere?

Is it possible to force an array of records (that exists as a property in a Torm/TSQLrecord) to be saved in a TEXT field in the database as JSON Array of JSON objects?

Last edited by dcoun (2021-11-25 20:30:28)

Offline

#2 2021-11-25 22:30:38

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

Re: tlist<record> inside a Torm/Tsqlrecord

It is not supported.

You need to use a dynamic array for such content.
Try with TArray<Dobjs>.

Offline

#3 2021-11-26 06:51:10

dcoun
Member
From: Crete, Greece
Registered: 2020-02-18
Posts: 416

Re: tlist<record> inside a Torm/Tsqlrecord

ab wrote:

It is not supported.

You need to use a dynamic array for such content.
Try with TArray<Dobjs>.

Dobjs is a record.
I usually prefer Tarray<> but in this case this property is created as BLOB and the content is not JSON
With Tlist the content is JSON and the database field is TEXT.
How do I force TArray<Dobjs> to be saved as JSON?
Thank you in advace

Offline

#4 2021-11-26 08:27:59

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

Re: tlist<record> inside a Torm/Tsqlrecord

Then use a RawJson published property.
You could then use a public getter/setter which makes the conversion to/from TArray<Dobjs>.

Offline

#5 2021-11-27 19:05:32

dcoun
Member
From: Crete, Greece
Registered: 2020-02-18
Posts: 416

Re: tlist<record> inside a Torm/Tsqlrecord

After the solution in  https://synopse.info/forum/viewtopic.php?id=6064 My Geter and Seter follow:

function TOrmtest.GetObjs: rawutf8;
begin
result:='';
if assigned(list) then
   for var i in list do
     result:=result+','+RecordSaveJson(i,typeinfo(Dobjs));
if result<>'' then
     result[1]:='[' 
else result:='[';
result:=result+']';
end;

procedure TOrmtest.SetObjs(const Value: rawutf8); 
var
     a:TPUtf8CharDynArray;
     n,o,m:integer;
     c:Dobjs;
     s:rawutf8;
begin
list.clear;
if (value='') or (not JsonArrayDecode(putf8char(value)+1,a)) then exit;
m:=length(a)-1;
for n:=0 to m do
  begin
   if n<m then
     SetString(s,a[n],a[n+1]-a[n]-1)
   else begin
     s:=a[n];
     s:=copy(s,1,length(s)-1);
   end;
  RecordLoadJson(c,s,typeinfo(Dobjs));
  list.Add(c); //list:=list+[c]; for Tarray<Dobjs>
end;
end;

list is a Tlist<Dobjs> (can be also be a TArray<Dobjs>) and GetObjs needs a modification for Delphi's mobile apps

The above implementation results to a database field filled with a Json Array that can be searchable by SQL queries

Comments to improve it are welcome, I am a hobbyist programmer
Mormot2 is really wonderful and many, MANY, many thanks to Arnaud

The above needs also the following for Recordloadjson/Recordsavejson to work:
TRttiJson.RegisterFromText(typeinfo(Dobjs),'iu integer nam string',
[jpoIgnoreUnknownProperty,jpoIgnoreUnknownEnum],[woFullExpand,woStoreStoredFalse,woDateTimeWithZSuffix]);

Last edited by dcoun (2021-11-27 19:40:31)

Offline

#6 2021-11-27 21:46:49

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

Re: tlist<record> inside a Torm/Tsqlrecord

Don't use RecordLoadJson, but just use DynArrayLoadJson for what you need.

It will create a TArray<DObjs> directly from the JSON input array.

I guess this is a simpler solution than calling JsonArrayDecode() - and it will also be faster.
And thanks for the kind words about mORMot 2. big_smile

Offline

#7 2021-11-27 22:19:26

dcoun
Member
From: Crete, Greece
Registered: 2020-02-18
Posts: 416

Re: tlist<record> inside a Torm/Tsqlrecord

if a Tlist<Dobjs> is needed, then the above set/get(ers) is a solution
If a Tarray<Dobjs> is used, you have a magic and effecient solution
I am new to mormot so, I am really missing a lot of procedures/functions
I apologize
With a list:Tarray<Dobjs> the above code is much more simpler:

function TOrmtest.GetObjs: rawutf8;
begin
if assigned(list) then
      result:=DynArraySaveJson(list,typeinfo(Tarray<Dobjs>))
else result:='';
end;

procedure TOrmtest.SetObjs(const Value: rawutf8);
begin
list:=nil;
if value='' then
    exit;
if not DynArrayLoadJson(list,value,typeinfo(Tarray<Dobjs>)) then
    list:=nil;
end;

By the way is the following registration needed with the above code?
TRttiJson.RegisterFromText(typeinfo(Dobjs),'iu integer nam string',
[jpoIgnoreUnknownProperty,jpoIgnoreUnknownEnum],[woFullExpand,woStoreStoredFalse,woDateTimeWithZSuffix]);

Offline

Board footer

Powered by FluxBB