#251 Re: mORMot 1 » How to make TSynLog give "all" line numbers ? » 2014-05-12 17:21:27

Thank you for your time !

Now, it seems to me that TSynLog.Enter; and ILog := TSynLog.Enter; gives line number, but ILog := TSynLog.Enter(self,'FormCreate'); does not. Could you help to comment ... big_smile

#252 Re: mORMot 1 » How to make TSynLog give "all" line numbers ? » 2014-05-12 17:09:10

Thank you for your knowledgeable comments on TSQLLog and TSynLog !

About the line number, please see my previous post with correct information ... big_smile

#253 Re: mORMot 1 » How to make TSynLog give "all" line numbers ? » 2014-05-12 16:54:45

Oh ! Thank you very much for your help !

It seems that using TSQLLog from mORMot.pas instead of TSynLog from SynCommons.pas gives line number ! big_smile

I wonder is this by design ? Is TSynLog not to be used if one wants line numbers ?

Sorry for the misinformation !

TSynLog.Enter; gives the line number.

procedure TForm1.FormCreate(Sender: TObject);
var
  ILog: ISynLog;
begin
  with TSynLog.Family do
  begin
    Level := LOG_VERBOSE;
  end;
  TSynLog.Enter;

ILog := TSynLog.Enter(self,'FormCreate'); does not give the line number.

procedure TForm1.FormCreate(Sender: TObject);
var
  ILog: ISynLog;
begin
  with TSynLog.Family do
  begin
    Level := LOG_VERBOSE;
  end;
  ILog := TSynLog.Enter(self,'FormCreate');

I wonder if this is by design ?

Furthermore, could you help to comment about TSQLLog and TSynLog (for example, best practices) ? big_smile

#254 mORMot 1 » Could you add function type AnyAnsiToUTF8 besides the procedure type ? » 2014-05-12 15:20:04

ComingNine
Replies: 2

Currently there is only procedure type AnyAnsiToUTF8. 

Could you also add function type AnyAnsiToUTF8 besides the procedure type ?

The reason is to make it easier to transform AnsiString into RawUTF8 in unicode Delphi. big_smile

#255 Re: mORMot 1 » How to make TSynLog give "all" line numbers ? » 2014-05-12 13:32:55

Thank you for your help! Enable "stack frames" under "Compiler" for D7 does not help. Furthermore, "Stack frames" under "Compiler" for DXE is already enabled.

Could you help to comment ?

#256 mORMot 1 » How to make TSynLog give "all" line numbers ? » 2014-05-12 13:12:42

ComingNine
Replies: 9

Source code

unit Unit1;

interface

uses
  SynCommons,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, 
  Controls, Forms, Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  ILog: ISynLog;
  sl: TStringList;
begin
  with TSynLog.Family do
  begin
    Level := LOG_VERBOSE;
    PerThreadLog := ptIdentifiedInOnFile;
    RotateFileCount := 5;
    RotateFileSizeKB := 20*1024; // rotate by 20 MB logs
  end;
  ILog := TSynLog.Enter(self,'FormCreate');

  // 1
  // sl.Add(''); // <--- GPF

end;

end.

Problem description

Without the "GPF" line, the log is as below. Note the line number for FormCreate is not shown. On Page 105 of latest SAD 1.18, the line number for TestLog is shown.

20140512 14502252  +    TForm1(00762674).FormCreate
20140512 14502252  -    00.000.001

With the "GPF" line, the log is as below. Note the line number for where the exception occurs is not shown.

20140512 15083546  +    TForm1(00762674).FormCreate
20140512 15083546 EXCOS 	EAccessViolation (C0000005) at  stack trace API 0002D204 SynCommons.SynRtlUnwind (30796) 00002F6C System.@HandleAnyException (9574) 00058EFF Forms.TCustomForm.DoCreate (2648) 00058BDF Forms.TCustomForm.AfterConstruction (2576) 0006029C Forms.TApplication.CreateForm (6947) 00061D00 VCL (13) 
20140512 15083546  -    00.000.165

Settings for Delphi 7 and Delphi XE.

D7 Compiler WENCxlJ.png
D7 Linker laZBkNo.png

DXE Compiler BTdaxvD.png
DXE Linker TGm3mDK.png

#257 Re: mORMot 1 » Will there be TSynLog and TMemoryMapText for linux OS ? » 2014-05-11 16:54:59

Two IDEs are used Delphi 7 (CrossKylix) and Delphi XE. (Non-visual code is using D7 syntax but edited with DXE.) big_smile

#258 Re: mORMot 1 » Will there be TSynLog and TMemoryMapText for linux OS ? » 2014-05-11 14:58:54

Thank you for your comments very much !

CrossKylix is a good idea: (1) CrossKylix is convenient (2) From the FPC mail list archives, it seems that CrossKylix gives better performance and compatibility while FPC gives more targets. (3) That Delphi 7 is one of your favorite IDEs probably means the Linux/CrossKylix part will be in good sync with the Delphi part.

FPC may become useful when CrossKylix fails mainstream Linux distributions. CodeTyphon, bare Lazarus or even CrossFPC are all good choices.

That will be my pleasure! Furthermore, once the linux (Kylix/FPC) version is ready, the FPC gurus (for example, Graeme Geldenhuys who contributes to tiOPF and fpGUI, which might share equally good concepts with your great framework) may also start to use it and like it. Involvements from these experts should be be helpful and important.

#259 Re: mORMot 1 » Will there be TSynLog and TMemoryMapText for linux OS ? » 2014-05-11 10:49:22

The HTTP/IOCP part is really beyond me.

Nonetheless, could you help to comment specifically about what one could do to help to make SynCommons compilable under Linux ? Thus the goodies inside the SynCommons (TSynLog and/or TMemoryMapText) can be used under Linux...

#260 Re: mORMot 1 » How to model "Classroom - Class" relationship using sharding ? » 2014-05-10 11:31:46

Thanks for your comments. I have been reading your SAD document but have no clue.

Do you mean it is possible to model this "classroom-class" relationship using sharding ?

If you think this is an improper question for you, please just say so . smile

#261 mORMot 1 » How to model "Classroom - Class" relationship using sharding ? » 2014-05-09 18:08:01

ComingNine
Replies: 3

Sorry for this newbie question !

The sharding facilitated by mORMot sounds very interesting ! I want to learn this practice with a "Classroom - class" relationship:

"Classroom" :
(1) "Classroom" instances, which will be available for a certain period (e.g., half a day), will be announced.
(2) Each "Classroom" can accommodate one "Class" at a given time. 
(3) Once "Classroom" is free from a previous "Class", it may accommodate another "Class".

"Class"
(1) "Class" instances, which will need to be taught at a given time, will be announced.
(2) Each "Class" will be taught in one "Classroom" at a given time.

With multiple-table-paradigm, a new "Assignment" table can help to model this relationship.

Right now I don't have any idea how to model this relationship using sharding. Could you help to give me some suggestions ?

If it is not possible to use sharding, could you help to comment how to identify whether sharding fits a relationship in practice ?

Many thanks for your time and comments !

#263 Re: mORMot 1 » How to have an archived table besides a normal one, with one TSQLRec ? » 2014-05-08 17:23:48

Thank you for your helpful comments very much ! This should work !

#264 Re: mORMot 1 » Newbie question of using TSQLRecordMany. » 2014-05-08 17:22:15

Thank you for your comment !

If the internal-mode SQLite is used (i.e. TSQLRestServerDB), can RollBack affect all three (Source, Dest, Pivot) tables ? smile

Furthermore, could you help to comment whether these three are equivalent when all three tables are being updated ? TransactionBegin (TSQLSource), TransactionBegin (TSQLDest), TransactionBegin (TSQLDestPivot) ? big_smile

#265 Re: mORMot 1 » Newbie question of using TSQLRecordMany. » 2014-05-08 14:27:12

Thank you for your comments ! I wonder which table to pass into TransactionBegin when multiple tables (Source,Dest,Pivot) are to be updated ? Will the RollBack affect all the tables ?

For example, MySql seems not able to rollback a multiple-table transaction http://stackoverflow.com/questions/3094398, while MSSql seems capable http://social.msdn.microsoft.com/Forums … ransactsql .

#266 mORMot 1 » How to have an archived table besides a normal one, with one TSQLRec ? » 2014-05-08 14:07:05

ComingNine
Replies: 2

If the number of the records gets larger (than 1000), it seems useful to move the records that are three days old from one table into another table (as an archive). Could you help to comment whether it is possible to implement this situation with one TSQLRecord descendant, instead of one TSQLRecordActive and one TSQLRecordNonActive with identical properties ? big_smile

(PS: Maybe it is not possible because ORM applies strict relation between class and table, as seen from this link http://stackoverflow.com/questions/8018597/)

#268 mORMot 1 » Can 1 server and N clients (in threads) coexist in 1 standalone EXE ? » 2014-05-07 14:21:50

ComingNine
Replies: 1

For the HTTP mORMot architecture, the server can handle multiple clients (via http.sys or the other pure-pascal implementation) simultaneously (as seen at the client side) .

For the stand-alone mORMot architecture, can one server and multiple clients (one client per thread) coexist ? The reason to ask is that this might be thought as "producer-consumer" situation.

For example, if I create one TSQLRestServerDB, and use this existing TSQLRestServerDB to create multiple TSQLRestClientDB instances (one client per thread):

  1. Can the server handle the underlying ORM thread-safely ?

  2. How does the server achieve the ORM thread-safety ? Through a queue, or via spawned threads (e.g., TSQLRestClientDB spawns threads to deal with each request of TSQLRestClientDB, when the request of customized service-method takes quite a long time to complete ) ?

  3. Are there special things to pay attention to, for example, in the URI or customized service-methods in the TSQLRestServerDB, to ensure thread-safety for this situation ?

#269 Re: mORMot 1 » MongoDB direct access and ORM/ODM integration with mORMot » 2014-05-07 08:40:43

Very nice blog ! (Didn't see that in SAD v1.18 big_smile)

Thank you for your helpful comments !

Could you also help to comment on the pros and cons to use "SQLite and sharding" instead of "MongoDB" ? big_smile

#270 Re: mORMot 1 » MongoDB direct access and ORM/ODM integration with mORMot » 2014-05-07 08:02:21

Really nice work ! Could you elaborate on ACIDity or the best practices in your test against MongoDB ?
For example, this SO post says MongoDB is only ACID when writing a single record into a single table. http://stackoverflow.com/questions/7149890
For another example, the MongoDB FAQ says the "records/documents" do not need to have the same schema. Is this still so when used with mORMot ? http://docs.mongodb.org/manual/faq/fundamentals/

#271 Re: mORMot 1 » Newbie question of using TSQLRecordMany. » 2014-05-05 07:55:15

Could you help to comment the questions above ? i.e. (1) why the sample app above runs faster within IDE than standalone ? (2) what to pass into TransactionBegin when multiple tables are to be updated ?

Thank you very much for your time ! big_smile

#272 Re: mORMot 1 » Test or use case for TRestClient.RTreeMatch ? » 2014-05-05 07:49:16

Thank you very much for your helpful comments !

#273 mORMot 1 » Test or use case for TRestClient.RTreeMatch ? » 2014-05-04 21:48:07

ComingNine
Replies: 2

Page 174 in the SAD doc v1.18 describes TRestClient.RTreeMatch. However, could you create test case or use case about it ?

In SynSelfTests.pas, there is a test of TSQLRecordRTree, which only involves RTree index, but not TRestClient.RTreeMatch, which involves both data and RTree index. 

For example, it is not clear why the TSQLRecordMapData has a BlobField containing the textual representation of the coordinates exposed by TSQLRecordMapBox. Are these two types explicitly defined ? Or TSQLRecordMapData somehow includes a TSQLRecordMapBox. Many Thanks!... big_smile

#274 Re: mORMot 1 » Will there be TSynLog and TMemoryMapText for linux OS ? » 2014-05-02 09:51:22

Thank you for your time and efforts ! A linux version of mORMot framework should benefit many people !

#275 Re: mORMot 1 » How to print forum post better ? » 2014-05-02 09:49:19

Thank you very much for your help ! SDD v1.17 section 1.9 describes design about ORM.

There seems to be SAD v1.18 around. Is there corresponding SDD v1.18 to read and learn ? roll

#276 mORMot 1 » How to print forum post better ? » 2014-05-01 22:40:10

ComingNine
Replies: 5

Take http://synopse.info/forum/viewtopic.php?id=336 for example.

Using IE/Chrome, the printed forum post looks not very well. There is too much space in the printed version.

Could you help to comment how to print forum post better ?

#277 Re: mORMot 1 » Will there be TSynLog and TMemoryMapText for linux OS ? » 2014-05-01 22:16:45

Thank you for your efforts very much ! That is indeed a great news ! big_smile

It probably needs mentioning that http.sys is in "kernel land" but lighhtpd is in "user land" . Does this have a consequence ?
(Note, this comment is from google/internet...)

#278 Re: mORMot 1 » How does our unit testing work? » 2014-05-01 20:50:18

Thank you for your helpful comments !

#279 Re: mORMot 1 » Will there be TSynLog and TMemoryMapText for linux OS ? » 2014-05-01 20:44:14

Thank you for your time, efforts and knowledgeable comments !

Sorry that I know nothing about this topic... Please check this SO post about IOCP under Linux (In short, epoll seems to be used under Linux instead of IOCP)
http://stackoverflow.com/questions/2794535

#280 Re: mORMot 1 » Newbie question of using TSQLRecordMany. » 2014-05-01 14:48:24

Could you help to comment another two questions:

1. It seems when running within IDE, the time consumed is much less than that when running standalone. Could you help to comment ?

      For example: running within IDE gives,
     

        - Test TSQL record many: 6,113 assertions passed  138.87ms
        Total failed: 0 / 6,113  - My test TSQL record many PASSED  139.14ms
      

      running standalone gives,
     

        - Test TSQL record many: 5,813 assertions passed  479.87ms
        Total failed: 0 / 5,813  - My test TSQL record many PASSED  481.13ms
      

2. There are two occurrences of "TransactionBegin" in "uTestTSQLRecordMany.pas". In the source code comments of "TransactionBegin", it is written "the aTable parameter is not used yet". Is this description correct ? I mean, there are descriptions in the doc v1.18 saying "Locking of the database at the record level (page 157)" and "at sqlite 3 engine leve, there is some kind of giant lock (page 249)".

If not, which aTable should one pass ? For example, in the first occurrence of "TransactionBegin" (line 89), TSQLSource is passed even though three tables are being effected. Is this procedure correct ?

3.
The source code corrected from my mistakes is pasted below for your convenience:

The console program source code is

program Learn2_TSQLRecordMany;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  SynSQLite3Static,
  uTestTSQLRecordMany in 'uTestTSQLRecordMany.pas';

{$R *.res}

begin
 with TMyTestSuit.Create do
   try
//     ToConsole := @Output; // so we will see something on screen
     Run;
     readln;
   finally 
     Free; 
   end;
end.

The test unit source code is

unit uTestTSQLRecordMany;

interface

uses
  SysUtils,
  SynCommons,
  mORMot,
  mORMotSQLite3;

type

  TMyTestTSQLRecordMany = class(TSynTestCase)
  private
    fDatabase: TSQLRest;
    fModel: TSQLModel;
  published
    procedure TestTSQLRecordMany;
  end;

  TMyTestSuit = class(TSynTests)
  published
    procedure RegMyTestSuit;
  end;

type

  TSQLSource = class;
  TSQLDest = class;
  TSQLDestPivot = class(TSQLRecordMany)
  private
    fSource: TSQLSource;
    fDest: TSQLDest;
    fTime: TDateTime;
  published
    property Source: TSQLSource read fSource;
    property Dest: TSQLDest read fDest;
    property AssociationTime: TDateTime read fTime write fTime;
  end;
  TSQLSource = class(TSQLRecordSigned)
  private
    fDestList: TSQLDestPivot;
  published
    property SignatureTime;
    property Signature;
    property DestList: TSQLDestPivot read fDestList;
  end;
  TSQLDest = class(TSQLRecordSigned)
  published
    property SignatureTime;
    property Signature;
  end;

implementation

// !!! Modified !!!
//procedure InternalTestMany(Test: TSynTestCase; aClient: TSQLRestClient);
procedure InternalTestMany(Test: TSynTestCase; aClient: TSQLRest);
var MS: TSQLSource;
    MD, MD2: TSQLDest;
    i: integer;
    sID, dID: array[1..100] of Integer;
    res: TIntegerDynArray;
  procedure CheckOK;
  begin
    if Test.CheckFailed(MS.FillTable<>nil) then
      exit;
    Test.Check(MS.FillTable.RowCount>=length(sId));
    while MS.FillOne do begin
      Test.Check(MS.DestList.Source.fID=MS.fID);
      Test.Check(MS.DestList.Dest.SignatureTime<>0);
      MS.ClearProperties;
      MS.DestList.Source.ClearProperties;
      MS.DestList.Dest.ClearProperties;
    end;
    MS.FillClose;
  end;
begin
  MS := TSQLSource.Create;
  MD := TSQLDest.Create;
  with Test do
  try
    MD.fSignatureTime := TimeLogNow;
    MS.fSignatureTime := MD.fSignatureTime;
    Check(MS.DestList<>nil);
    Check(MS.DestList.InheritsFrom(TSQLRecordMany));
// !!! Modified !!!
//    Check(aClient.TransactionBegin(TSQLSource)); // faster process
    Check(aClient.TransactionBegin(TSQLSource, CONST_AUTHENTICATION_NOT_USED)); // faster process
    for i := 1 to high(dID) do begin
      MD.fSignature := FormatUTF8('% %',[aClient.ClassName,i]);
      dID[i] := aClient.Add(MD,true);
      Check(dID[i]>0);
    end;
    for i := 1 to high(sID) do begin
      MS.fSignature := FormatUTF8('% %',[aClient.ClassName,i]);
      sID[i] := aClient.Add(MS,True);
      Check(sID[i]>0);
      MS.DestList.AssociationTime := i;
      Check(MS.DestList.ManyAdd(aClient,sID[i],dID[i])); // associate both lists
      Check(not MS.DestList.ManyAdd(aClient,sID[i],dID[i],true)); // no dup
    end;
// !!! Modified !!!
//    aClient.Commit;
    aClient.Commit(CONST_AUTHENTICATION_NOT_USED);
    for i := 1 to high(dID) do begin
      Check(MS.DestList.SourceGet(aClient,dID[i],res));
      if not CheckFailed(length(res)=1) then
        Check(res[0]=sID[i]);
      Check(MS.DestList.ManySelect(aClient,sID[i],dID[i]));
      Check(MS.DestList.AssociationTime=i);
    end;
    for i := 1 to high(sID) do begin
      Check(MS.DestList.DestGet(aClient,sID[i],res));
      if CheckFailed(length(res)=1) then
        continue; // avoid GPF
      Check(res[0]=dID[i]);
      Check(MS.DestList.FillMany(aClient,sID[i])=1);
      Check(MS.DestList.FillOne);
      Check(Integer(MS.DestList.Source)=sID[i]);
      Check(Integer(MS.DestList.Dest)=dID[i]);
      Check(MS.DestList.AssociationTime=i);
      Check(not MS.DestList.FillOne);
      Check(MS.DestList.DestGetJoined(aClient,'',sID[i],res));
      if not CheckFailed(length(res)=1) then
        Check(res[0]=dID[i]);
      // !!! Modified !!!
      // Check(MS.DestList.DestGetJoined(aClient,'ADest.SignatureTime=:(0):',sID[i],res));
      Check(MS.DestList.DestGetJoined(aClient,'Dest.SignatureTime=:(0):',sID[i],res));
      Check(length(res)=0);
      Check(MS.DestList.DestGetJoined(aClient,      
        // !!! Modified !!!
        // FormatUTF8('ADest.SignatureTime=?',[],[MD.SignatureTime]),sID[i],res));
        FormatUTF8('Dest.SignatureTime=?',[],[MD.SignatureTime]),sID[i],res));
//   'ADest.SignatureTime=:('+Int64ToUTF8(MD.SignatureTime)+'):',sID[i],res));
      if CheckFailed(length(res)=1) then
        continue; // avoid GPF
      Check(res[0]=dID[i]);
      MD2 := MS.DestList.DestGetJoined(aClient,
        // !!! Modified !!!
        // FormatUTF8('ADest.SignatureTime=?',[],[MD.SignatureTime]),sID[i]) as TSQLDest;
        FormatUTF8('Dest.SignatureTime=?',[],[MD.SignatureTime]),sID[i]) as TSQLDest;
//   'ADest.SignatureTime=:('+Int64ToUTF8(MD.SignatureTime)+'):',sID[i]) as TSQLDest;
      if CheckFailed(MD2<>nil) then
        continue;
      try
        Check(MD2.FillOne);
        Check(MD2.ID=dID[i]);
        Check(MD2.Signature=FormatUTF8('% %',[aClient.ClassName,i]));
      finally
        MD2.Free;
      end;
    end;
    Check(MS.FillPrepareMany(aClient,nil,[],[]));
    CheckOK;    
    Check(MS.FillPrepareMany(aClient,'DestList.Dest.SignatureTime<>?',[],[0]));
    CheckOK;
    Check(MS.FillPrepareMany(aClient,
      'DestList.Dest.SignatureTime<>% and RowID>=? and DestList.AssociationTime<>0 '+
      'and SignatureTime=DestList.Dest.SignatureTime '+
      'and DestList.Dest.Signature<>"DestList.AssociationTime"',[0],[sID[1]]));
    if CheckFailed(MS.FillTable<>nil) then
      exit;
    Check(MS.FillTable.RowCount=length(sID));
    for i := 1 to high(sID) do begin
      MS.SignatureTime := 0;
      MS.DestList.Dest.SignatureTime := 0;
      if CheckFailed(MS.FillOne) then
        break;
      Check(MS.fID=sID[i]);
      Check(MS.SignatureTime=MD.fSignatureTime);
      Check(MS.DestList.AssociationTime=i);
      Check(MS.DestList.Dest.fID=dID[i]);
      Check(MS.DestList.Dest.SignatureTime=MD.fSignatureTime);
      Check(MS.DestList.Dest.Signature=FormatUTF8('% %',[aClient.ClassName,i]));
    end;
    MS.FillClose;
// !!! Modified !!!
//    Check(aClient.TransactionBegin(TSQLDestPivot)); // faster process
    Check(aClient.TransactionBegin(TSQLDestPivot, CONST_AUTHENTICATION_NOT_USED)); // faster process
    for i := 1 to high(sID) shr 2 do
      Check(MS.DestList.ManyDelete(aClient,sID[i*4],dID[i*4]));
// !!! Modified !!!
//    aClient.Commit;
    aClient.Commit(CONST_AUTHENTICATION_NOT_USED);
    for i := 1 to high(sID) do
      if i and 3<>0 then begin
        Check(MS.DestList.ManySelect(aClient,sID[i],dID[i]));
        Check(MS.DestList.AssociationTime=i);
      end else
        Check(not MS.DestList.ManySelect(aClient,sID[i],dID[i]));
  finally
    MD.Free;
    MS.Free;
  end;
end;

{ TMyTestTSQLRecordMany }

procedure TMyTestTSQLRecordMany.TestTSQLRecordMany;
begin
  fModel := TSQLModel.Create([TSQLSource, TSQLDest, TSQLDestPivot]);;
  fDatabase := TSQLRestServerDB.Create(fModel, ChangeFileExt(paramstr(0),'.db3'));
  TSQLRestServerDB(fDatabase).CreateMissingTables(0);
  InternalTestMany(Self, fDatabase);
end;

{ TMyTestSuit }

procedure TMyTestSuit.RegMyTestSuit;
begin
  AddCase([TMyTestTSQLRecordMany]);
end;

end.

#281 Re: mORMot 1 » Newbie question of using TSQLRecordMany. » 2014-05-01 14:14:10

Sorry ! My fault ! big_smile

"TSQLADest" is typed by me as "TSQLDest" in the Delphi type declarations.

Thus, when DestGetJoined is called, the parameter string needs to be changed in accordance. tongue

That is to say, "ADest.SignatureTime" -> "Dest.SignatureTime"...

#282 mORMot 1 » Newbie question of using TSQLRecordMany. » 2014-05-01 10:32:51

ComingNine
Replies: 7

There is an ESQLite3Exception complaining "no such column: XXX". However, when the sqlite database file is opened with SqliteMaestro, the column is there. Could you help to comment ?

The console program source code is

program Learn2_TSQLRecordMany;

uses
  SysUtils,
  SynSQLite3Static,
  uTestTSQLRecordMany in 'uTestTSQLRecordMany.pas';

{$R *.res}

begin
 with TMyTestSuit.Create do 
   try 
//     ToConsole := @Output; // so we will see something on screen
     Run;
     readln; 
   finally 
     Free; 
   end;
end.

The test unit source code is

unit uTestTSQLRecordMany;

interface

uses
  SysUtils,
  SynCommons,
  mORMot,
  mORMotSQLite3;

type

  TMyTestTSQLRecordMany = class(TSynTestCase)
  private
    fDatabase: TSQLRest;
    fModel: TSQLModel;
  published
    procedure TestTSQLRecordMany;
  end;

  TMyTestSuit = class(TSynTests)
  published
    procedure RegMyTestSuit;
  end;

type

  TSQLSource = class;
  TSQLDest = class;
  TSQLDestPivot = class(TSQLRecordMany)
  private
    fSource: TSQLSource;
    fDest: TSQLDest;
    fTime: TDateTime;
  published
    property Source: TSQLSource read fSource;
    property Dest: TSQLDest read fDest;
    property AssociationTime: TDateTime read fTime write fTime;
  end;
  TSQLSource = class(TSQLRecordSigned)
  private
    fDestList: TSQLDestPivot;
  published
    property SignatureTime;
    property Signature;
    property DestList: TSQLDestPivot read fDestList;
  end;
  TSQLDest = class(TSQLRecordSigned)
  published
    property SignatureTime;
    property Signature;
  end;

implementation

// !!! Modified !!!
//procedure InternalTestMany(Test: TSynTestCase; aClient: TSQLRestClient);
procedure InternalTestMany(Test: TSynTestCase; aClient: TSQLRest);
var MS: TSQLSource;
    MD, MD2: TSQLDest;
    i: integer;
    sID, dID: array[1..100] of Integer;
    res: TIntegerDynArray;
  procedure CheckOK;
  begin
    if Test.CheckFailed(MS.FillTable<>nil) then
      exit;
    Test.Check(MS.FillTable.RowCount>=length(sId));
    while MS.FillOne do begin
      Test.Check(MS.DestList.Source.fID=MS.fID);
      Test.Check(MS.DestList.Dest.SignatureTime<>0);
      MS.ClearProperties;
      MS.DestList.Source.ClearProperties;
      MS.DestList.Dest.ClearProperties;
    end;
    MS.FillClose;
  end;
begin
  MS := TSQLSource.Create;
  MD := TSQLDest.Create;
  with Test do
  try
    MD.fSignatureTime := TimeLogNow;
    MS.fSignatureTime := MD.fSignatureTime;
    Check(MS.DestList<>nil);
    Check(MS.DestList.InheritsFrom(TSQLRecordMany));
// !!! Modified !!!
//    Check(aClient.TransactionBegin(TSQLSource)); // faster process
    Check(aClient.TransactionBegin(TSQLSource, CONST_AUTHENTICATION_NOT_USED)); // faster process
    for i := 1 to high(dID) do begin
      MD.fSignature := FormatUTF8('% %',[aClient.ClassName,i]);
      dID[i] := aClient.Add(MD,true);
      Check(dID[i]>0);
    end;
    for i := 1 to high(sID) do begin
      MS.fSignature := FormatUTF8('% %',[aClient.ClassName,i]);
      sID[i] := aClient.Add(MS,True);
      Check(sID[i]>0);
      MS.DestList.AssociationTime := i;
      Check(MS.DestList.ManyAdd(aClient,sID[i],dID[i])); // associate both lists
      Check(not MS.DestList.ManyAdd(aClient,sID[i],dID[i],true)); // no dup
    end;
// !!! Modified !!!
//    aClient.Commit;
    aClient.Commit(CONST_AUTHENTICATION_NOT_USED);
    for i := 1 to high(dID) do begin
      Check(MS.DestList.SourceGet(aClient,dID[i],res));
      if not CheckFailed(length(res)=1) then
        Check(res[0]=sID[i]);
      Check(MS.DestList.ManySelect(aClient,sID[i],dID[i]));
      Check(MS.DestList.AssociationTime=i);
    end;
    for i := 1 to high(sID) do begin
      Check(MS.DestList.DestGet(aClient,sID[i],res));
      if CheckFailed(length(res)=1) then
        continue; // avoid GPF
      Check(res[0]=dID[i]);
      Check(MS.DestList.FillMany(aClient,sID[i])=1);
      Check(MS.DestList.FillOne);
      Check(Integer(MS.DestList.Source)=sID[i]);
      Check(Integer(MS.DestList.Dest)=dID[i]);
      Check(MS.DestList.AssociationTime=i);
      Check(not MS.DestList.FillOne);
      Check(MS.DestList.DestGetJoined(aClient,'',sID[i],res));
      if not CheckFailed(length(res)=1) then
        Check(res[0]=dID[i]);
      Check(MS.DestList.DestGetJoined(aClient,'ADest.SignatureTime=:(0):',sID[i],res));
      Check(length(res)=0);
      Check(MS.DestList.DestGetJoined(aClient,
        FormatUTF8('ADest.SignatureTime=?',[],[MD.SignatureTime]),sID[i],res));
//   'ADest.SignatureTime=:('+Int64ToUTF8(MD.SignatureTime)+'):',sID[i],res));
      if CheckFailed(length(res)=1) then
        continue; // avoid GPF
      Check(res[0]=dID[i]);
      MD2 := MS.DestList.DestGetJoined(aClient,
        FormatUTF8('ADest.SignatureTime=?',[],[MD.SignatureTime]),sID[i]) as TSQLDest;
//   'ADest.SignatureTime=:('+Int64ToUTF8(MD.SignatureTime)+'):',sID[i]) as TSQLDest;
      if CheckFailed(MD2<>nil) then
        continue;
      try
        Check(MD2.FillOne);
        Check(MD2.ID=dID[i]);
        Check(MD2.Signature=FormatUTF8('% %',[aClient.ClassName,i]));
      finally
        MD2.Free;
      end;
    end;
    Check(MS.FillPrepareMany(aClient,nil,[],[]));
    CheckOK;
    Check(MS.FillPrepareMany(aClient,'DestList.Dest.SignatureTime<>?',[],[0]));
    CheckOK;
    Check(MS.FillPrepareMany(aClient,
      'DestList.Dest.SignatureTime<>% and RowID>=? and DestList.AssociationTime<>0 '+
      'and SignatureTime=DestList.Dest.SignatureTime '+
      'and DestList.Dest.Signature<>"DestList.AssociationTime"',[0],[sID[1]]));
    if CheckFailed(MS.FillTable<>nil) then
      exit;
    Check(MS.FillTable.RowCount=length(sID));
    for i := 1 to high(sID) do begin
      MS.SignatureTime := 0;
      MS.DestList.Dest.SignatureTime := 0;
      if CheckFailed(MS.FillOne) then
        break;
      Check(MS.fID=sID[i]);
      Check(MS.SignatureTime=MD.fSignatureTime);
      Check(MS.DestList.AssociationTime=i);
      Check(MS.DestList.Dest.fID=dID[i]);
      Check(MS.DestList.Dest.SignatureTime=MD.fSignatureTime);
      Check(MS.DestList.Dest.Signature=FormatUTF8('% %',[aClient.ClassName,i]));
    end;
    MS.FillClose;
// !!! Modified !!!
//    Check(aClient.TransactionBegin(TSQLDestPivot)); // faster process
    Check(aClient.TransactionBegin(TSQLDestPivot, CONST_AUTHENTICATION_NOT_USED)); // faster process
    for i := 1 to high(sID) shr 2 do
      Check(MS.DestList.ManyDelete(aClient,sID[i*4],dID[i*4]));
// !!! Modified !!!
//    aClient.Commit;
    aClient.Commit(CONST_AUTHENTICATION_NOT_USED);
    for i := 1 to high(sID) do
      if i and 3<>0 then begin
        Check(MS.DestList.ManySelect(aClient,sID[i],dID[i]));
        Check(MS.DestList.AssociationTime=i);
      end else
        Check(not MS.DestList.ManySelect(aClient,sID[i],dID[i]));
  finally
    MD.Free;
    MS.Free;
  end;
end;

{ TMyTestTSQLRecordMany }

procedure TMyTestTSQLRecordMany.TestTSQLRecordMany;
begin
  fModel := TSQLModel.Create([TSQLSource, TSQLDest, TSQLDestPivot]);;
  fDatabase := TSQLRestServerDB.Create(fModel, ChangeFileExt(paramstr(0),'.db3'));
  TSQLRestServerDB(fDatabase).CreateMissingTables(0);
  InternalTestMany(Self, fDatabase);
end;

{ TMyTestSuit }

procedure TMyTestSuit.RegMyTestSuit;
begin
  AddCase([TMyTestTSQLRecordMany]);
end;

end.

The exception is

First chance exception at $75A2C41F. Exception class ESQLite3Exception with message 'no such column: ADest.SignatureTime'. Process Learn2_TSQLRecordMany.exe (11172)

The stack-trace is

:75a2c41f KERNELBASE.RaiseException + 0x58
SynSQLite3.sqlite3_check(7583624,1)
SynSQLite3.TSQLRequest.Prepare(7583624,'SELECT Dest.RowID FROM Dest,DestPivot WHERE DestPivot.Source=? AND DestPivot.Dest=Dest.RowID AND ADest.SignatureTime=?')
SynSQLite3.TSQLStatementCached.Prepare('SELECT Dest.RowID FROM Dest,DestPivot WHERE DestPivot.Source=? AND DestPivot.Dest=Dest.RowID AND ADest.SignatureTime=?')
mORMotSQLite3.TSQLRestServerDB.GetAndPrepareStatement('SELECT Dest.RowID FROM Dest,DestPivot WHERE DestPivot.Source=:(1): AND DestPivot.Dest=Dest.RowID AND ADest.SignatureTime=:(0):')
mORMotSQLite3.TSQLRestServerDB.EngineList('SELECT Dest.RowID FROM Dest,DestPivot WHERE DestPivot.Source=:(1): AND DestPivot.Dest=Dest.RowID AND ADest.SignatureTime=:(0):',False,nil)
mORMot.TSQLRestServer.ExecuteList((...),'SELECT Dest.RowID FROM Dest,DestPivot WHERE DestPivot.Source=:(1): AND DestPivot.Dest=Dest.RowID AND ADest.SignatureTime=:(0):')
mORMot.TSQLRecordMany.DestGetJoinedTable($6E3660,'ADest.SignatureTime=:(0):',1,jkDestID,'')
mORMot.TSQLRecordMany.DestGetJoined($6E3660,'ADest.SignatureTime=:(0):',1,())
uTestTSQLRecordMany.InternalTestMany($7836D0,$6E3660)
uTestTSQLRecordMany.TMyTestTSQLRecordMany.TestTSQLRecordMany
SynCommons.TSynTests.Run
Learn2_TSQLRecordMany.Learn2_TSQLRecordMany
:753433aa kernel32.BaseThreadInitThunk + 0x12
:778b9ef2 ntdll.RtlInitializeExceptionChain + 0x63
:778b9ec5 ntdll.RtlInitializeExceptionChain + 0x36

It should be noted that even though there is no occurrence of TSynLog, the app will give a log file when compiled with Delphi 7, but no log file when compiled with Delphi XE6.

#283 Re: mORMot 1 » How does our unit testing work? » 2014-05-01 10:08:01

On Page 393 of the doc v1.18, there is a "ToConsole := @Output". In your first post above, there is a "ToConsole: ^Text;".

However, this "ToConsole" seems to be removed in the NightlyBuild. Could you help to comment the reason to remove this and what is the replacement ?

#284 Re: mORMot 1 » Will there be TSynLog and TMemoryMapText for linux OS ? » 2014-05-01 08:01:19

Yes, because of the great comments in this SO post. http://stackoverflow.com/questions/3387501/

Oh! When your great framework turns cross-platform, will it be with Kylix or FPC ?

Oh! How do your server apps utilize mORMot with crosskylix ? Or your server apps only utilize your enhanced RTL ?

#285 mORMot 1 » Will there be TSynLog and TMemoryMapText for linux OS ? » 2014-05-01 07:25:11

ComingNine
Replies: 39

TSynLog is a very good log framework! TMemoryMapText provides a very fast file-reading capability!

Both of them are contained in SynCommons.pas, I am therefore wondering if they can be used under Linux OS ? If so, how should one consume them ? (For example, a "Kylix" DEF can be seen in SynCommons.pas. However, when Delphi7/CrossKylix is used to compile a application using TSynLog, the process stops when compiling SynLz.)

#286 Re: mORMot 1 » Error on Update after get the last source » 2014-04-30 11:26:13

Could you help to comment:
(1) the reason not to test against Delphi XE?
(2) whether it is possible for your forum to differentiate the posts (read/unread, new/old/edited)?

big_smile

#287 Re: mORMot 1 » Error on Update after get the last source » 2014-04-30 06:36:17

Fantastic ! cool

(Can you also test against Delphi XE ?)

#288 Re: mORMot 1 » Error on Update after get the last source » 2014-04-29 14:31:18

"Sounds more like a problem of your system code page - some tests are working only with a Windows 1252 code page..."

Does this mean that even every NightlyBuild passes your tests  ? roll

#289 Re: mORMot 1 » Error on Update after get the last source » 2014-04-29 07:58:08

With the nightly build, TestSQL3.dpr will fail some tests. Not sure whether it is related...

Delphi XE debug

   Synopse mORMot Framework Automated tests
  ------------------------------------------


1. Synopse libraries

 1.1. Low level common:
  - System copy record: 22 assertions passed  186us
  - TRawUTF8List: 70,005 assertions passed  116.96ms
  - TDynArray: 1,027,702 assertions passed  263.56ms
  - TDynArrayHashed: 1,200,629 assertions passed  192.50ms
  - TObjectListHashed: 999,874 assertions passed  739.55ms
  - TObjectDynArrayWrapper: 167,501 assertions passed  30.29ms
  - Fast string compare: 7 assertions passed  222us
  - IdemPropName: 30 assertions passed  222us
  - Url encoding: 105 assertions passed  1.64ms
  - GUID: 9,005 assertions passed  3.67ms
  - IsMatch: 599 assertions passed  309us
  - Soundex: 35 assertions passed  157us
  - Numerical conversions: 1,066,591 assertions passed  405.69ms
  - Curr 64: 20,053 assertions passed  1.77ms
  - CamelCase: 11 assertions passed  163us
  - Bits: 4,774 assertions passed  233us
  - Ini files: 7,004 assertions passed  31.25ms
  - UTF8: 79,111 assertions passed  2.06s
  - Iso 8601 date and time: 32,007 assertions passed  6.32ms
  - Url decoding: 1,100 assertions passed  705us
  - Mime types: 20 assertions passed  137us
!  - TSynTable: 197 / 875 FAILED  8.13ms
  - TSynCache: 404 assertions passed  876us
  - TSynFilter: 1,005 assertions passed  4.10ms
  - TSynValidate: 677 assertions passed  869us
  - TSynLogFile: 42 assertions passed  1.13ms
  Total failed: 197 / 4,689,188  - Low level common FAILED  3.88s

 1.2. Low level types:
  - RTTI: 52 assertions passed  738us
  - Url encoding: 200 assertions passed  2.50ms
  - Encode decode JSON: 262,010 assertions passed  187.32ms
  - Mustache renderer: 137 assertions passed  2.86ms
!  - TDocVariant: 2 / 71,661 FAILED  202.18ms
!  - BSON: 8 / 20,000,184 FAILED  357.10ms
  Total failed: 10 / 20,334,244  - Low level types FAILED  755.57ms

 1.3. Big table:
  - TSynBigTable: 19,187 assertions passed  82.12ms
  - TSynBigTableString: 16,076 assertions passed  36.31ms
  - TSynBigTableMetaData: 384,060 assertions passed  2.06s
  - TSynBigTableRecord: 452,185 assertions passed  5.11s
  Total failed: 0 / 871,508  - Big table PASSED  7.29s

 1.4. Synopse PDF:
!  - TPdfDocument: 1 / 2 FAILED  4.52ms
  - TPdfDocumentGDI: 5 assertions passed  258.18ms
  Total failed: 1 / 7  - Synopse PDF FAILED  263.89ms

 1.5. Cryptographic routines:
  - Adler32: 1 assertion passed  748us
  - MD5: 1 assertion passed  682us
  - SHA1: 5 assertions passed  205us
  - SHA256: 5 assertions passed  1.10ms
  - AES256: 16,815 assertions passed  1.14s
  - RC4: 1 assertion passed  1.01ms
  - Base64: 11,994 assertions passed  220.97ms
  - CompressShaAes: 1,683 assertions passed  5.39ms
  Total failed: 0 / 30,505  - Cryptographic routines PASSED  1.37s

 1.6. Compression:
  - In memory compression: 12 assertions passed  437.91ms
  - GZIP format: 19 assertions passed  825.20ms
  - ZIP format: 36 assertions passed  1.48s
  - SynLZO: 3,006 assertions passed  156.37ms
  - SynLZ: 29,018 assertions passed  1.14s
  Total failed: 0 / 32,091  - Compression PASSED  4.04s


2. mORMot

 2.1. File based:
  - Database direct access: 10,138 assertions passed  326.92ms
  - Virtual table direct access: 12 assertions passed  2.60ms
  - TSQLTableJSON: 111,074 assertions passed  167.87ms
  - TSQLRestClientDB: 605,151 assertions passed  3.78s
  - Regexp function: 6,016 assertions passed  38.60ms
  Total failed: 0 / 732,391  - File based PASSED  4.32s

 2.2. File based memory map:
  - Database direct access: 10,136 assertions passed  340.42ms
  - Virtual table direct access: 12 assertions passed  3.09ms
  - TSQLTableJSON: 111,074 assertions passed  161.65ms
  - TSQLRestClientDB: 605,150 assertions passed  3.62s
  - Regexp function: 6,016 assertions passed  35.65ms
  Total failed: 0 / 732,388  - File based memory map PASSED  4.17s

 2.3. File based WAL:
  - Database direct access: 10,138 assertions passed  353.74ms
  - Virtual table direct access: 12 assertions passed  1.60ms
  - TSQLTableJSON: 111,074 assertions passed  165.78ms
  - TSQLRestClientDB: 605,151 assertions passed  3.55s
  - Regexp function: 6,016 assertions passed  33.82ms
  Total failed: 0 / 732,391  - File based WAL PASSED  4.11s

 2.4. Memory based:
  - Database direct access: 10,136 assertions passed  328.75ms
  - Virtual table direct access: 12 assertions passed  2.35ms
  - TSQLTableJSON: 111,074 assertions passed  158.81ms
  - TSQLRestClientDB: 673,447 assertions passed  4.15s
  - Regexp function: 6,016 assertions passed  35.30ms
  - RTree: 140,000 assertions passed  1.43s
  Total failed: 0 / 940,685  - Memory based PASSED  6.11s

 2.5. Basic classes:
!  - TSQLRecord: 11 / 65 FAILED  3.03ms
  - TSQLRecordSigned: 200 assertions passed  5.65ms
  - TSQLModel: 3 assertions passed  6.75ms
  Total failed: 11 / 268  - Basic classes FAILED  17.89ms

 2.6. Client server access:
  - TSQLHttpServer: 2 assertions passed  5.29ms
     using HTTP API 2.0
  - TSQLHttpClient: 3 assertions passed  33.82ms
  - HTTP client keep alive: 3,087 assertions passed  520.89ms
     4818 B, first 6.76ms, done 481.97ms i.e. 2074/s, aver. 481us, 9.7 MB/s
  - HTTP client multi connect: 3,087 assertions passed  449.58ms
     4818 B, first 586us, done 427.30ms i.e. 2340/s, aver. 427us, 10.9 MB/s
  - HTTP client encrypted: 3,087 assertions passed  597.42ms
     4818 B, first 758us, done 567.31ms i.e. 1762/s, aver. 567us, 8.2 MB/s
  - Named pipe access: 3,089 assertions passed  594.54ms
     4818 B, first 256.45ms, done 122.51ms i.e. 8162/s, aver. 122us, 38.1 MB/s
  - Local window messages: 3,088 assertions passed  130.93ms
     4818 B, first 374us, done 105.94ms i.e. 9438/s, aver. 105us, 44.1 MB/s
  - Direct in process access: 3,056 assertions passed  60.95ms
     4818 B, first 57us, done 53.45ms i.e. 18709/s, aver. 53us, 87.4 MB/s
  - HTTP several DB servers: 9,604 assertions passed  1.34s
     4818 B, first 722us, done 398.60ms i.e. 2508/s, aver. 398us, 11.7 MB/s
     4818 B, first 744us, done 387.63ms i.e. 2579/s, aver. 387us, 12.0 MB/s
     4818 B, first 703us, done 398.46ms i.e. 2509/s, aver. 398us, 11.7 MB/s
  Total failed: 0 / 28,103  - Client server access PASSED  3.74s

 2.7. Service oriented architecture:
  - Weak interfaces: 56 assertions passed  165us
  - Service initialization: 200 assertions passed  3.00ms
  - Direct call: 577,083 assertions passed  41.30ms
  - Server side: 577,102 assertions passed  48.43ms
  - Client side REST: 577,107 assertions passed  668.60ms
  - Client side REST result as object: 577,101 assertions passed  720.64ms
  - Client side REST locked: 577,104 assertions passed  652.80ms
  - Client side REST synchronized: 577,104 assertions passed  1.26s
  - Client side REST background thread: 577,104 assertions passed  1.23s
  - Client side REST weak authentication: 577,101 assertions passed  666.66ms
  - Client side REST custom record layout: 577,101 assertions passed  751.06ms
  - Client side JSONRPC: 577,101 assertions passed  922.35ms
  - Test over HTTP: 9,524 assertions passed  828.74ms
  - Security: 135 assertions passed  1.61ms
  - Mocks and stubs: 30,031 assertions passed  66.32ms
  Total failed: 0 / 5,810,954  - Service oriented architecture PASSED  7.87s

 2.8. External database:
  - External records: 2 assertions passed  10.84ms
  - Auto adapt SQL: 448 assertions passed  39.38ms
  - Crypted database: 253,275 assertions passed  333.95ms
  - External via REST: 168,343 assertions passed  1.37s
  - External via virtual table: 168,343 assertions passed  3.16s
  - JET database: 7,007 assertions passed  1.12s
  Total failed: 0 / 597,418  - External database PASSED  6.04s

 2.9. Multi thread process:
  - Create thread pool: 1 assertion passed  3.41ms
  - TSQLRestServerDB: 4,822 assertions passed  116.61ms
     1=28508/s  2=25263/s  5=18317/s  10=20180/s  30=20247/s  50=20784/s
  - TSQLRestClientDB: 4,822 assertions passed  146.12ms
     1=19158/s  2=21143/s  5=10299/s  10=20214/s  30=17799/s  50=21637/s
  - TSQLRestClientURINamedPipe: 2,412 assertions passed  1.64s
     1=1054/s  2=1243/s  5=542/s
  - TSQLRestClientURIMessage: 3,222 assertions passed  264.77ms
     1=4928/s  2=10105/s  5=6160/s  10=5515/s
  - TSQLHttpClientWinHTTP_HTTPAPI: 4,810 assertions passed  554.67ms
     1=2302/s  2=4772/s  5=5210/s  10=5817/s  30=6940/s  50=5390/s
  - TSQLHttpClientWinSock_WinSock: 4,820 assertions passed  345.59ms
     1=8622/s  2=8358/s  5=8031/s  10=6735/s  30=8323/s  50=5070/s
  - Locked: 4,822 assertions passed  152.36ms
     1=26056/s  2=16786/s  5=23688/s  10=21265/s  30=14971/s  50=9021/s
  - Unlocked: 4,822 assertions passed  174.67ms
     1=16175/s  2=17604/s  5=28783/s  10=16806/s  30=12199/s  50=8118/s
  - Background thread: 4,821 assertions passed  462.48ms
     1=11321/s  2=21219/s  5=16081/s  10=12104/s  30=6351/s  50=1452/s
  - Main thread: 4,822 assertions passed  264.48ms
     1=9261/s  2=8375/s  5=8714/s  10=11824/s  30=14462/s  50=6866/s
  Total failed: 0 / 44,196  - Multi thread process PASSED  4.14s


Synopse framework used: 1.18
SQlite3 engine used: 3.8.4.3
Generated with: Delphi XE compiler

Time elapsed for all tests: 58.20s
Tests performed at 2014/4/29 9:55:03

Total assertions failed for all test suits:  219 / 35,576,337
! Some tests FAILED: please correct the code.

Delphi XE6 release

   Synopse mORMot Framework Automated tests
  ------------------------------------------


1. Synopse libraries

 1.1. Low level common:
  - System copy record: 22 assertions passed  241us
  - TRawUTF8List: 70,005 assertions passed  116.29ms
  - TDynArray: 1,027,702 assertions passed  205.29ms
  - TDynArrayHashed: 1,200,629 assertions passed  167.71ms
  - TObjectListHashed: 999,907 assertions passed  549.59ms
  - TObjectDynArrayWrapper: 167,501 assertions passed  33.37ms
  - Fast string compare: 7 assertions passed  294us
  - IdemPropName: 30 assertions passed  234us
  - Url encoding: 105 assertions passed  1.03ms
  - GUID: 9,005 assertions passed  7.03ms
  - IsMatch: 599 assertions passed  269us
  - Soundex: 35 assertions passed  143us
  - Numerical conversions: 1,063,059 assertions passed  510.88ms
  - Curr 64: 20,053 assertions passed  1.40ms
  - CamelCase: 11 assertions passed  110us
  - Bits: 4,774 assertions passed  133us
  - Ini files: 7,004 assertions passed  34.16ms
  - UTF8: 79,111 assertions passed  1.25s
  - Iso 8601 date and time: 32,007 assertions passed  5.17ms
  - Url decoding: 1,100 assertions passed  784us
  - Mime types: 20 assertions passed  207us
!  - TSynTable: 200 / 875 FAILED  9.09ms
  - TSynCache: 404 assertions passed  877us
  - TSynFilter: 1,005 assertions passed  9.35ms
  - TSynValidate: 677 assertions passed  997us
  - TSynLogFile: 42 assertions passed  754us
  Total failed: 200 / 4,685,689  - Low level common FAILED  2.91s

 1.2. Low level types:
  - RTTI: 52 assertions passed  3.86ms
  - Url encoding: 200 assertions passed  783us
  - Encode decode JSON: 262,010 assertions passed  136.71ms
  - Mustache renderer: 137 assertions passed  2.07ms
  - TDocVariant: 71,661 assertions passed  216.75ms
!  - BSON: 8 / 20,000,184 FAILED  223.39ms
  Total failed: 8 / 20,334,244  - Low level types FAILED  587.45ms

 1.3. Big table:
  - TSynBigTable: 19,216 assertions passed  67.58ms
  - TSynBigTableString: 16,177 assertions passed  22.47ms
  - TSynBigTableMetaData: 384,060 assertions passed  1.06s
  - TSynBigTableRecord: 452,185 assertions passed  2.50s
  Total failed: 0 / 871,638  - Big table PASSED  3.66s

 1.4. Synopse PDF:
!  - TPdfDocument: 1 / 2 FAILED  4.71ms
  - TPdfDocumentGDI: 5 assertions passed  141.06ms
  Total failed: 1 / 7  - Synopse PDF FAILED  146.75ms

 1.5. Cryptographic routines:
  - Adler32: 1 assertion passed  648us
  - MD5: 1 assertion passed  104us
  - SHA1: 5 assertions passed  114us
  - SHA256: 5 assertions passed  648us
  - AES256: 16,815 assertions passed  1.08s
  - RC4: 1 assertion passed  1.13ms
  - Base64: 11,994 assertions passed  156.61ms
  - CompressShaAes: 1,683 assertions passed  4.41ms
  Total failed: 0 / 30,505  - Cryptographic routines PASSED  1.25s

 1.6. Compression:
  - In memory compression: 12 assertions passed  464.13ms
  - GZIP format: 19 assertions passed  956.83ms
  - ZIP format: 36 assertions passed  1.69s
  - SynLZO: 3,006 assertions passed  137.41ms
  - SynLZ: 29,018 assertions passed  861.38ms
  Total failed: 0 / 32,091  - Compression PASSED  4.12s


2. mORMot

 2.1. File based:
  - Database direct access: 10,138 assertions passed  313.02ms
  - Virtual table direct access: 12 assertions passed  2.53ms
  - TSQLTableJSON: 111,074 assertions passed  110.57ms
  - TSQLRestClientDB: 605,151 assertions passed  3.26s
  - Regexp function: 6,016 assertions passed  40.57ms
  Total failed: 0 / 732,391  - File based PASSED  3.73s

 2.2. File based memory map:
  - Database direct access: 10,136 assertions passed  335.15ms
  - Virtual table direct access: 12 assertions passed  1.87ms
  - TSQLTableJSON: 111,074 assertions passed  109.27ms
  - TSQLRestClientDB: 605,150 assertions passed  3.14s
  - Regexp function: 6,016 assertions passed  33.67ms
  Total failed: 0 / 732,388  - File based memory map PASSED  3.63s

 2.3. File based WAL:
  - Database direct access: 10,138 assertions passed  354.29ms
  - Virtual table direct access: 12 assertions passed  1.68ms
  - TSQLTableJSON: 111,074 assertions passed  109.03ms
  - TSQLRestClientDB: 605,151 assertions passed  3.27s
  - Regexp function: 6,016 assertions passed  32.96ms
  Total failed: 0 / 732,391  - File based WAL PASSED  3.77s

 2.4. Memory based:
  - Database direct access: 10,136 assertions passed  303.13ms
  - Virtual table direct access: 12 assertions passed  1.30ms
  - TSQLTableJSON: 111,074 assertions passed  100.84ms
  - TSQLRestClientDB: 673,447 assertions passed  3.96s
  - Regexp function: 6,016 assertions passed  55.47ms
  - RTree: 140,000 assertions passed  1.30s
  Total failed: 0 / 940,685  - Memory based PASSED  5.73s

 2.5. Basic classes:
  - TSQLRecord: 65 assertions passed  1.10ms
  - TSQLRecordSigned: 200 assertions passed  5.07ms
  - TSQLModel: 3 assertions passed  17.55ms
  Total failed: 0 / 268  - Basic classes PASSED  26.07ms

 2.6. Client server access:
  - TSQLHttpServer: 2 assertions passed  4.39ms
     using HTTP API 2.0
  - TSQLHttpClient: 3 assertions passed  29.16ms
  - HTTP client keep alive: 3,087 assertions passed  448.02ms
     4818 B, first 6.67ms, done 417.23ms i.e. 2396/s, aver. 417us, 11.2 MB/s
  - HTTP client multi connect: 3,087 assertions passed  381.44ms
     4818 B, first 1.90ms, done 351.20ms i.e. 2847/s, aver. 351us, 13.3 MB/s
  - HTTP client encrypted: 3,087 assertions passed  482.64ms
     4818 B, first 745us, done 459.15ms i.e. 2177/s, aver. 459us, 10.1 MB/s
  - Named pipe access: 3,089 assertions passed  595.13ms
     4818 B, first 256.61ms, done 117.76ms i.e. 8491/s, aver. 117us, 39.7 MB/s
  - Local window messages: 3,088 assertions passed  112.02ms
     4818 B, first 266us, done 94.18ms i.e. 10617/s, aver. 94us, 49.6 MB/s
  - Direct in process access: 3,056 assertions passed  37.53ms
     4818 B, first 37us, done 30.60ms i.e. 32670/s, aver. 30us, 152.7 MB/s
  - HTTP several DB servers: 9,604 assertions passed  1.46s
     4818 B, first 695us, done 424.69ms i.e. 2354/s, aver. 424us, 11.0 MB/s
     4818 B, first 740us, done 416.07ms i.e. 2403/s, aver. 416us, 11.2 MB/s
     4818 B, first 739us, done 449.91ms i.e. 2222/s, aver. 449us, 10.3 MB/s
  Total failed: 0 / 28,103  - Client server access PASSED  3.56s

 2.7. Service oriented architecture:
  - Weak interfaces: 56 assertions passed  546us
  - Service initialization: 200 assertions passed  2.65ms
  - Direct call: 577,083 assertions passed  33.09ms
  - Server side: 577,102 assertions passed  42.37ms
  - Client side REST: 577,107 assertions passed  508.39ms
  - Client side REST result as object: 577,101 assertions passed  514.09ms
  - Client side REST locked: 577,104 assertions passed  495.11ms
  - Client side REST synchronized: 577,104 assertions passed  1.20s
  - Client side REST background thread: 577,104 assertions passed  1.06s
  - Client side REST weak authentication: 577,101 assertions passed  466.62ms
  - Client side REST custom record layout: 577,101 assertions passed  500.51ms
  - Client side JSONRPC: 577,101 assertions passed  544.11ms
  - Test over HTTP: 9,524 assertions passed  814.27ms
  - Security: 135 assertions passed  3.92ms
  - Mocks and stubs: 30,031 assertions passed  61.26ms
  Total failed: 0 / 5,810,954  - Service oriented architecture PASSED  6.26s

 2.8. External database:
  - External records: 2 assertions passed  670us
  - Auto adapt SQL: 448 assertions passed  35.55ms
  - Crypted database: 253,275 assertions passed  278.45ms
  - External via REST: 168,343 assertions passed  1.29s
  - External via virtual table: 168,343 assertions passed  2.96s
  - JET database: 7,007 assertions passed  1.12s
  Total failed: 0 / 597,418  - External database PASSED  5.69s

 2.9. Multi thread process:
  - Create thread pool: 1 assertion passed  3.93ms
  - TSQLRestServerDB: 4,822 assertions passed  92.30ms
     1=29418/s  2=26418/s  5=27047/s  10=26996/s  30=29076/s  50=25834/s
  - TSQLRestClientDB: 4,822 assertions passed  153.67ms
     1=27647/s  2=21180/s  5=16107/s  10=19250/s  30=15521/s  50=9195/s
  - TSQLRestClientURINamedPipe: 2,411 assertions passed  1.50s
     1=1182/s  2=1108/s  5=666/s
  - TSQLRestClientURIMessage: 3,222 assertions passed  264.42ms
     1=4688/s  2=9997/s  5=8107/s  10=5087/s
  - TSQLHttpClientWinHTTP_HTTPAPI: 4,795 assertions passed  520.02ms
     1=3029/s  2=4455/s  5=5496/s  10=4833/s  30=6375/s  50=5599/s
  - TSQLHttpClientWinSock_WinSock: 4,819 assertions passed  423.05ms
     1=8550/s  2=6860/s  5=7637/s  10=7704/s  30=6947/s  50=2773/s
  - Locked: 4,822 assertions passed  179.75ms
     1=25992/s  2=18309/s  5=14345/s  10=12970/s  30=14398/s  50=7920/s
  - Unlocked: 4,822 assertions passed  171.18ms
     1=23540/s  2=16152/s  5=9330/s  10=13961/s  30=16201/s  50=14719/s
  - Background thread: 4,822 assertions passed  585.05ms
     1=22026/s  2=14927/s  5=11818/s  10=7876/s  30=2355/s  50=1452/s
  - Main thread: 4,822 assertions passed  249.12ms
     1=9653/s  2=5074/s  5=9568/s  10=20360/s  30=10879/s  50=16382/s
  Total failed: 0 / 44,180  - Multi thread process PASSED  4.16s


Synopse framework used: 1.18
SQlite3 engine used: 3.8.4.3
Generated with: Delphi XE6 compiler

Time elapsed for all tests: 49.32s
Tests performed at 2014/4/29 9:58:03

Total assertions failed for all test suits:  209 / 35,572,952
! Some tests FAILED: please correct the code.

#290 Re: mORMot 1 » Newbie questions of using TDynArray. » 2014-04-28 20:14:07

Thank you very much for your knowledgeable comments !

#291 Re: mORMot 1 » Newbie questions of using TDynArray. » 2014-04-28 12:14:25

Could you help to comment on another two questions of mine ?

1.
On Page 87 of Doc v1.18, "4.3.3 Capacity handling via an external Count", it is mentioned that "That is, whether you call Add or Delete methods, an internal call to SetLength(DynArrayVariable) is performed.". I am wondering, does the dynamic array grow by 1 or exponentially every time ?

2.
Your unitary tests are not contained in the "nightly" zip file. I wonder where to download them ? (For example, 4.3.5 on Page 87 mentions TTestLowLevelCommon where one could learn how to use TDynArray/TDynArrayHashed.) (Found in "SynSelfTests.pas". big_smile)

#292 Re: mORMot 1 » Newbie questions of using TDynArray. » 2014-04-25 09:14:30

Thank you for your helpful comments very much !

#293 mORMot 1 » Newbie questions of using TDynArray. » 2014-04-24 17:11:10

ComingNine
Replies: 5

I want to learn your great mORMot framework. Could you help to comment on the three questions below ?

procedure TForm1.FormCreate(Sender: TObject);
type
  TGroup = array of Integer;
var
  Group: TGroup;
  GroupA: TDynArray;
  I, V: Integer;
  Test: RawByteString;
begin
  GroupA.Init(TypeInfo(TGroup),Group);
  for I := 0 to 1000 do
  begin
    //GroupA.Add(I); // Question 1: Why "I" is not used directly ? (Page 85 of doc v1.18 says "need argument passed as a const variable". However, I do not understand what bad effects will come otherwise.) 

    V := I ;
    GroupA.Add(V); // Question 2: TDynArray does not have type-check ? It seems anything can be added here, which is not alerting enough ?
  end;

  Test := GroupA.SaveTo;
  GroupA.Clear;
  //GroupA.LoadFrom(Test);  // Question 3: This line (from Page 86) does not compile ? Should one hard-case as below ?
  GroupA.LoadFrom(PAnsiChar(Test));

  Caption := FloatToStrF(Group[50], ffFixed, 12, 6);
end;

#294 Re: Delphi » I'm still preferring Delphi 7 IDE » 2010-08-03 22:53:49

Thank you very much for your comments!

I had tried the "THashedStringList" together with a separate TObject list/array to mimic a Dictionary/HashMap/HashTable before, but I didn't know the "best practice" to do it in Delphi 7. Besides, there have been discussions and THashedStringList was said to be low efficient generally (i.e., a simple linear search for bucket collisions is used internally, which is a bad choice in general and an especially bad choice for a fixed small bucket count. See https://forums.embarcadero.com/message. … geID=86963). In that post, DIContainers has been recommended, but it doesn't provide Kylix compatibility.

Regarding IniFiles.TStringHash, because the key is string type and the value is integer type, I would think its usage is the same as THashedStringList. Could you help to comment whether it has the same problem of bucket collision search as THashedStringList?

#295 Re: Delphi » I'm still preferring Delphi 7 IDE » 2010-08-03 14:31:02

You mentioned that coding in Delphi 7 manner helps to migrate to Free Pascal and so forth. However, Delphi 7 doesn't provide TDictionary/HashMap/HashTable, which is convenient sometimes.

Could you help to comment on this issue?

#296 Re: Delphi » Cross Kylix updated » 2010-07-30 15:48:27

Dear Arnaud, thank you very much for your time! I don't know how to send bug requests; I will then send the link of this page to him via email.

Furthermore, I have sent you an email regarding another question to "freelance at synopse dot info" (with a zipped file attachment as large as 1.5 MB). Thank you very much again!

#297 Re: Delphi » Cross Kylix updated » 2010-07-30 14:02:50

Thank you very much for your time and kindness!!

1.
I have tried the following steps several times in clean virtual machines (clean means fresh-installed Windows Xp Sp2, without any other programs):

(1) Install Delphi 7
(2) Install CrossKylix + Kylix files
(3) Install CrossKylix ideplugin into Delphi 7 IDE; as prompted by the plugin itself and mentioned kindly by you, I have to filled in the path of crosskylix installation (, and the "unit+include+object" will be filled by itself). 
(4) Try to use "Build with Kylix"
(5) Reboot the virtual machine, try to use "Build with Kylix"

The same problem occurred as in my workstation and laptop: in step (5), "Build with Kylix" will not respond.

2.
HOWEVER, I accidentally found that, after each rebooting, if I ran ckdcc.exe once, by double clicking for instance, and THEN open Delphi 7, the "Build with Kylix" will work!

I tried this workaround on my workstation and laptop (i.e., run ckdcc.exe once before opening Delphi 7 IDE) and it is also valid. I didn't know why, though.

#298 Re: Delphi » Cross Kylix updated » 2010-07-30 08:56:19

Thank you very much for your prompt suggestions!

1. I didn't install or uninstall any experts plugin.

2, 4. I installed once in my workstation (using default options as in #4 post), and now in my laptop. Thus, I didn't need to uninstall.

3. Yes. I mean, after I just installed Delphi 7, CrossKylix and kylix files, I indeed can use "Build with Kylix". After restarting the computer, the menuitem will not respond my click (error log as in #4 post). The command line compiler works however.

I will then try carefully as you advised in clean virtual machines (because the state of the virtual machine can be saved and restored quite easily), and report what happens later.

#299 Re: Delphi » Cross Kylix updated » 2010-07-30 07:35:40

Thank you for your prompt help very much!

I am sorry that:

  The information at #4 post is when I installed CrossKylix at its default directory.

  After that, I tried to install CrossKylix without space characters under C:\CrossKylix, which is the information at #5 post.

#300 Re: Delphi » Cross Kylix updated » 2010-07-29 20:07:41

I forgot to mention that:

1.
Despite the fact that the "Build with Kylix" menuitem in the Delphi 7 IDE will not respond after I click it, with the .conf file generated by CrossKylix, a manual call like:

C:\TestProject1> "C:\Program Files\CrossKylix\ckdcc.exe" Project1.dpr

still works.

2.
When I tried to install CrossKylix into another directory without space characters in the path, like C:\crosskylix, the same problem exists, i.e. :

The "Build with Kylix" menuitem in the Delphi 7 IDE will not respond after I click it.

With the .conf file generated by CrossKylix, a manual call like:

C:\TestProject1> C:\CrossKylix\ckdcc.exe Project1.dpr

works.

Could you help me with this problem? Thank you very much!!

Board footer

Powered by FluxBB