#1 mORMot 2 » Orm with Boolean type and Batch » 2026-02-01 17:22:21

rcla
Replies: 0

Basically, I'm using ORM with an external PostgreSQL database.

  
  TOrmBuy = class(TOrm)
  private
    fcant: integer;
    fprice: integer;
    fdescrip: RawUtf8;
    factive: Boolean;
    fexpimp: Boolean;
  published
    property cant: integer read fcant write fcant;
    property price: integer read fprice write fprice;
    property descrip: RawUtf8 read fdescrip write fdescrip;
    property active: Boolean read factive write factive;
    property expimp: Boolean read fexpimp write fexpimp;
  end;
  
  myBuy := TOrmBuy.Create;
  
  //This is filled in with the respective data 
  //Just to give one example (The values are actually filled in another function) 
  for i := 0 to 300 do
  begin
    myBuy.cant := 3;
    myBuy.active := True;
    ServerDB.Add(myBuy, True);
  end;

 
It works perfectly well. But obviously it will take some time.
 
That's why I decided to use Batch.

  myBatch := TRestBatch.Create(ServerDB.Orm,nil); 
  
  for i := 0 to 300 do
  begin
    myBuy.cant := 3;
    myBuy.active := True;
    myBatch.Add(myBuy,True);
  end;
  
  cresu := ServerDB.BatchSend(myBatch);

 
But there is an exception and it doesn't work:
TSqlDBPostgresLib Error "active" is type boolean but the expression is of type bigint

I understand that SQLite doesn't have a boolean type, but why does it work without Batch?

What do I need to do to make it work?

Thank you for any help you can provide.

#2 Re: mORMot 2 » More mORMot2 examples: adapted from DMVCframework » 2025-12-25 15:57:44

@Javierus , Thank you very much for all that number of examples, in addition to all the SAD documentation that you have provided.

I'm using FPC 3.2.3 (fixes) with Windows 11 and wanted to learn about HTTP Basic Authentication.
So I took the "08-basicauth" example, but I ran into the following issues:

  1. It was showing a related error that "RegisterInterfaces" was missing...
    I fixed it by adding the following code to the "api.interfaces.pas" file:

    initialization
      TInterfaceFactory.RegisterInterfaces([TypeInfo(IBasicAuthApi)]);
  2. Inside the Log file, an error related to "useHttpApiRegisteringURI" is displayed.
    "TRestHttpServer(06222840) Create: HttpSetServiceConfiguration() failed: ERROR_ACCESS_DENIED (5) for root - useHttpApiRegisteringURI may need admin rights"
    "EXC   ERestHttpServer {Message:"TRestHttpServer: http.sys URI registration error ERROR_ACCESS_DENIED for http://+:8080/root (you need to register the URI - try to use useHttpApiRegisteringURI)"}"
    I solved it by changing from "HTTP_DEFAULT_MODE" to "useHttpAsync"

      // Create HTTP server
      fHttpServer := TRestHttpServer.Create(aPort, [fRestServer],
        '+', useHttpAsync, {threaded=}32); 
  3. It showed several memory leaks when exiting the program.
    I solved it by adding a variable "fModel: TOrmModel;" and you don't need to free "fBasicAuthApi"

      // Create in-memory REST server (no database needed)
      fModel := TOrmModel.Create([]);
      fRestServer := TRestServerFullMemory.Create(
        fModel, 'root', {authentication=}true); 
    
    destructor TBasicAuthServer.Destroy;
    begin
      Stop;
      fHttpServer.Free;
      //fBasicAuthApi.Free;
      fModel.Free;
      fRestServer.Free;
      inherited Destroy;
    end;
  4. The program did not work correctly, with or without authentication it did not show the expected results. 
    After spending hours understanding how it worked, I found that the problem is with "methodName"

    For some reason "Ctxt.UriMethodPath" always returns empty.
    And within the code you have to:

      methodName := Ctxt.UriMethodPath;
      if methodName = '' then
      begin
        // Fallback to full URI
        methodName := Ctxt.Call^.Url;
      end;

    The problem is that it returns the entire Url.
    For example, we obtain that:
    methodName ="root/BasicAuthApi.PublicSection" , but it was expected that methodName ="PublicSection"
    methodName ="root/BasicAuthApi.OnlyRole2" , but it was expected that methodName ="OnlyRole2"
    methodName ="root/BasicAuthApi.OnlyRole1Json?par1=hello" , but it was expected that methodName ="OnlyRole1Json"

    I solved it by doing the following code (maybe not the best solution, but it works)

      methodName := Ctxt.UriMethodPath;
      if methodName = '' then
      begin
        tmpUrl := Ctxt.Call^.Url;
        mPosIni := PosI('.',tmpUrl) + 1;
        mPosEnd := PosI('?',tmpUrl);
        if mPosEnd >0 then
          mLen :=  mPosEnd - mPosIni
        else
          mLen := length(tmpUrl);
        methodName := Copy(tmpUrl,mPosIni,mLen);
      end;

#4 Re: mORMot 2 » Use of DynArrayLoadCsv » 2025-12-20 10:04:24

Currently, the "DynArrayLoadCsv" function only allows csv file content to have a delimiter/separator ','.

IMHO, the function should have the option (not mandatory) to specify the delimiter/separator.

Respectfully, I propose changing the definition to: (It does not affect programs that have already been created.)

function TDynArrayLoadCsv(var Value: TDynArray; Csv: PUtf8Char;
  Intern: TRawUtf8Interning = nil; CommaSep: AnsiChar=','): boolean;

function DynArrayLoadCsv(var Value; const Csv: RawUtf8; TypeInfo: PRttiInfo;
  Intern: TRawUtf8Interning = nil; CommaSep: AnsiChar=','): boolean;

And its respective implementation code: (I've only changed the constant ',' to a variable "CommaSep: AnsiChar")

An example of using a CSV file containing the semicolon ';' delimiter/separator:


if DynArrayLoadCsv(csvItems, csvContent, TypeInfo(TCsvItems), nil, ';') then
begin
  
end;

#5 Re: mORMot 2 » Use of DynArrayLoadCsv » 2025-12-19 18:41:33

zen010101 wrote:

initialization
    // Register RTTI before any CSV parsing
    Rtti.RegisterFromText([TypeInfo(TCsvItem), _TCsvItem]);

https://github.com/zen010101/Claude_Mor … array-demo


Thank you so much for your help and explanation, and the example you did with Claude is great.

One small detail I encountered with your example when opening it with FPC is that the executable path is in the "bin" folder, while the "test.csv" file is in the root directory.
And obviously, a message appears indicating that it can't be found.

The generated documentation is excellent: very concise and detailed in your example.


Thank you for taking the time to provide the solution and create an excellent example.

#6 mORMot 2 » Use of DynArrayLoadCsv » 2025-12-18 23:42:18

rcla
Replies: 6

I have a "test.csv" file that only contains:

qty,price
4,50
12,100

I'm a beginner in mORMot2 and I'm trying to use the "DynArrayLoadCsv" function, but it always returns false:

type
  TCsvItem = packed record
    qty: integer;
    price: integer;
  end;
  TCsvItems = array of TCsvItem; 

var
  csvItems: TCsvItems;
  csvContent: RawUtf8;

  csvContent := RawUtf8FromFile('test.csv'); 

  if DynArrayLoadCsv(csvItems, csvContent, TypeInfo(TCsvItems)) then
    writeln('DynArrayLoadCsv OK')
  else
    writeln('DynArrayLoadCsv Failed'); 

I tried changing the delimiter in the csv file from "," to ";" but it's still the same.

This is the complete code for the simple test program, including the CSV file.

I would appreciate any guidance you can provide.

#7 Re: mORMot 2 » Newbie with PostgreSQL Pipeline Mode » 2025-12-17 17:07:20

The idea is basically the same as that used in the published example techempower-bench

After several tests, he concluded that to avoid this exception, a "GetPipelineResult" is required for each SQL statements sent.
And it's consistent with the operation of Pipeline mode.

This would be the corrected code for the one initially proposed.

I ran tests with several SQL statements sent to different tables in my database and it it works like a charm.

The goal/purpose is to use Pipeline mode for better PostgreSQL performance on slow networks.

Again, thank you very much for the excellent work done with mORMot2.

#8 mORMot 2 » Newbie with PostgreSQL Pipeline Mode » 2025-12-16 17:21:14

rcla
Replies: 2

I had never worked with PostgreSQL's pipeline mode before.

After reading about it, For example this article.

I see that it has some advantages, and the best part is that mORMot2 has it implemented.

I implemented the following code , and it works! : the respective price values are updated in the database.

However, I'm getting the following exception when trying to release the connection, specifically with pConn.CheckPipelineSync.

TSqlDBPostgresConnection.CheckPipelineSync returned 1 instead of PGRES_PIPELINE_SYNC [] 

Any help you can provide would be greatly appreciated.

#9 mORMot 2 » TWebSocketProcess and SendFrameJson » 2025-12-15 17:15:52

rcla
Replies: 0

TWebSocketProtocolChat has the SendFrameJson function.

Is it possible to add this function to TWebSocketProcess?

Something like:

function TWebSocketProcess.SendFrameJson(const Json: RawUtf8): boolean;
var
  frame: TWebSocketFrame;
begin
  frame.opcode := focText;
  frame.content := [];
  frame.tix := 0;
  FastSetRawByteString(frame.payload, pointer(Json), length(Json)); // temp copy
  result := SendFrame(frame)
end;

#10 Re: mORMot 2 » Example Echo with TWebSocketAsyncServer » 2025-12-13 16:56:33

Javierus wrote:

IMO, that kind of simple examples is prefect for anyone approaching mORMot2; what for an expert is "just ..." for a newcomer is "ah, that's what I was looking for"

IMHO, I agree with you.

Thanks.

#11 Re: mORMot 2 » Example Echo with TWebSocketAsyncServer » 2025-12-13 16:51:42

ab wrote:

Thanks for the feedback and interest.

I guess it is just
https://github.com/synopse/mORMot2/blob … server.dpr
but using THttpWebsocketAsyncServer class, isn't it?

Almost, it also has DoOnRequest which loads the file "restws_simpleechoserver.html"

#12 mORMot 2 » Example Echo with TWebSocketAsyncServer » 2025-12-13 15:58:40

rcla
Replies: 5

I have done Example of an asynchronous HTTP WebSocket Echo Server with TWebSocketAsyncServer.

Point your browser to http://localhost:8888/ for initial page using the existing file "restws_simpleechserver.html"

Full Code

What I've noticed is that when connecting for the first time, "Sender.Protocol.ConnectionID" starts at 2 or 3, not 1.

I hope this example is helpful and can be included in the official mORMot2 GitHub repository.

Thank you very much for such excellent work.

Board footer

Powered by FluxBB