#1 Re: mORMot 2 » TThreadList Naming Conflict in the Latest Version » 2026-04-03 17:43:12

Thank you so much—everything is working fine now.

#2 Re: mORMot 2 » TThreadList Naming Conflict in the Latest Version » 2026-04-03 17:01:05

You're right. Thanks for the suggestion—I'm going to modify the program now.

#3 mORMot 2 » TThreadList Naming Conflict in the Latest Version » 2026-04-03 16:21:28

idigger
Replies: 4

A naming conflict between the `TThreadList` in the latest version of `mormot.core.threads.pas` and FPC's `TThreadList` is causing the project compilation to fail.

#5 mORMot 2 » The latest trunk is failing to compile with Delphi 12.3 » 2026-03-25 14:10:31

idigger
Replies: 2
[dcc32 Error] mormot.net.sock.windows.inc(552): E2441 Inline function declared in interface section must not use local symbol 'PSockAddr'
[dcc32 Fatal Error] mormot.net.sock.pas(4163): F2084 Internal Error: D13574

#6 Re: mORMot 2 » DynArrayLoadJson does not work in Delphi 2007 » 2026-02-06 17:09:47

My backend service program is using the latest FPC trunk, but my front end is an old project and can only use Delphi 2007. Therefore, we can only hope to use DynArraySaveJsonBase64 in the backend and DynArrayLoadJsonBase64 in the front end.

#7 Re: mORMot 2 » DynArrayLoadJson does not work in Delphi 2007 » 2026-02-06 13:46:26

The problem has been identified. In the above code, simply change "s" to "s := '{"code":200,"orders":["￰AAACAAAAAAEAAAABAAAAAQAAAAIAAAA="]}';" and there will be no issues. That Base64 string is the binary Base64 encoding of the "orders" array.


It would be much more convenient if the functions DynArraySaveJsonBase64 and DynArrayLoadJsonBase64 could be provided, just like the existing RecordSaveBase64/RecordLoadBase64 functions.

#8 mORMot 2 » DynArrayLoadJson does not work in Delphi 2007 » 2026-02-06 09:23:21

idigger
Replies: 3
  TOrder = record
    id: Integer;
    amount: Integer;
  end;
  TOrders = array of TOrder; 

  s := '{"code":200,"orders":[{"id":1,"amount":1},{"id":2,"amount":2}]}';
  V := _Json(s);
  DynArrayLoadJson(orders, VariantSaveJson(V.orders), TypeInfo(TOrders));
  WriteLn(Length(orders));

The code above results in Length(orders)==0 in Delphi 2007, but 2 in Delphi 12 and Lazarus.

I remember it working fine before, but now it suddenly stops working. Even reverting to an older version of the mormot2 repository doesn't work anymore. It's really strange.

Additionally, in Lazarus, VariantSaveJson must be added before V.orders in the DynArrayLoadJson statement above, but not in Delphi.

#10 mORMot 2 » Could not compile used unit 'mormot.core.unicode.pas' at commit 671855 » 2026-02-05 10:51:59

idigger
Replies: 3

Could not compile used unit 'mormot.core.unicode.pas' at commit 671855 in delphi 2007 and 12.

[dcc32 Error] mormot.core.unicode.pas(9263): E2250 There is no overloaded version of 'UnCamelCase' that can be called with these arguments
[dcc32 Fatal Error] mormot.net.client.pas(1081): F2063 Could not compile used unit 'mormot.core.unicode.pas'

Compiled successfully in Lazarus 4.99 (rev main_4_99-3381-g9ac18157ff) FPC 3.3.1 i386-win32-win32/win64.

Addition:
Compiled successfully at commit 8ef39ea5494e137cae69fe6cee309317f4d5122f in delphi 2007 and 12.

Again:
Compile error at commit a4df3929145701d11cb35bcb8ed3abf27b9c4874 in delphi 2007 and 12.

[dcc32 Error] mormot.core.unicode.pas(9284): E2250 There is no overloaded version of 'UnCamelCase' that can be called with these arguments
[dcc32 Error] mormot.core.unicode.pas(9295): E2250 There is no overloaded version of 'UnCamelCase' that can be called with these arguments
[dcc32 Error] mormot.core.unicode.pas(9297): E2010 Incompatible types: 'PUtf8Char' and 'PAnsiChar'
[dcc32 Error] mormot.core.unicode.pas(9304): E2010 Incompatible types: 'PUtf8Char' and 'PAnsiChar'
[dcc32 Fatal Error] mormot.net.client.pas(1081): F2063 Could not compile used unit 'mormot.core.unicode.pas'

Finally:
Compiled successfully at commit 90bf2eb9826e62630e203c643ef6c264db6950c0 in delphi 2007 and 12 and Lazarus.

#11 mORMot 2 » Compilation error occurred for mormot.net.server.pas at commit 5e01887 » 2026-01-25 15:43:45

idigger
Replies: 1
Compile package mormot2 2.4: Exit code 1, Errors: 5
mormot.net.server.pas(2760,5) Error: Identifier not found "delay"
mormot.net.server.pas(2767,28) Error: Identifier not found "delay"
mormot.net.server.pas(2777,10) Error: Identifier not found "delay"
mormot.net.server.pas(2778,13) Error: Identifier not found "delay"
mormot.net.server.pas(2778,20) Error: Identifier not found "delay"

#12 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.

#13 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.

#14 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.

#15 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)

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

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

#17 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.

#18 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)

#19 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.

#20 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"}

#21 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.

#22 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.

#23 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)"
}

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

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

#25 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

#26 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

#27 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.

#28 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

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

yes, {$modeswitch advancedrecords} is not needed.

#30 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.

#31 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.

#32 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.

#33 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!

#34 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