#1 Re: mORMot 2 » woDontStoreVoid in function SaveJson is not working properly » 2025-12-02 06:55:40

Thank you for your guidance. Everything works fine now when the above record is changed to class.

#2 mORMot 2 » woDontStoreVoid in function SaveJson is not working properly » 2025-12-01 16:04:52

idigger
Replies: 3

The following code.

type
{$RTTI EXPLICIT PROPERTIES([vcPublished]) FIELDS([vcPublic]) METHODS([])}
  TReq = packed record
    id: Cardinal;
    desc: UTF8String;
    amount: Double;
    memo: UTF8String;
  end;
{$RTTI EXPLICIT METHODS([]) FIELDS([]) PROPERTIES([])}
var
  req: TReq;
  s: UTF8String;
begin
  with req do begin
    id := 1000;
    desc := 'test';
  end;
  SaveJson(req, TypeInfo(TReq), TEXTWRITEROPTIONS_SETASTEXT[False], s, [woDontStoreVoid]);
  WriteLn(s);
end.

The output is

{"id":1000,"desc":"test","amount":0,"memo":""}

instead of

{"id":1000,"desc":"test"}

I'm using the latest trunk.

#3 Re: mORMot 2 » Errors related to postgresql ORM. » 2025-11-18 08:59:32

Ok. Thank you very much. I'll give it a try.

#4 Re: mORMot 2 » Errors related to postgresql ORM. » 2025-11-18 08:40:57

    rec.Prefix := 'M';  // "char"
    rec.Flag := '2';    // char(1)
    rec.Start := Time;
    rec.Stop := IncMinute(Time, 15);
    Rest.Add(rec, True);   // <-- not work

Rest.Add(rec, True) not work.

ESqlDBException {Message:"Invalid TSqlDBPostgresStatement.Bind(2,TSqlDBFieldType(0),77)"
or
ESqlDBPostgres {Message:"TSqlDBPostgresLib Exec failed: 22001 [ERROR:  value too long for type character(1)

#5 Re: mORMot 2 » Errors related to postgresql ORM. » 2025-11-18 08:19:17

Does ORM not support postgresql's "char" and char(1)?

#6 Re: mORMot 2 » Errors related to postgresql ORM. » 2025-11-17 12:52:54

TDateTime is Ok.

WriteLn(DateTimeToStr(rec.Start), ' ', DateTimeToStr(rec.Stop));
Output: 1899-12-30 8:30:00 1899-12-30 14:30:00
Time is Ok.

#7 Re: mORMot 2 » Errors related to postgresql ORM. » 2025-11-17 12:47:10

Yes, I try with the latest trunk.

ORM has errors in both the "char" and char(1) columns.

ESqlDBException {Message:"Invalid TSqlDBPostgresStatement.Bind(2,TSqlDBFieldType(0),77)"
or
ESqlDBPostgres {Message:"TSqlDBPostgresLib Exec failed: 22001 [ERROR:  value too long for type character(1)

#8 mORMot 2 » Errors related to postgresql ORM. » 2025-11-17 11:51:45

idigger
Replies: 9

Create the following table.

create table if not exists testtbl (
  id int4,
  prefix "char",
  flag char(1),
  start time not null default '08:30:00',
  stop time not null default '14:30:00');

insert into testtbl (id, prefix, flag, start, stop) values (1, 'P', '1', '08:30:00', '14:30:00'); 

Define the following ORM.

  TOrmtesttbl = class(TOrm)
  private
    fPrefix: AnsiChar;
    fFlag: AnsiChar;
    fStart: TTime;
    fStop: TTime;
  published
    property Prefix: AnsiChar read fPrefix write fPrefix;
    property Flag: AnsiChar read fFlag write fFlag;
    property Start: TTime read fStart write fStart;
    property Stop: TTime read fStop write fStop;
  end; 

The following program has an incorrect running result.

    DBProps := TSQLDBPostgresConnectionProperties.Create(
        'localhost', 'testdb', 'root', 'pass'); 
    DBProps.ThreadSafeConnection.Connect;
    Model := TOrmModel.Create([TOrmtesttbl]);
    OrmMapExternal(Model, [TOrmtesttbl], DBProps);

    Rest := TRestServerDB.Create(Model);
    Rest.Model.Owner := Rest;
    Rest.Server.CreateMissingTables;

    rec := Tormtesttbl.Create;
    if Rest.Retrieve(1, rec) then begin
      WriteLn('Prefix: ', rec.Prefix);    // print P   <-- ok
      WriteLn('Flag: ', rec.Flag);        // print 1   <-- ok
      WriteLn(rec.Start, ' ', rec.Stop);  // print 0.0000000000000000E+000  0.0000000000000000E+000  <-- error
    end;

    rec.Prefix := 'M';
    rec.Flag := '2';
    rec.Start := Time;
    rec.Stop := IncMinute(Time, 15);
    Rest.Add(rec, True);   // <-- ESqlDBException {Message:"Invalid TSqlDBPostgresStatement.Bind(2,TSqlDBFieldType(0),77)" 

Complete program.

#9 Re: mORMot 2 » URI Authentication Failed after routing » 2025-10-21 14:03:22

I found that root can be set to the following form and still work without using routing.

Server := TMyServer.Create('myroot/v1');

server output

--- myapi ---
url: myapp/v1/myapi?q=abc&v=123&session_signature=000f36e000014ac1e3a96b48
method: mGET
Parameters: q=abc&v=123&session_signature=000f36e000014ac1e3a96b48
body:{"req": "hello"}

#10 Re: mORMot 2 » URI Authentication Failed after routing » 2025-10-21 13:37:51

URI authentication is also not applicable to the following routes.

HttpServer.Route.Run([urmGet, urmPost], '/app/api', Server.domyapi);

URI authentication currently does not work with routing.
If you want to use URI authentication, you cannot use routing.

#11 Re: mORMot 2 » URI Authentication Failed after routing » 2025-10-18 20:58:29

Ok, sorry, I just saw the forum rules 2 and 7. The post has been edited.

#12 mORMot 2 » URI Authentication Failed after routing » 2025-10-18 08:23:26

idigger
Replies: 4

Compile and execute the following program.

client.pas and server.pas

Run the server and client, and the output is as follows:

server side output

client side output

# client
--- no routed ---
test GET method
r: 200
resp: {"code": 0}

test POST method
r: 200
resp: {"code": 0}

--- routed ---
test GET method
r: 403
resp: {
"errorCode":403,
"errorText":"URI Authentication Failed: Invalid signature (0)"
}

test POST method
r: 403
resp: {
"errorCode":403,
"errorText":"URI Authentication Failed: Invalid signature (0)"
}

#13 Re: mORMot 2 » Parameters lost after routing » 2025-10-17 14:35:48

Great, it was solved so quickly, it works now.

#14 mORMot 2 » Parameters lost after routing » 2025-10-17 10:46:20

idigger
Replies: 2

Compile and execute the following program.

// e:\delphi12\bin\dcc32 servertest.pas -ID:\Borland\mORMot2\src -Ud:\Borland\mORMot2\src\core;d:\Borland\mORMot2\src\crypt;d:\Borland\mORMot2\src\db;d:\Borland\mORMot2\src\lib;d:\Borland\mORMot2\src\orm;d:\Borland\mORMot2\src\net;d:\Borland\mORMot2\src\soa;D:\Borland\mORMot2\src\rest -NSSystem;Winapi
program servertest;

{$apptype console}

{$I mormot.defines.inc}
uses
  {$I mormot.uses.inc} // use FastMM4 on older versions of Delphi
  Windows,
  sysutils,
  classes,
  mormot.core.base,
  mormot.core.log,
  mormot.core.os,      
  mormot.core.rtti,
  mormot.core.text,    
  mormot.net.http,
  mormot.net.server,     
  mormot.rest.server,      
  mormot.rest.memserver,      
  mormot.rest.http.server;

type
  TMyServer = class(TRestServerFullMemory)
  public
    constructor Create(const pmcRootName: RawUtf8); reintroduce;
  published
    procedure myapi(Ctxt: TRestServerUriContext);
  end;

constructor TMyServer.Create(const pmcRootName: RawUtf8);
begin
  CreateWithOwnModel([], FALSE, pmcRootName);
  Server.CreateMissingTables;
end;

procedure TMyServer.myapi(Ctxt: TRestServerUriContext);
begin
  Writeln('--- myapi ---');

  WriteLn('1:', Ctxt.Call.Url);
  WriteLn('2: Parameters: ', Ctxt.Parameters);

  Ctxt.Returns('{"code": 0}', HTTP_SUCCESS, JSON_CONTENT_TYPE_HEADER_VAR);
end;


const
  MYROOT = 'myapp';

procedure Run;
var
  HttpServer: TRestHttpServer;
  Server: TMyServer;
begin
  Server := TMyServer.Create(MYROOT);
  try
    HttpServer := TRestHttpServer.Create('8888', [Server], '+', useHttpAsync);
    try
      HttpServer.Route.Get('/app/api', MYROOT + '/myapi');
      HttpServer.AccessControlAllowOrigin := '*';
      ConsoleWrite('Press [Enter] to quit'#13#10);
      ConsoleWaitForEnterKey;
    finally
      HttpServer.Free;
    end;
  finally
    Server.Free;
  end;
end;

begin
  with TSynlog.Family do
  begin
    Level := LOG_VERBOSE;
    EchoToConsole := LOG_NFO + [sllDebug,sllDB,sllHTTP];
    PerThreadLog := ptIdentifiedInOnFile;
    NoFile := True;
  end;
  try
    Run;
  except
    on E: Exception do
      ConsoleShowFatalException(E);
  end;
  FreeConsole;
end.

The results are as follows.

# servertest.exe
......
Press [Enter] to quit

--- myapi ---
1:myapp/myapi              <--- routing: curl http://127.0.0.1:8888/app/api?q=abc
2: Parameters:
20251017 10372819  5 srvr               mormot.rest.server.TRestServerRoutingRest(035f6390)   Method GET myapi=200 out=11 in 940us
--- myapi ---
1:myapp/myapi?q=abc        <--- no routing: curl http://127.0.0.1:8888/myapp/myapi?q=abc
2: Parameters: q=abc
20251017 10373228  - srvr               mormot.rest.server.TRestServerRoutingRest(035f6390)   Method GET myapi=200 out=11 in 1.88ms

#15 Re: mORMot 2 » Issues regarding the time field in postgresql » 2025-10-13 16:07:31

Great! Everything has been solved. There's no problem with either FPC or Delphi

The results are as follows.

# dbtest
1: 08:30:00-14:30:00      <-- ok
2: 0.35, 0.60             <-- ok
3: 8:30:00-14:30:00       <-- ok

#16 Re: mORMot 2 » Issues regarding the time field in postgresql » 2025-10-13 15:11:05

Thank you for your reply.

Is there any solution for R.start and R.stop.

#17 mORMot 2 » Issues regarding the time field in postgresql » 2025-10-13 14:45:19

idigger
Replies: 4

Compile and execute the following program.
e:\delphi12\bin\dcc32 dbtest.pas -ID:\Borland\mORMot2\src;D:\Borland\mORMot2\static\i386-win32 -Ud:\Borland\mORMot2\src\core;d:\Borland\mORMot2\src\crypt;d:\Borland\mORMot2\src\db;d:\Borland\mORMot2\src\net;D:\Borland\mORMot2\src\lib -NSSystem;Winapi

{
create table if not exists testtbl (
  id int4,
  start time not null default '08:30:00',
  stop time not null default '14:30:00');

insert into testtbl (id, start, stop) values (1, '08:30:00', '14:30:00');
}

program dbtest;

{$ifdef FPC}
{$mode delphi}
{$else}
{$APPTYPE CONSOLE}
{$endif}

{$I mormot.defines.inc}

uses
  {$I mormot.uses.inc}
  {$IFDEF DCC}System.{$ENDIF}Classes, {$IFDEF DCC}System.{$ENDIF}SysUtils,
  Variants,
  mormot.db.sql.postgres;

var
  DBProps: TSQLDBPostgresConnectionProperties;
  R: variant;
  startstr, stopstr: String;
  start, stop: TTime;
begin
  DBProps := TSQLDBPostgresConnectionProperties.Create(
    'localhost', 'testdb', 'root', '12345678');
  try
    DBProps.ThreadSafeConnection.Connect;
    with DBProps.Execute('select * from testtbl limit 1',[],@R) do
      begin
        while Step do begin
         startstr := ColumnUTF8('start');
         stopstr := ColumnUTF8('stop');
         WriteLn('1: ', startstr, '-', stopstr);

         start := ColumnDateTime('start');
         stop := ColumnDateTime('stop');
         WriteLn(Format('2: %f, %f', [start, stop]));

         WriteLn('3: ', VarToStr(R.start), '-', VarToStr(R.stop));

         break;
        end;
        ReleaseRows;
      end;
  except
  end;

  DBProps.Free;
end.

The results are as follows.

# dbtest
1: 08:30:00-14:30:00        <-- ok
2: 0.00, 0.00               <-- error
3: 0:00:00-0:00:00          <-- error

#18 Re: mORMot 2 » DynArrayLoadJson does not work like Delphi in FPC » 2024-06-27 16:00:00

yes, {$modeswitch advancedrecords} is not needed.

#19 Re: mORMot 2 » DynArrayLoadJson does not work like Delphi in FPC » 2024-06-27 14:21:54

After testing, delphi enables rtti record by default, and fpc is off by default.
Replace {$RTTI EXPLICIT PROPERTIES([vcPublished]) FIELDS([]) PROPERTIES([])} with {$RTTI EXPLICIT METHODS([]) FIELDS([vcPublic]) METHODS([])},
project.pas compiled by delphi and the results also failed.

#20 Re: mORMot 1 » M2: different results Delphi/FPC, using RecordLoadJson » 2024-06-27 10:35:55

You're amazing. Everything is working on the new mormot2.

#21 Re: mORMot 2 » DynArrayLoadJson does not work like Delphi in FPC » 2024-06-27 10:26:52

project1.pas adds the following statement before TEFloor = packed record.

{$RTTI EXPLICIT
PROPERTIES([vcPublished])
FIELDS([vcPublic])
METHODS([])}

Recompile and run, everything is fine.

You were amazing.

Thank you for your quick response and quick repair.

#22 mORMot 2 » DynArrayLoadJson does not work like Delphi in FPC » 2024-06-27 03:07:55

idigger
Replies: 6

System Information
- Operating system: Windows
- Processor architecture: x86-64
- Device: Computer
- FPC version: 3.3.1 [2024/06/26] for i386, Trunk 0c745fb257
- mORMot2 version: master 70e2e9ce

Example Project

program project1;

{$ifdef FPC}
{$mode delphi}
{$else}
{$APPTYPE CONSOLE}
{$endif}

{$I mormot.defines.inc}

uses
  {$I mormot.uses.inc}
  {$IFDEF DCC}System.{$ENDIF}Classes, {$IFDEF DCC}System.{$ENDIF}SysUtils,
  mormot.core.base,
  mormot.core.rtti,
  mormot.core.variants,
  mormot.core.json;

type

  {$RTTI EXPLICIT PROPERTIES([vcPublished]) FIELDS([vcPublic]) METHODS([])}

  TEFloor = packed record
    el: WORD;
    fl: array of Byte;
  end;

  TECtrl = packed record
    ecid: WORD;
    expd: array of Byte;
    efl: array of TEFloor;
    icod: UTF8String;
    pt: array of Integer;
    adv: BYTE;
  end;
  TECtrls = Array of TECtrl;

var
  tmp1, tmp2: UTf8String;
  ec: TECtrls;
begin
  tmp1 := '[{"ecid":12,"expd":[80,17,18],"efl":[{"el":0,"fl":[1,2]},{"el":1,"fl":[4,5]}],"icod":"123456","pt":[1,2,3],"adv":5}]';
  DynArrayLoadJson(ec, tmp1, TypeInfo(TECtrls));
  WriteLn(tmp1);

  tmp2 := DynArraySaveJson(ec, TypeInfo(TECtrls));
  WriteLn(tmp2);

  if tmp1 = tmp2 then WriteLn('ok')
  else                WriteLn('failed');

end.

The above programs are compiled with fpc and run as follows.

# fpc project1.pas -Fic:\mORMot2\src -Fuc:\mORMot2\src\core;c:\mORMot2\src\lib -Flc:\mORMot2\static\i386-win32
Free Pascal Compiler version 3.3.1 [2024/06/26] for i386
Copyright (c) 1993-2024 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling project1.pas
Linking project1.exe
895 lines compiled, 0.3 sec, 563504 bytes code, 20004 bytes data

# project1
[{"ecid":12,"expd":[80,17,18],"efl":[{"el":0,"fl":[1,2]},{"el":1,"fl":[4,5]}],"icod":"123456","pt":[1,2,3],"adv":5}]
[]
failed

Relevant 3rd party information

The above program is compiled by delphi and the results are as follows

# dcc32 project1.pas -Ic:\mORMot2\src;c:\mORMot2\static\i386-win32 -Uc:\mORMot2\src\core;c:\mORMot2\src\lib -NSSystem;Winapi
Embarcadero Delphi for Win32 compiler version 36.0
Copyright (c) 1983,2024 Embarcadero Technologies, Inc.
c:\mORMot2\src\mormot.defines.inc(792)
c:\mORMot2\src\mormot.uses.inc(50)
project1.pas(56)
897 lines, 0.11 seconds, 1439256 bytes code, 103032 bytes data.

# project1.exe
[{"ecid":12,"expd":[80,17,18],"efl":[{"el":0,"fl":[1,2]},{"el":1,"fl":[4,5]}],"icod":"123456","pt":[1,2,3],"adv":5}]
[{"ecid":12,"expd":[80,17,18],"efl":[{"el":0,"fl":[1,2]},{"el":1,"fl":[4,5]}],"icod":"123456","pt":[1,2,3],"adv":5}]
ok

I know that using RegisterType and RegisterFromText can solve this problem,

But the latest FPC has supported RTTI record (https://gitlab.com/freepascal.org/fpc/s … sues/40798)

Just request improvements to mORMot2 DynArrayLoadJson in FPC.
May mORMot2 get better and better!

#23 Re: mORMot 1 » M2: different results Delphi/FPC, using RecordLoadJson » 2024-06-26 18:03:59

The latest FPC has supported RTTI record (https://gitlab.com/freepascal.org/fpc/s … sues/40798)

Request improvements to mormot2 DynArrayLoadJson in FPC.

Board footer

Powered by FluxBB