#51 mORMot 1 » How to read from database feeding a filtered list without memory leak » 2021-07-07 08:14:37

larand54
Replies: 2

How to read from database feeding a filtering list without memory leakage?

I have a windows-service that reads data from a table into a TObjectList
which is customized to filter out some data i.e. duplicate records.
That's because I couldn't find out how to do that with SQL and mORMot.
I have created a solution that works but I think it might be a
smarter solution.
Anyone that can tell?

Here is my solution:
Alt 1.

Alt 1. Just need one list and the finally is simpler.
procedure TEvNServer.readPkgPrefix(out aPrefixList: TPrefixList);
var
  SQL: RawUTF8;
  ppf: TSQLPkgPrefix;
  newPkgPrefix: TSQLPkgPrefix;
begin
  SQL := 'usedBySync = ? ORDER BY DefaultPrefix desc ';
  ppf := TSQLPkgPrefix.CreateAndFillPrepare(fDBServer, SQL, [1]);
  aPrefixList := TPrefixList.create;
  try
    while ppf.FillOne do begin
      newPkgPrefix := TSQLPkgPrefix.create;       // Clone object before adding to list
      newPkgPrefix.assign(ppf);                   //
      if aPrefixList.add(newPkgPrefix) = -1 then  // if object not accepted by the list,
        newPkgPrefix.free;                        // it must be free:d, otherwise mem-leakage
    end;
  finally
    ppf.free;  // must be free:d otherwise mem-leakage
  end;
end;

Alt 2.

Alt 2. Dont need to clone and add the assign method to TSQLPkgPrefix class.
procedure TEvNServer.readPkgPrefix(out aPrefixList: TPrefixList);
var
  SQL: RawUTF8;
  ppf: TSQLPkgPrefix;
  tmpList: TObjectList<TSQLPkgPrefix>;
begin
  SQL := 'usedBySync = ? ORDER BY DefaultPrefix desc ';
  tmpList := fDBServer.RetrieveList<TSQLPkgPrefix>(SQL, [1], '');
  aPrefixList := TPrefixList.create;
  try
    for ppf in tmpList do begin
      if aPrefixList.add(ppf) = -1 then begin
        ppf.free;
      end;
    end;
  finally
    if assigned(tmpList) then begin
      tmpList.OwnsObjects := false;
      freeAndNil(tmpList);
    end;
  end;
end;

#52 Re: mORMot 1 » Problems with LogViewer and file rotation » 2020-11-05 11:09:59

Don't know where I should set these options/flags and what choices I have?
I skimmed through the Logviewers code but didn't found anything useful.

#53 mORMot 1 » Problems with LogViewer and file rotation » 2020-11-04 10:26:52

larand54
Replies: 4

If I open the logfile with the log viewer, while the program is running and produces lines to the log file, and watching it over time the log go nuts!
It seems that the log viewer holds the logfile so that log rotation can not rename the file but still copies and compresses the filecontents into the rotate-list of files.
As it can't begin with an empty file it continues to run the rotate cycle for each line that adds to the log. This will cause huge cpu and memory load.

Is there a way to avoid this and still view the log? It's too easy to forget to close the viewer and unwatched it can cause a mess.

Otherwise I really like the viewer.

#55 mORMot 1 » How create a json formatted array of records? » 2020-08-15 10:47:45

larand54
Replies: 2

I tried this:

var
  body: variant;
  i: integer;
  files: array of RawUTF8;
  atm: array of variant;
  t: variant;
begin
  setLength(files, 2);
  files[0] := 'C:\temp\Faktura_se.pdf';
  files[1] := 'C:\temp\din.pdf';
  TDocVariant.new(body);
  if high(files) > -1 then
  begin
    SetLength(atm, high(files) + 1);
    for i := 0 to high(files) do
    begin
      TDocVariant.new(atm);
      t.name := extractFileName(files[i]);
      t.value := fileToBase64(files[i]);
      atm[i] := t;
    end;
    body.FileAttachments := _arr([atm]);
  end;

but that just set FileAttachments to '{"FileAttachments":[null]}'

Is there a simple correction of this code?

#56 Re: mORMot 1 » SynCrtSock error 12019 when run in a VCL-app » 2020-08-15 10:33:14

Found the reason... it was a setting called "Use a Proxy" that was on. I never ever used a proxy before... just don't have a clue on how it was set.
Well, that's it.
Thank's a lot.

#57 Re: mORMot 1 » SynCrtSock error 12019 when run in a VCL-app » 2020-08-14 20:09:47

Ok, but it won't help me as it only works when WIN10 is not detected.
HttpRequest gives error when proxy is set to auto which it is when WIN10 is detected.

What can make it do that? I suppose it normally works with win10?

And when I added "{$R Vista.res}" into the console project it stopped work.

#58 mORMot 1 » SynCrtSock error 12019 when run in a VCL-app » 2020-08-14 10:22:16

larand54
Replies: 4

When executing TWinHTTP.Post I get this error when run in a VCL app but if I run an excact copy of the code in a console-app it works.
I have debuged but can't find out what causes this.
Nice if someone have a clue to work on..

I have DELPHI-10.3 in this case and the latest version of WIN10.

I've debugged a bit deeper and found that in the initialization of connection properties there is a selection using Automatic proxy or no proxy. This is controled by OS-Version.
If i run the VCL-app I get major-version=10 and minor=3 but in the console app I get Major=6 and Minor=2 and in that case I get NO_PROXY but in the VCL-app I get Automatic_Proxy.

And if I changed the value from Auto to NO-proxy, using debugger,  it works with the VCL-version.

I have no idea why it is like that and why it won't work with automatic_proxy.
I don't want to change anything in SynCrtSock so I still need some help.

#59 Re: mORMot 1 » How do I load a file into the body of a http-request » 2020-08-14 10:04:32

Thank's a lot, I've just solved it this way:

    TDocVariant.new(body);
    body.SendUser := aFrom;
    body.Message := aMessage;
    body.Subject := aSubject;
    body.ToRecipients := _Arr([stringReplace(aMailTo, ';', ',', [rfReplaceAll, rfIgnoreCase])]);
    body.CcRecipients := _Arr([stringReplace(aCC, ';', ',', [rfReplaceAll, rfIgnoreCase])]);
    if high(aAttachments) > -1 then
    begin
      for i := 0 to high(aAttachments) do
      begin
        TDocVariant.new(atm[i]);
        atm[i].name := extractFileName(aAttachments[i]);
        atm[i].value := fileToBase64(aAttachments[i]);
      end;
    body.FileAttachments := _Arr([atm]);
    end;

    messageID := TWinHTTP.Post(fOaSec.getMailURL, body, fOaSec.getMailHeader);

function FileToBase64(const aFileName: RawUTF8): RawUTF8;
var
  f: TStream;
  bytes: TBytes;
begin
  result := '';
  f := TFileStream.Create(afilename, fmOpenRead);
  try
    if f.Size > 0 then
    begin
      SetLength(bytes, f.Size);
      f.Read(bytes[0], f.Size);
    end;
    result := binToBase64(@bytes[0], f.size); //String(sb);
  finally
    f.free;
  end;
end;

#60 Re: mORMot 1 » How do I load a file into the body of a http-request » 2020-08-12 07:46:14

Yes, it's about a http-request.
The service requires a body that contans mailFrom, mailto, message etc. and the attached files with name and contentents encoded in Base64 .
Al is wrapped in a json structure:

{
    "SendUser": "senderName@somwhere.on.earth",
    "Message": "Hello",
    "Subject": "HelloSubject",
    "ToRecipients": [
        "receiver.theMartian@mons.olympus.on.mars"
    ],
    "CcRecipients": [
        "flash@titan.on.saturn"
    ],
    "FileAttachments": [
        {
            "Name": "spacetraveling.pdf",
            "Value": "N7I+GuZ4KclTXP7KXM3YRdh0BfKxnMpOv8s....        } // Filecontents base64-encoded
    ]
}

Part of the code that calls the sendmail service

var
  messageID: sockString;
  body: variant;
  atm: variant;
begin
  if getToken = '' then
    result := -1
  else begin
    TDocVariant.new(body);
    body.SendUser := aFrom;
    body.Message := aMessage;
    body.Subject := aSubject;
    body.ToRecipients := _Arr([stringReplace(aMailTo,';',',')]);
    body.CcRecipients := _Arr([stringReplace(aCC,';',',')]);
    if high(aAttachments) > -1 then begin
       TDocVariant.new(atm);
       atm.name := aAttachments[0];
	   .
	   . read and add file contents here - all attachments should be put into an array and then added to the body.
	   
    messageID := TWinHTTP.Post(fOaSec.getMailURL,body,fOaSec.getMailHeader);

#61 Re: mORMot 1 » How do I load a file into the body of a http-request » 2020-08-11 18:54:09

Ok, thank's for an answer but I has to send the mail through a service where everything is built around OAuth2. I have everything working and can send the mail but I need to know how I should do with the files that needs to be attached to the mail.
Indy will not help here.

#62 mORMot 1 » How do I load a file into the body of a http-request » 2020-08-11 16:27:27

larand54
Replies: 9

In a new project I need to send mail using OAUTH2. The mail can contain attachments like pdf-files and they need to be Base64 encoded.
I feel lost in all alternatives so I need some help to move forward.
I use TWinHttp.post sending mail. It works good with simple mail.

#63 Re: mORMot 1 » urlEncode don't convert the "tilde" character » 2020-08-10 16:15:55

Ok, I understand.
Well, good to know why it is like that, then it makes it more easy to accept.
In my case, for the moment at least, it won't be much of a problem as it is a fixed string that will not change often if ever so I only have to replace the '~':s with "%7E" manually.

#64 mORMot 1 » urlEncode don't convert the "tilde" character » 2020-08-10 10:56:09

larand54
Replies: 5

Tries to use OAUTH2 in a project but a secret code  contains '~'-characters and they are not replaced by the function.
While debugging I could se that this character belongs to the "unreserved characters" and will be left unchanged.

The OUTH2 service to get a token don't accept this character.

What can I do about it?
I no INDY has that function and that works but would like to make it without adding more libraries.

#65 Re: mORMot 1 » ORMAdd does not store the linked classes » 2020-05-10 17:08:50

Ok, from the beginning I did just that but I did not want a complete flat table, I want to split them in One Customer table and one PersonContactable table.
In this simple example it isn't needeed but I want to know how to behave when I really need to split.
In one case I can think of is when you have several contacts for the customer. They are specified by what "role" that contact have. Different customers has different roles One may have only one another has 3 and others may have 6 etc. In that case it feels inconvenient to have a flat table for all this even if its possible.
One contact can possess several roles, the customer employs a new person to take over another contacts role etc.


21_customer-role-contact.png

#66 mORMot 1 » ORMAdd does not store the linked classes » 2020-05-10 13:04:31

larand54
Replies: 3

Having problem finding out how I should handle INSERT of objects that contains linked classes.
ORMAdd does not seems to handle that.
I came up with an own solution but don't really like it.

The main TSQLRecord looks like this:

     TSQLRecordCustomer = class(TSQLRecord)
  protected
    fContact: TSQLRecordPersonContactable;    <<<--- The linked class
  published
    property Contact: TSQLRecordPersonContactable read fContact write fContact;

   
The repositorys add-function:   

function TCustomerRepository.Add(const aAggregate: TCustomer): TCQRSResult;
var
  rest: TSQLRest;
  SQLpc: TSQLRecordPersonContactable;
  pc: TPersonContactable;
  SQLcus: TSQLRecordCustomer;
begin
  result := cqrsInternalError;
  rest := GetRest(self);
  SQLpc := TSQLRecordPersonContactable.Create;
  SQLcus := TSQLRecordCustomer.Create;
  CustomerToRecord(aAggregate,SQLcus,SQLpc); <<<---- Copies all fields from TCustomer into SQLcus and SQLpc
  SQLcus.Contact := TSQLRecordPersonContactable(rest.add(SQLpc, true));
  rest.Add(SQLcus, true);
  result := cqrsSuccess;

This works but I don't know how to handle different errors here and the "CustomerToRecord" function is heavy to type.

What I want is that this should be enough.

  Result := ORMAdd(aAggregate);

But this leaves the "Contact"-field equal to zero.

I'm afraid that it isn't possible using ORM this way but hopes for a simpler and better solution than mine.

#67 Re: mORMot 1 » ORMSelectAll('Name_Last LIKE ?',[aName+'%'],(aName='')) does not work » 2020-04-12 11:49:19

You are right, it works when running using external tables, at least against SQLite3.
Thank's for the help!
But isn't this a limit to this framework? I've thought that it should be transparent to any storage? Or am I wrong?

#68 mORMot 1 » ORMSelectAll('Name_Last LIKE ?',[aName+'%'],(aName='')) does not work » 2020-04-12 09:45:02

larand54
Replies: 4

I run the regressiontest of TUser in the DDDExample but found that there was no test with the 'LIKE' operator.
The function "SelectByLastName" exists though and it takes an extra boolean parameter "StartsWith" that controls whether you want exact(false) or something that starts with..
Added some code that exercise that function.

    test.Check(Rest.Services.Resolve(IDomUserCommand,cmd));
    CQRS := cmd.SelectByLastName('Last1', false);                  // Exact - this one works
    CQRS := cmd.SelectByLastName('Last', True);                    // Using "LIKE" and will not find anything.

Tried with debugging and finally entering: function TSQLRestStorageInMemory.GetJSONValues
where it checked the type of operator used.
Following cleaned code shows the execution flow..

function TSQLRestStorageInMemory.GetJSONValues(Stream: TStream;
    case Stmt.Where[0].Operator of
    opEqualTo:
opIsNull, opIsNotNull:
    else begin
err:  W.CancelAll;
      result := 0;
      exit;

When using the "LIKE" operator, the value of "Stmt.Where[0].Operator" is "opLike" and there's no entry for that and that causes this select to end with "W.CancelAll".

What's wrong here? Shouldn't it be an entry for "opLike".

#69 mORMot 1 » Inheritance and persistance don’t work as I expected » 2020-03-30 17:06:15

larand54
Replies: 0

I tested using the dddUserTypes unit with the classes TPersonFullName, TPerson and TPersonContactable.
Instead of Tuser I created the TCustomer class that inherits from TsynAutoCreateFields and contains a field of type TPersonContactable.

  TCustomer = class(TSynAutoCreateFields)
  private
    fContact: TPersonContactable;
  published
    property Contact: TPersonContactable read fContact;
  end;

Calling –
TDDDRepositoryRestFactory.ComputeSQLRecord([TPersonContactable, TCustomer]);
creates the following classes:
•    TSQLRecordPerson
•    TSQLRecordPersonContactable
•    TSQLRecordCustomer

Calling - .CreateMissingTables creates the following tables:
•    PersonContactable
•    Customer
PersonContactable contains all the fields from TAddress, TPerson and TPersonFullName and it’s own.
Regression tests on TCustomer confirm access to all fields of these classes.
But testing using ORM doesn’t give access to the fields in the class TPersonFullName. There is no error or warnings when adding records But the fields Name_First, Name_Middle, and Name_Last will not be updated in the table  “PersonContactable” but all other fields are updated.
I’ve checked all I can think of but can not make this work. Strange that ORM creates the fields from TPerson-TPersonFullName but does not allow access to the fields from TPersonFullName.
I wonder what I may be missing, I’m sure this should work automatically if I did everything wright.
Hope anyone could spread some light over this.

#70 Re: mORMot 1 » fields of type currency is not persisted » 2020-03-16 13:15:32

You are completely right, but it makes "currency" special any way as it works if you do: TPrice = double;
Thank's a lot!

#71 mORMot 1 » fields of type currency is not persisted » 2020-03-16 10:23:29

larand54
Replies: 3

In my little test project running some regression tests, I found that fields that have the type "currency" will not be updated on the database.
I thought it should work with "currency" but in my case apparently not. If I change type "TPrice" to be of type "double" it works.
Am I doing something wrong or should I avoid type "currency"?

---- A crippled piece of the code i use  ----

type
  TPrice                    = type currency;
  TDiscount                 = type double;
  TWeight                   = type double;
-------------------------------------------------

  TSQLRecordProduct = class(TSQLRecord)
  protected
    fweight: double; // TWeight
    fdiscount: currency; // TDiscount
    fPrice: double;//currency; // TPrice
  published
    property weight: double read fweight write fweight;
    property discount: double read fdiscount write fdiscount;
    property price: double read fPrice write fPrice;
  end;
--------------------------------------------------
  TProduct = class(TSynAutoCreateFields)
  private
    fWeight: TWeight;
    fPrice: TPrice;
    fDiscount: TDiscount;
  public
    constructor create(const aName: TProductName; const aWeight: TWeight; const aPrice: TPrice;
                       const aDiscount: TDiscount); overload;
  published
    property weight: TWeight read fWeight write fWeight;
    property price: TPrice read fPrice write fPrice;
    property discount: TDiscount read fDiscount write fDiscount;
  end;
    TProductObjArray = array of TProduct;
   
------------- part of server code --------
RestServer := TSQLRestExternalDBCreate( TSQLModel.Create([TSQLRecordProduct]),
RestServer.ServiceContainer.InjectResolver([TProductRepoFactory.Create(RestServer)],true);
   
---------------------- Test code below --------------------
var p1: TProduct;

p1 := TProduct.Create;
p1.weight := 12.3;
p1.price :=  249.99;
p1.discount := 25;
aCQRSRes := cmd.Add(p1);
Check(cqrsSuccess = aCQRSRes);
Check(cqrsSuccess = cmd.Commit);

p1.price is not persisted.

#72 mORMot 1 » ObjectToJSON and stored AS_UNIQUE » 2020-02-07 12:08:46

larand54
Replies: 1

A few problems I've stumbled into:

1. When using "stored AS_UNIQUE" or a calculated property like "discountedprice" below, those properties is lost using ObjectToJSON.
   Why? and what can I do about it?
   
2. Why do I get the new function: "function AS_UNIQUE" when I press (ctrl-shift C)?
   Is it possible to avoid?
   
Below a sample code:
  TProduct = class(TSynAutoCreateFields)
  private
    fName: TProductName;
    fPrice: TPrice;
    fDiscount: TDiscount;
    function getDiscountedPrice: TPrice;
    function AS_UNIQUE: Boolean;                            <<<<----- Will be automatically created on (ctrl-shift C)
  public
    constructor create(const aName: TProductName; const aPrice: TPrice;
                       const aDiscount: TDiscount); overload;
    class procedure RegressionTests(test: TSynTestCase);
  published
    property productName: TProductName index 80 read fName stored AS_UNIQUE;
    property price: TPrice read fPrice write fPrice;
    property discount: TDiscount read fDiscount write fDiscount;
    property discountedPrice: TPrice read getDiscountedPrice;
  end;

============
procedure T
var b,c: TProduct;
    jsonC, jsonB: RawUTF8;
begin
  c := TProduct.Create('HardDrive 2TB',12.5,5.0);
  with test do
  try
    jsonC := ObjectToJSON(c)+'*';
---->>>>  jsonC will not contain productName nor discountedPrice.

#73 mORMot 1 » Legacy tables and the ID-field » 2019-11-19 05:48:04

larand54
Replies: 1

We have a huge system containing several hundreds of tables and I tries to replace pieces of delphi-code by using mORMot and the DDD-concept.
When I do some testing I find that it won't work when the tables don't contain the ID-field. Which is true in most tables.

I can not access these tables without getting the "Invalid column name 'ID'" - error
In the implementation of the service I'm intend not to use ORM on these tables to avoid such problems. But that's not enough.

Even the call of "CreateMissingTables" returns this error. So I wonder if there is a solution for this or if I need to treat these tables in a total different way?

#74 Re: mORMot 1 » Checking against NULL data from DB » 2019-06-11 15:46:44

That was a good idea, that worked! Normally I like to use standard ORM-style instead of plain SQL but sometimes it seems to be necessary to breake that rule.
If someone have a better idea using ORM you're welcome, but otherwise I would say this is now solved.
Thank's smile

#75 Re: mORMot 1 » Checking against NULL data from DB » 2019-06-10 16:29:25

Yes I have read that and made all TDateTime fields of type TNullable. But it didn't help.
You see, I'm new to mORMot and not so familiar with variants. I have not so easy to understand how I should use it here.

I doubt that I can write the code like I did in my example above even though it feels natural for me as I'm more used to SQL.

I just test mORMot occasionally when I have time. I'm looking for a way to use it in a larger project and try to find as many pitfalls as possible before I proceeds with a larger project.
I've found a lot of them already and some of them are solved but this problem are still unsolved.

#76 mORMot 1 » Checking against NULL data from DB » 2019-06-10 09:49:15

larand54
Replies: 5

Using ORM I want to check if a field is null or not like this:

function TInfraRepoTicket.SelectUO: TCQRSResult;
begin
  result := ORMSelectAll('DateOpened is ?',[null]);
end;

This doesn't seem to work as I never get a hit.
How can I solve this problem?

#77 Re: mORMot 1 » ORM crashes when all data is read using ORMGetNextAggregate[SOLVED] » 2019-05-05 11:42:28

I have now installed a new version of fpc and lazarus following your instructions.
And now the testSQLite3 and my testapp works as it should.
Easy solved but hard to find wink

#78 Re: mORMot 1 » ORM crashes when all data is read using ORMGetNextAggregate[SOLVED] » 2019-05-03 09:12:51

I got the same revision.. very strange when you can't reproduce it. Can it be something with Lazarus?

Free Pascal Compiler version 3.3.1-r41736 [2019/03/19] for x86_64

#79 Re: mORMot 1 » ORM crashes when all data is read using ORMGetNextAggregate[SOLVED] » 2019-05-03 08:41:32

An immedite answer here, I'm just try to debug the "TestSQL3" app. It fails with access violation and it seems to be in the same code part as in my app.
What's common is that when a call result in a cqrsStatus <> cqrsSuccess and it tries to create the JSON formatted response it crasches.
It is very hard for me to understand what's really happends here and I've been trying to find out by debugging. So far I have not find it.
It should be simple though to reproduce it by running TestSQL3 with the same FPC-compiler 3.3.1 as I use.
The first test that fails is this:

Check(service.StartEmailValidation(template,'toto','toto@toto .com')=cqrsDDDValidationFailed);

This test is made to give an error status and that causes the crasch.

Is it enough to put the code into paste.bin, all code in one file or...?

#80 Re: mORMot 1 » ORM crashes when all data is read using ORMGetNextAggregate[SOLVED] » 2019-05-02 09:39:07

Ok,
I'm using a Lazarus installation, installed by using fpcupDeluxe choosing the trunk version and got fpc-3.3.1 and Lazarus-2.1.0. I included mORMot in the installation.
I also installed ZEOS (7.2.4-stable build at 2018-03-25 11:08:27).

I also installed the latest WAMP-server to get MySQL together with a convenient environment.

To test that I could use MySQL and ZEOS in future programming I created a simple simple application to test all this.
First I had both server and client in the same application but later I splited it into one  client and one server application but the result is the same.
It has no problem adding new records in the database table and it can also read them back without any problem. But,
if I want to read them all by using the function "ORMGetNextAggregate" I get all records delivered but at the end, when this function tries to read beyond the last record,
it gets the cqrsStatuscode=cqrsSuccessWithMoreData. So far so good but then it tries to create  the JSON-message to be sent back to the client it goes wrong.
It looks like it doesn't know when to stop the process so it goes to far and get garbage data.
The "PPropInfo^PropType^.Kind the point outside it's buffer and returns a value to the TTextKind variable Kind that is outside its definition.

Maybe it can be in the function listed below:

function InternalClassProp(ClassType: TClass): PClassProp;
{$ifdef FPC}
begin
  with GetFPCTypeData(pointer(ClassType.ClassInfo))^ do
    result := AlignToPtr(@UnitName[ord(UnitName[0])+1]);
{$else}
{$ifdef PUREPASCAL}
var PTI: PTypeInfo;
begin // code is a bit abstract, but compiles very well
  PTI := PPointer(PtrInt(ClassType)+vmtTypeInfo)^;
  if PTI<>nil then // avoid GPF if no RTTI available for this class
    with PTI^, PClassType(@Name[ord(Name[0])+1])^ do
      result := PClassProp(@UnitName[ord(UnitName[0])+1]) else
    result := nil;
{$else}
asm // this code is the fastest possible
        mov     eax, [eax + vmtTypeInfo]
        test    eax, eax
        jz      @z // avoid GPF if no RTTI available for this class
        movzx   edx, byte ptr[eax].TTypeInfo.Name
        lea     eax, [eax + edx].TTypeInfo.Name[1]
        movzx   edx, byte ptr[eax].TClassType.UnitName
        lea     eax, [eax + edx].TClassType.UnitName[1].TClassProp
@z:
{$endif PUREPASCAL}
{$endif FPC}
end;

The delphi version returns NIL when it don't find the classtype but the fpc version just returns the result from: AlignToPtr(@UnitName[ord(UnitName[0])+1]);
I failed to check what this function ( or isn't it a function?) returns.

I'm totally stuck here and if I don't solve this soon, there is nothing more than to leave this project I'm afraid.
I have struggled for days trying to solve this but now I understand I can't get any further without help. sad

#82 Re: mORMot 1 » Authorization tables not created with "CreateMissingTables » 2019-04-25 07:36:32

I found the missing part myself. I had to put all tables in the "VirtualTableExternalRegister" procedure.
I was fooled by the fact that you didn't need to put these tables (TSQLAuthUser, TSQLAuthGroup) into the model as do that automatically in the background, so I never thought about putting these tables into the VirtualTableExternalRegister procedure.

  VirtualTableExternalRegister(Model, [TTicket, TSQLAuthUser, TSQLAuthGroup], Props);

#83 Re: mORMot 1 » ORM crashes when all data is read using ORMGetNextAggregate[SOLVED] » 2019-04-23 14:06:32

As simple as this:

  TDTOTicket = class(TSQLRecord)
  protected
    fticketNo: integer; // TTicketNo
    fdescription: RawUTF8; // TDescription
    fdateCreated: TDateTime; // TDateTime
    fdateOpened: TDateTime; // TDateTime
    fdateSolved: TDateTime; // TDateTime
  published
    /// maps TTicket.ticketNo (TTicketNo)
    property ticketNo: integer read fticketNo write fticketNo;
    /// maps TTicket.description (TDescription)
    property description: RawUTF8 read fdescription write fdescription;
    /// maps TTicket.dateCreated
    property dateCreated: TDateTime read fdateCreated write fdateCreated;
    /// maps TTicket.dateOpened
    property dateOpened: TDateTime read fdateOpened write fdateOpened;
    /// maps TTicket.dateSolved
    property dateSolved: TDateTime read fdateSolved write fdateSolved;
  end;

The server is running in the same program as the client, to simplify testing.

The server looks like this:

constructor TTicketServer.create(const aObserver: IErrorObserver);
begin
  DBConnect(rseZeosMySQL, 'zdbc:mysql://localhost:3306', 'test_mormot', 'root', 'gT7Wqa96S');
  Model := CreateTicketModel;
  VirtualTableExternalRegister(Model, [TTicket], Props);
  DBServer := TSQLRestServerDB.Create(Model, true);     // true -> Authorization used
  try
    DBServer.CreateMissingTables;
    DBServer.ServiceContainer.InjectResolver([TInfraRepoTicketFactory.create(DBServer)], false);
    DBServer.ServiceDefine(TInfraRepoTicket, [IDomTicketCommand], sicClientDriven);
    httpServer := TSQLHttpServer.Create(PORT_NAME, [DBServer], '+', HTTP_DEFAULT_MODE);
    try
      httpServer.AccessControlAllowOrigin := '*'; // allow cross-site AJAX queries
      CodeHalted := true;
      while CodeHalted do begin
        Application.ProcessMessages;
        sleep(1000);
      end;
    finally
      httpServer.Free;
    end;
  finally
    DBServer.Free;
  end;
end;

TTicket is defined as:

  TTicket = class(TSQLRecord)
  private
    fTicketNo: TTicketNo;
    fDescription : TDescription;
    fDateCreated: TDateTime;
    fDateModified: TDateTime;
    fDateOpened: TDateTime;
    fDateSolved: TDateTime;
    fCategory: TTicketCategory;
    function getTicketID: TTicketID;
  published
    property ticketNo: TTicketNo read fTicketNo write fTicketNo;
    property description: TDescription read fDescription write fDescription;
    property dateCreated: TDateTime read fDateCreated write fDateCreated;
    property dateOpened: TDateTime read fDateOpened write fDateOpened;
    property dateSolved: TDateTime read fDateSolved write fDateSolved;
  end;

#84 Re: mORMot 1 » Authorization tables not created with "CreateMissingTables » 2019-04-23 14:02:43

ianxevcd, I tried that before and I tried again - it didn't change anything. The parameter I used is, as what I understand, just a version number. Don't know where it is used but as my ticket table is created with or without this parameter, I can't see that it have something with db modification to do. But what do I know?

I will try to debug that function a bit more later on if no other solution comes up.

#85 mORMot 1 » ORM crashes when all data is read using ORMGetNextAggregate[SOLVED] » 2019-04-23 13:36:15

larand54
Replies: 10

In unit mORMot:
procedure TCQRSService.InternalCqrsSetResult(Error: TCQRSResult; var Result: TCQRSResult);
procedure TJSONSerializer.WriteObject(Value: TObject; Options: TTextWriterWriteObjectOptions);

procedure WriteProp(P: PPropInfo);

     Kind := P^.PropType^.Kind;
    case Kind of                                   <<<< Kind is 28 (TSQLRecordTableDeletedClass)
                                                   ===== Raises exception External: SIGSEGV
      tkInt64{$ifdef FPC}, tkQWord{$endif}: begin
     
This happends when I call the function ORMGetNextAggregate when there is no data left and when
it sets the cqrsStatus via InternalCqrsSetResult.

The code sequence in my testapp looks like:

    ticketServer.DBServer.Services.Resolve(IDomTicketCommand,IDTC);

    theTicket := TDTOTicket.Create;
    theTicket.ticketNo := 199;
    cqrsStatus := IDTC.Add(theTicket);
    IDTC.Commit;
    try
      cqrsStatus := IDTC.SelectAll;
      if cqrsStatus in [cqrsSuccess, cqrsSuccessWithMoreData] then begin
        while cqrsStatus in [cqrsSuccessWithMoreData, cqrsSuccess] do
        begin
          cqrsStatus := IDTC.getNext(theTicket);

What can I do here? Is it a system bug or am I the bug? wink

#86 Re: mORMot 1 » Authorization tables not created with "CreateMissingTables » 2019-04-22 18:28:50

I have already tested that and I did it again but only the ticket.table is created.

I'm using fpc, zeos and lazarus and I have had a lot of problems making it work can it be something with this configuration? I've tested with delphi in another project and that was easier but then I also used MSSQL.

#87 mORMot 1 » Authorization tables not created with "CreateMissingTables » 2019-04-22 12:04:58

larand54
Replies: 7

Setting up the server with authorization doesn't work as expected.
I expected the two tables would be created automatically when I set the parameter of "TSQLRestServerDB.Create" to true.
The table "Ticket" is created

constructor TTicketServer.create;
begin
  TDDDRepositoryRestFactory.ComputeSQLRecord([TTicket]);
  DBConnect(rseZeosMySQL, 'zdbc:mysql://localhost:3306', 'test_mormot', 'root', '');
  Model := CreateTicketModel;
  VirtualTableExternalRegister(Model, [TTicket], Props);
  DBServer := TSQLRestServerDB.Create(Model, true);  // Require authorization
  try
    DBServer.CreateMissingTables(0);
    DBServer.ServiceContainer.InjectResolver([TInfraRepoTicketFactory.create(DBServer)], true);
    DBServer.ServiceDefine(TInfraRepoTicket, [IDomTicketCommand], sicClientDriven);
    httpServer := TSQLHttpServer.Create(PORT_NAME, [DBServer], '+', HTTP_DEFAULT_MODE);

function createTicketModel: TSQLModel;
begin
  result := TSQLModel.Create([TTicket],'root');
end;

procedure TTicketServer.DBConnect(aEngine: TRemoteSQLEngine; const aServerName,
  aDatabaseName, aUserID, aPassWord: RawUTF8);
const
  TYPES: array[TRemoteSQLEngine] of TSQLDBConnectionPropertiesClass = (TSQLDBZEOSConnectionProperties,TOleDBConnectionProperties, TODBCConnectionProperties, TSQLDBOracleConnectionProperties, TSQLDBSQLite3ConnectionProperties, nil, TOleDBMSSQL2008ConnectionProperties);
begin
  if Props <> nil then
    raise Exception.Create('Connect called more than once');
  if TYPES[aEngine] = nil then
    raise Exception.CreateFmt('aEngine=%s is not supported', [GetEnumName(TypeInfo(TRemoteSQLEngine), ord(aEngine))^]);
  Props := TYPES[aEngine].Create(aServerName, aDatabaseName, aUserID, aPassWord);
end;

What am I missing?

#88 Re: mORMot 1 » SynTaskDialog problem with FPC/Lazarus » 2019-04-11 14:49:35

Ok, I understand. I'll skip that part of the sample to get forward.
I'm new to mORMot and it's not an easy beast to tame so I feel that I'm not ready yet to come with any proposal here. Maybe in the future wink

#89 mORMot 1 » SynTaskDialog problem with FPC/Lazarus » 2019-04-11 07:08:14

larand54
Replies: 2

Trying to make sample 16 to work with Lazarus and are stopped out by synTaskDialog which are used by mORMotUILogin.
I found that in mORMotUILogin there is a compiler switch that refer to:

  {$ifdef FPC}
  SynTaskDialog in '.\Samples\ThirdPartyDemos\Ondrej\SynTaskDialog4Lazarus\SynTaskDialog.pas',
  {$else}
  SynTaskDialog,

But I can see that it is the version of synTaskDialog from the ordinary mORMot library that is used and that one won't compile with FPC.

I find it very odd to have a standard library unit that refer to a sample third party unit. Is that good programming?

Ok, that's that.. but isn't it possible to have FPC work with this fundamental unit?

#90 Re: mORMot 1 » Using subqueries and aggregate functions in ORM » 2019-04-08 17:51:59

I thought I made it work but it was only an coincidence:

  Baby := TSQLBaby.Create;
  if aClient.Retrieve('', Baby, 'min(BirthDate)') then
    Memo1.lines.Add(Format('zzzz %s - %s ',[Baby.Name, Baby.Address])+' // '+FormatDateTime('yyyy-mm-dd', Baby.BirthDate));  <<-- Gives an empty Baby
  if aClient.Retrieve('', Baby, '') then
    Memo1.lines.Add(Format('yyyyy %s - %s ',[Baby.Name, Baby.Address])+' // '+FormatDateTime('yyyy-mm-dd', Baby.BirthDate)); <<-- Gives the first record created (it happened to be the one I searched for)

I'm sure I do something wrong but after I have tested so many different things... it looks impossible to make it work.

#91 Re: mORMot 1 » Using subqueries and aggregate functions in ORM » 2019-04-08 12:16:40

Well I did got a hit but the Baby object was empty in return so all strings was empty and the date was '1899-12-30'.

I did like this:

  Baby := TSQLBaby.Create;
  if aClient.Retrieve('', Baby, 'min(Birthdate)') then

I feel that I'm missing something but what?

#92 Re: mORMot 1 » Using subqueries and aggregate functions in ORM » 2019-04-07 17:09:37

Finally I found why I got the Access violation. That's because I didn't created the Baby object first.
I needed to do like this:

  if aClient.Retrieve(ID,Baby) then
    Memo1.lines.Add(Format('WWWW %s - %s ',[Baby.Name, Baby.Address])+' // '+FormatDateTime('yyyy-mm-dd', Baby.BirthDate));

But I still don't know how I should do to use "Retrieve" to get the post with oldest date.
Of course I can do like this:

  if aClient.Retrieve('BirthDate = (SELECT MIN(BirthDate) FROM Baby)',Baby) then
    Memo1.lines.Add(Format('WWWW %s - %s ',[Baby.Name, Baby.Address])+' // '+FormatDateTime('yyyy-mm-dd', Baby.BirthDate));

But as I understod from ab, this is not the best way to do it... am I wright/wrong?

#93 Re: mORMot 1 » ORM and date queries[Solved] » 2019-04-07 16:46:00

Ok, that solved some mystery about this. I have declared BirthDate as TDate and that result as FLOAT in SQLite3. When I changed to TDateTime I got TEXT in SQLite3.
Strange that TDate and TDateTime is not treated the same here.

That solved everything about this and if I had choosen TDateTime from the begining, this topic would not been created wink

#94 Re: mORMot 1 » ORM and date queries[Solved] » 2019-04-06 12:02:59

Finally it worked smile

I could also reduce it to:

  Baby := TSQLBaby.CreateAndFillPrepare( aClient, 'BirthDate=?',[double(dt)]);

So you may ask... Why all this about using DateToSQL and DateTimeToSQL when you should cast it to a double?
It has to be some other situations when you need to use them but when?

Thank's !

PS
  Is there any Convention how to mark a thread solved here ?
DS

#95 Re: mORMot 1 » ORM and date queries[Solved] » 2019-04-05 17:50:34

Sorry, but that didn't work either.
Can there be any more solutions to test? sad

#96 Re: mORMot 1 » ORM and date queries[Solved] » 2019-04-05 14:42:36

I use SQLIteStudio 3.2.1
which gives the following output:

ID	Name	Address	BirthDate	Sex
310	Fredrik	Stockholm	43259.5122240741	1
311	Kristina	Lund	43294.5122242593	0
312	Kurt	Lindesberg	43103	1

The last line is the line I searched for which is 2018-01-03.

#97 Re: mORMot 1 » ORM and date queries[Solved] » 2019-04-05 10:40:59

I just tested that, but, sorry ... no hit.
Date seems to be a problem in mORMot.
Maybe it could also depend on SQLite3? I never had any such problems in Delphi with firedac and MSSQL.

#98 Re: mORMot 1 » ORM and date queries[Solved] » 2019-04-05 06:44:22

It doesn't matter if I change to DateTimeToSQL. Still no hit.
You only get hits when using :

Baby := TSQLBaby.CreateAndFillPrepare( aClient, 'BirthDate <> ?',[DateTimeToSQL(dt)]);

or whenever you use '<' or '>' but thats not what I want in this case. I want hits on a certain date.

Maybe this wont work with fpc and lazarus? But I thought it would.
I'm running on Windows10.

Still hope on some help or explanation

#99 Re: mORMot 1 » Using subqueries and aggregate functions in ORM » 2019-04-04 21:39:50

I have tried your suggestion but failed, I've probably not understand what you mean so I need more help.

Note that I use Lazarus-2.1 and fpc-3.3.1

I've tried hard to find out how I should use the retrieve-function but totaly failed.

  if aClient.Retrieve('BirthDate = ?',[],['Select min(BirthDate)'],Baby,'') then

and even this will not work,

  if aClient.Retrieve('BirthDate = ?',[],['2019-01-01'],Baby) then

I get access violation in mormot.pas at the last line in the dump below:

function TSQLModel.GetTableIndex(aTable: TSQLRecordClass): integer;
var i: PtrInt;
    Props: TSQLRecordProperties;
    c: PSQLRecordClass;
begin
  if (self<>nil) and (aTable<>nil) then begin
    Props := PPointer(PtrInt(aTable)+vmtAutoTable)^;
    if (Props<>nil) and (Props.fModelMax<fTablesMax) then

#100 mORMot 1 » ORM and date queries[Solved] » 2019-03-30 12:58:42

larand54
Replies: 12

The following does not work as I expected:

  Baby := TSQLBaby.Create;
  Baby.name := 'Kurt';
  Baby.Sex := sMale;
  dt := encodeDate(2018,01,03);
  Baby.BirthDate := dt;
  Baby.Address := 'Lindesberg';
  aClient.Add(Baby, true);
  Baby.Free;
  
  Baby := TSQLBaby.CreateAndFillPrepare( aClient, 'BirthDate = ?',[DateToSQL(dt)]);
  while Baby.FillOne do
  begin
    Memo1.lines.Add(Format('>>>>>>>>>>  %s - %s ',[Baby.Name, Baby.Address])+' // '+FormatDateTime('yyyy-mm-dd', Baby.BirthDate));
  end;

BirthDate and dt is clearly the same date so why didn't I get a hit from the query?

Board footer

Powered by FluxBB