#1 mORMot 1 » Reference from SynSelfTests to ECCProcess in SQLite3 samples » 2021-09-18 17:36:45

Beertjie
Replies: 1

I'm following the documentation section "26.4.4. Writing your project for FPC".

The minimal application example given there is this:

program LinuxSynTestFPCLinuxi386;

{$I Synopse.inc}
{$APPTYPE CONSOLE}

uses
  {$I SynDprUses.inc}
  mORMotSelfTests;

begin
  SQLite3ConsoleTests;
end.

However, for me this program failed to compile due to a reference to a .pas file in the SQLite3 samples directory! It turns out the SynSelfTests unit depends on a unit there only for FPC:

ECCProcess {$ifdef FPC} in '.\SQLite3\Samples\33 - ECC\ECCProcess.pas' {$endif},

I suppose I could add this sample project to my search path, but I must admit I was surprised to find the test code tightly coupled to the samples. Or is there something else going on that I'm missing?

#2 Re: mORMot 1 » Errors compiling SynCommons in FPC (64-bit Linux) » 2021-09-06 06:03:15

I didn't realize how old my FPC version is. I will upgrade to 3.2 and try again. Thanks!

#3 mORMot 1 » Errors compiling SynCommons in FPC (64-bit Linux) » 2021-09-05 20:55:51

Beertjie
Replies: 2

I'm using Ubuntu on the WSL and I'm trying to compile a Free Pascal project to 64-bit Linux using mORMot. I am using FPC version 3.0.4. I cloned the latest mORMot code from the GitHub repository.

As soon as I include the unit SynCommons, I get the following error:

SynFPCLinux.pas(288,69) Error: Identifier not found "PUTF8Char"

Indeed, the type PUTF8Char is defined in SynCommons itself, which is not referenced by SynFPCLinux. At first, I thought this would cause a circular reference, but since SynCommons is only referencing SynFPCLinux in the uses-clause for the implementation section. Tentatively, I made a change to SynFPCLinux so that SynCommons is included in the uses-clause for the interface. This allowed compilation to resume, but then I faced the following errors:

SynFPCTypInfo.pas(95,31) Error: Identifier not found "PInterfaceData"
SynFPCTypInfo.pas(95,45) Error: Error in type definition
SynFPCTypInfo.pas(96,32) Error: Identifier not found "PVmtMethodParam"
SynFPCTypInfo.pas(96,47) Error: Error in type definition
SynFPCTypInfo.pas(97,33) Error: Identifier not found "PIntfMethodTable"
SynFPCTypInfo.pas(97,49) Error: Error in type definition
SynFPCTypInfo.pas(98,33) Error: Identifier not found "PIntfMethodEntry"
SynFPCTypInfo.pas(98,49) Error: Error in type definition

These missing types are pulled from the TypInfo unit; however, looking at typinfo.pp, not one of these types are defined there.

I must be doing something wrong. What am I missing? Has anyone here successfully compiled mORMot for Linux using Free Pascal?

#4 Re: mORMot 1 » TSQLRequest.Execute ignoring Expand when result set is empty » 2019-06-15 18:29:38

ab wrote:

Note that the best practice is to not publish REST ORM in production, but encapsulate the ORM call in a service.

I didn't know that. What is the reason it's not recommended practice? I assume it's not just about the layout.

#5 Re: mORMot 1 » TSQLRequest.Execute ignoring Expand when result set is empty » 2019-06-13 18:08:48

Thanks, igors233. That will work for a Delphi client.

I'd prefer to have my API respond in a friendlier way. In a public API, I do not have control over my consumers, and I'd rather not have to ask them to implement a workaround.

Does anyone know of a way to deal with this on the server? If the Execute method were virtual, perhaps I could override it...

#6 mORMot 1 » TSQLRequest.Execute ignoring Expand when result set is empty » 2019-06-13 10:55:30

Beertjie
Replies: 5

I want my REST API to consistently use the "expanded" JSON format in its responses, so I've got NoAJAXJSON set to False on my TSQLRestServerDB. However, in the TSQLRequest.Execute function in SynSQLite3.pas, there is the following code which explicitly defies the value of the Expand argument if the result set is empty:

if (result=0) and W.Expand then begin
  // we want the field names at least, even with no data: we allow RowCount=0
  W.Expand := false; //  {"FieldCount":2,"Values":["col1","col2"]}
  W.CancelAll;
  for i := 0 to FieldCount-1 do
    W.ColNames[i] := sqlite3.column_name(Request,i);
  W.AddColumns;
end;

This requires the consumer of my API to have special handling for empty result sets. It would be cleaner to respond with a standard empty JSON array.

Judging from the comments, this behaviour is clearly intentional; therefore, I am hesitant to submit a pull request to change it. Of course, I could modify this code locally and run the risk of having it overwritten on future updates, but I would prefer to avoid that.

Any recommendations?

#7 mORMot 1 » GraphQL? » 2019-06-06 09:26:54

Beertjie
Replies: 2

Are there any plans for GraphQL support in the future?

#8 Re: mORMot 1 » SQL Server 2005 Express » 2018-12-01 10:08:11

You're right, the problem is definitely my ODBC driver. Finding a 32-bit one for 2005 that works on 64-bit Windows 7 might prove difficult.

In the meantime, I got the OLE connection working. I was using the wrong connection properties class – it should have been TOleDBMSSQL2005ConnectionProperties. Works beautifully now!

#9 mORMot 1 » SQL Server 2005 Express » 2018-11-27 18:53:20

Beertjie
Replies: 2

I'm trying to use mORMot with SQL Server 2005 Express.

My code is a lot like andrey's code in this old thread, except I haven't had any luck with OLE (I keep getting "class not registered").

With ODBC, I've gotten a bit further. If I create the database ORMPOCTest beforehand, I am able to connect with the connection properties below:

FProps := TODBCConnectionProperties.Create('', 'Driver={SQL Native Client};Server=.\SQLExpress;Database=ORMPOCTest;Trusted_Connection=yes;', '', '');

I follow this up with:

FModel := TSQLModel.Create([TMovie, TBook]);
VirtualTableExternalRegister(FModel, [TMovie, TBook], FProps);
FServerDB := TSQLRestServerDB.Create(FModel, ':memory:');
FServerDB.CreateMissingTables;

The tables are created. Everything looks good. Now...

NewBook := TBook.Create;
try
  NewBook.Title := 'The Last Wish';
  NewBook.Author := 'Andrzej Sapkowski';
  NewBook.ISBN := '9780316029186';

  NewID := FServerDB.Add(NewBook, True);
finally
  NewBook.Free;
end;

I used this same code with straight-up SQLite3 and it worked. But here I get this error message:

TODBCStatement - TODBCLib error: [HY000] [Microsoft][ODBC Driver 13 for SQL Server]Connection is busy with results for another command (0)

Similarly, I have test code for retrieving, updating, and deleting records. With this connection, all of them fail with the above error.

Except for my RetrieveList code,

SearchResults := FServerDB.RetrieveList(TMovie, 'RunningTime > ? AND Released >= ?', [130, DateToSQL(2000, 5, 7)]);

This fails with a different error:

TODBCStatement - TODBCLib error: [HYC00] [Microsoft][ODBC Driver 13 for SQL Server]Optional feature not implemented (0)

I get the same results for all the drivers below:

  • SQL Native Client

  • SQL Server Native Client 11.0

  • ODBC Driver 13 for SQL Server

Any suggestions on what I could be doing wrong here?

P.S. I realize that Microsoft hasn't supported SQL Server 2005 since April 2016.

#10 Re: mORMot 1 » Interface-based services: Receiving a list of objects » 2018-10-17 12:08:28

That's pretty much exactly the pattern I am following, except that my API is written in C#, and my queue lives on my RabbitMQ server.

The idea is to scale this component by starting up more Delphi worker instances as needed, which I believe is the same thing you're describing.

#11 Re: mORMot 1 » Interface-based services: Receiving a list of objects » 2018-10-17 09:44:49

ab wrote:

TDocVariant are working just great with interface-based services: just define "variant" parameters.

That simple? Thanks, I'm sure that will come in handy in the future.

edwinsn wrote:

@Beertjie, would love to know some details about the queue-based architecture, if you can tell!
I has just recently discovered the 'queue' concept is so powerful and useful in a multi-thread environment, so I'm very curious about it smile

I'm only starting to play around with queues myself. My legacy application is slow and non-reentrant so I'm having it process requests from a queue rather than calling it directly via an API (currently using RabbitMQ as my message broker).

#12 Re: mORMot 1 » Interface-based services: Receiving a list of objects » 2018-10-15 17:14:25

Thank you for the suggestion, AntonE.

In fact, I have switched to TDocVariantData! This does give me much more flexibility, although time will tell whether it's simplifying or just bloating my code base.

I wouldn't know how to apply this to an interface-based service, but my app has since transformed from an HTTP-based service to a queue-based one, so I did away with that part anyway.

#13 Re: mORMot 1 » Interface-based services: Receiving a list of objects » 2018-09-30 13:07:44

Thank you so much. Automatic serialization works now.

ab wrote:

Use TSynPersistent and store lists as dynamic arrays using TJSONSerializer.RegisterObjArrayForJSON() for automatic serialization.

It turns out TJSONSerializer.RegisterObjArrayForJSON() was the key. I never knew about this method!

Sadly, with two decades' worth of technical debt, my application is already single-threaded. Nevertheless, I am happy to switch to TSynPersistent.

mpv wrote:

Why you need classes there? If you need methods you can add it to records.

I forgot to mention that I'm stuck in Delphi 6 for this project, so no methods on records.

Having gotten this far...
Is there any way to make this work with polymorphic arrays?

Edit:
For example, if my various types of "order items" have vastly different sets of properties:

{
  "Order": {
    "Description": "Test",
    "Items": [
      {
        "Class": "TOrderItemA",
        "Field1": "..."
      },
      {
        "Class": "TOrderItemB",
        "Field2": "...",
        "Field3": "..."
      },
      {
        "Class": "TOrderItemC",
        "Field4": "..."
      }]
  }
}

Then I'd prefer to have this:

TOrderItemA = class(TOrderItem)
published
  property Field1: string ...
end;

TOrderItemB = class(TOrderItem)
published
  property Field2: string ...
  property Field3: string ...
end;

TOrderItemC = class(TOrderItem)
published
  property Field4: string ...
end;

Otherwise I'll end up with a flat class like this:

TOrderItem = class(TSynPersistent)
published
  property Field1: string ...
  property Field2: string ...
  property Field3: string ...
  property Field4: string ...
end;

Which, in my real scenario, gets very unhandy very quickly.

#14 mORMot 1 » Interface-based services: Receiving a list of objects » 2018-09-14 14:15:24

Beertjie
Replies: 16

I have an interface-based service on my mORMot REST server, to which I'm submitting JSON parameters via an AJAX call.

Currently, the method takes a record with a property that is an array of other records. I'd like to replace those records with classes, but I can't get it to work.

Adding the "ClassName" property in my JSON doesn't seem to help.

Is this something that is supported by the framework?

Example of what I'm trying to do
For example, if my method takes a parameter of type TOrderItem, e.g.

TOrderItem = record
  ...
end;

TOrder = record
  Description: string;
  Items: array of TOrderItem;
end;

This allows me to post JSON to it such as:

{
  "Order": {
    "Description": "Test",
    "Items": [{...}, {...}, {...}]
  }
}

That works 100%. But now I need to replace those records with objects, e.g.

TOrderItem = class(TPersistent)
private
  ...
published
  ...
end;

What have I tried?
An array of objects, e.g.

property Items: array of TOrderItem
TOrderItems = array of TOrderItem;

TOrder = record
  ...
  Items: TOrderItems;
end;

A TObjectList, e.g.

property Items: TObjectList;

Subclassing TInterfacedCollection, e.g.

TOrderItem = class(TCollectionItem)
  ...
end;

TOrderItemCollection = class(TInterfacedCollection)
protected
  class function GetClass: TCollectionItemClass; override;
end;

TOrder = record
  ...
  Items: TOrderItemCollection;
end;

What do I mean "it doesn't work"?
Most of the time, my JSON is rejected by the framework (so my service method is never hit).

If I leave the object list properties out in my JSON, the object passed to my service method has its list properties set to nil.

Board footer

Powered by FluxBB