#1 Re: mORMot Framework » Logging 1 Line sllError takes 15 Seconds » 2022-03-17 09:47:50

ab wrote:

Perhaps the problem is that the .map file is recreated each time.

Is the .map file generated by Delphi for your project?
Is the .mab file properly generated by TDebugFile ?

Could you check if it is not TDebugFile.Create which is called by TDebugFile.Log on line 5670 of mormot.core.log which makes the delay.

Edit: Please try https://github.com/synopse/mORMot2/commit/99c7db03

Hi Arnaud, i only have the EXE on the Test Machine, no map / mab file.
After starting the App i can not find a mab/map file in the folder.

#2 Re: mORMot Framework » Logging 1 Line sllError takes 15 Seconds » 2022-03-17 09:19:22

Hi Arnaud,

i testet the latest commit.
Now OnlyApi is as fast as expected
OnlyManual does take the same time as before.

#3 Re: mORMot Framework » Logging 1 Line sllError takes 15 Seconds » 2022-03-15 19:21:41

As you can see Trace=0 works as expected. The Other have Delays.
The 15s Delay is at another Place in the Program where the Stack / Memory Usage is much bigger

#4 Re: mORMot Framework » Logging 1 Line sllError takes 15 Seconds » 2022-03-15 19:18:29

Here my Results, made 4 Tests

1. Default Settings

15.03.2022 20:04:57.688	Trace	1	 Program wurde gestartet
15.03.2022 20:04:57.688	Error	1	 Error1  
15.03.2022 20:04:59.608	Error	1	 Error2  
15.03.2022 20:05:00.976	Error	1	 Error3  
15.03.2022 20:05:03.656	Enter	1	 After Error3

2. OnlyApi

15.03.2022 20:05:45.944	Trace	1	 Program wurde gestartet
15.03.2022 20:05:45.944	Error	1	 Error1  
15.03.2022 20:05:47.784	Error	1	 Error2  
15.03.2022 20:05:48.992	Error	1	 Error3  
15.03.2022 20:05:51.240	Enter	1	 After Error3

3. OnlyManual

15.03.2022 20:06:18.304	Trace	1	 Program wurde gestartet
15.03.2022 20:06:18.304	Error	1	 Error1  
15.03.2022 20:06:19.784	Error	1	 Error2  
15.03.2022 20:06:21.112	Error	1	 Error3  
15.03.2022 20:06:23.288	Enter	1	 After Error3

4. StackTraceLevel=0

15.03.2022 20:09:37.144	Trace	1	 Program wurde gestartet
15.03.2022 20:09:37.144	Error	1	 Error1
15.03.2022 20:09:37.144	Error	1	 Error2
15.03.2022 20:09:37.144	Error	1	 Error3
15.03.2022 20:09:38.592	Enter	1	 After Error3

Example Code

TSynLog.Family.Level := LOG_VERBOSE;
  if AppHasParam('StackTraceLevel0') then
TSynLog.Family.StackTraceLevel := 0;
  if SameText(GetAppParamValue('StackTraceUse'), 'OnlyApi') then
TSynLog.Family.StackTraceUse := stOnlyApi;
  if SameText(GetAppParamValue('StackTraceUse'), 'OnlyManual') then
TSynLog.Family.StackTraceUse := stOnlyManual;
TSynLog.Family.HighResolutionTimeStamp := true;
TSynLog.Family.LocalTimeStamp := true;
TSynLog.Family.FileExistsAction := acAppend;
TSynLog.Family.PerThreadLog := ptIdentifiedInOnFile;
TSynLog.Family.RotateFileCount := 100;    // ca. 3 Monate
TSynLog.Family.RotateFileSizeKB := 5000 * 1024;
TSynLog.Family.RotateFileDailyAtHour := 23;
TSynLog.Family.IncludeComputerNameInFileName := true;
TSynLog.Family.DestinationPath := TPath.Combine(ExtractFilePath(Application.ExeName), 'Logs');
TDirectory.CreateDirectory(TSynLog.Family.DestinationPath);
TSynLog.Add.Log(sllTrace, 'Program wurde gestartet');
TSynLog.Add.Log(sllError, 'Error1');
TSynLog.Add.Log(sllError, 'Error2');
TSynLog.Add.Log(sllError, 'Error3');
---
After Error 3 - Later in code

#6 mORMot Framework » Logging 1 Line sllError takes 15 Seconds » 2022-03-15 10:37:17

itSDS
Replies: 8

Hi Arnaud,

Logging on a Standard Windows 11 Computer took a long time (much longer than on my develop maschine)
After looking in the Log i found the sllError Line takes 15 second.

The only Reason i found could be the StackTrace - Routines
I set StackTraceLevel to 0 an the delay disappeared (It disabled the StackTrace Option)
as i do not need the StackTrace at this log its not important for me.

But do you have an Idea what i have to do to avoid the delay on active StackTrace ? Is there a Windows - Option ? Does the Windows User afford som special rights ?

#7 Re: mORMot Framework » C0000005 in mormot.soa.core 64Bit » 2022-02-10 11:47:54

I wrote a derived Class from TInterfaceFactory which does not evaluate the Methods...

#9 mORMot Framework » C0000005 in mormot.soa.core 64Bit » 2022-02-10 11:31:29

itSDS
Replies: 4

Hi Arnaud,

today i got an exception in this method:
My Bugfix is here: can you pls add it to repo

function TServiceContainer.AddServiceInternal(aService: TServiceFactory): PtrInt;
var
  MethodIndex: integer;

  procedure AddOne(const aInterfaceDotMethodName: RawUtf8);
  var
    p: PServiceContainerInterfaceMethod;
  begin
    p := fInterfaceMethods.AddUniqueName(aInterfaceDotMethodName);
    p^.InterfaceService := aService;
    p^.InterfaceMethodIndex := MethodIndex;
    inc(MethodIndex);
  end;

var
  aUri: RawUtf8;
  internal: TServiceInternalMethod;
  m: PtrInt;
begin
  if (self = nil) or
     (aService = nil) then
    raise EServiceException.CreateUtf8(
      '%.AddServiceInternal(%)', [self, aService]);
  // add TServiceFactory to the internal list
  if ExpectMangledUri then
    aUri := aService.fInterfaceMangledUri
  else
    aUri := aService.fInterfaceUri;
  PServiceContainerInterface(fInterfaces.AddUniqueName(aUri, @result))^.
    Service := aService;
  // add associated methods - first SERVICE_PSEUDO_METHOD[], then from interface
  aUri := aUri + '.';
  MethodIndex := 0;
  for internal := Low(internal) to High(internal) do
    AddOne(aUri + SERVICE_PSEUDO_METHOD[internal]);
// BUGFIX here

  for m := 0 to (integer(aService.fInterface.MethodsCount)-1) do    /// <<<---- Wrong Subtraction MethodsCount is Cardinal and mc-1 is also cardinal.
    AddOne(aUri + aService.fInterface.Methods[m].Uri);


end;

#10 Re: mORMot Framework » mORMot2 Wrapper generation broken » 2022-01-27 14:50:13

Today I had another problem in the Wrapper Generator.
The generated ContractID is different between mORMot2 and mORMot.
However, after I inserted the one generated by mORMot, the data transfer still works.

#11 Re: mORMot Framework » mORMot2 Wrapper generation broken » 2022-01-25 14:01:07

Hi Arnaud,

i like to move completely to mORMot2. But this feature is a show stopper atm.
I tested and debugged the Problem now for hours but can not solve it.
I just have some new hints and things i found out.

I use the same Sample as above. Slightly enhanced. if you like i can send you the code or show the Problem by Teamviewer.
i Compared the mORMot and mORMot2 by debugging TWrapperContent. And added some TSynLog Stuff to dig in the deep.

The Following Errors are in mORMot2:
1. Nested Records are expanded the reason is in the used new rtti props in ContextOneProperty function

for mORMot Version prop.PropertyType is ptCustom and for mORMot2 prop.Value.Parser is ptRecord
(generally it is a ptRecord but i do not know where mORMot generates the ptCustom where mORMot2 has a ptRecord.)
this adds additional nestedRecord in the structure. which is wrong.

2. Second BUG is a DynArray of (Record or simple Type e.g. String)
in mORMot the Code is correct
in M2 You internally map ptDynArray to Blob which results in wrong code. The Wrong Conversion occurs for example in ContextFromRTTI in

typ := TYPES_ORM[GetOrmFieldType(rtti.Info)];

Hopefully you have an idea to fix the Wrapper Generator with this info

#12 mORMot Framework » External DB function Problem (mormot2) » 2021-12-01 13:27:01

itSDS
Replies: 1

Hi Arnaud

atm im struggling with an external Oracle DB - I used both ConnectionProperties:  TSqlDBOracleConnectionProperties and TSQLDBUniDACConnectionProperties (for Oracle)

i use code like this:

var LVariant := RestModel.RetrieveDocVariantArray(TSQLEOR_SomeRecord,'', 
'trunc(DateTimeField) = trunc(sysdate)' ,  // <-- SQLite Error Oracle SQL Function sysdate unknown
 [] , 
'ID, DateTimeField, Field1, Field2, Field3,')

Example for other Oracle functions not working:

to_char( datetimefield, 'YYYY-MM-DD' ) = '2021-12-01'  // SQLite Error: to_char unkown
trunc( datetimefield ) = to_date('2021-12-01', 'YYYY-MM-DD')");  // SQLite Error: to_date unknown

trunc is also unkown smile

Is there a possibilty to let SQLite know the functions or to get the Query run
Why does SQLite have to know the functions ?

Best Regards

#13 Re: mORMot Framework » BUGFix for mORMot.pas » 2021-10-06 15:39:48

thank you - yes i used a piece of code with mORMot2 and then with mORMot and under mORMot my Objekt was freed in Support...

#14 mORMot Framework » BUGFix for mORMot.pas » 2021-10-06 11:28:59

itSDS
Replies: 3

Hi Arnaud. i tried to upload this patch to github. But my credentials are rejected

diff --git a/SQLite3/mORMot.pas b/SQLite3/mORMot.pas
index 5b692f78..30d00b67 100644
--- a/SQLite3/mORMot.pas
+++ b/SQLite3/mORMot.pas
@@ -58447,10 +58447,11 @@ begin
   else
     result := fImplementationClass.Create;
   end;
+  inc(TInterfacedObjectHooked(result).FRefCount); // >0 to call Support() in event
   if Assigned(TSQLRestServer(Rest).OnServiceCreateInstance) then
     TSQLRestServer(Rest).OnServiceCreateInstance(self,result);
-  if AndIncreaseRefCount then
-    IInterface(result)._AddRef; // allow passing self to sub-methods
+  if not AndIncreaseRefCount then
+    dec(TInterfacedObjectHooked(result).FRefCount);
 end;
 
 procedure TServiceFactoryServer.OnLogRestExecuteMethod(Sender: TServiceMethodExecute;

#15 mORMot Framework » mORMOT 2 Exceptions in LogTrailer on sllError » 2021-08-31 10:21:50

itSDS
Replies: 1

Hi Arnaud

i found the following "bug" between DEBUG and RELEASE Version in mORMot2:

I get lot's of Exception (> 200) at this line of code:

mORMot.rest.client: 2460 (InternalLog('% % returned % (%) with message  %',  [method, url, Call.OutStatus, StatusMsg, fLastErrorMessage], sllError);)

only in RELEASE Mode - not in DEBUG Mode !

so it was a bit tricky to get the cause for the Exceptions.

The Source for the Exceptions is in mormot.core.log: AddStackTrace in LogTrailer (sllError is in fLevelStackTrace) around line 5416
your are ignoring the Exceptions but they are displayed in the LogFile - and on console Screen.

As WorkAround i added this piece of code to my "Log Initialisation Code"

{$if defined(RELEASE)}
    TSynLog.Family.LevelStackTrace := TSynLog.Family.LevelStackTrace - [sllError];
{$endif}

There are other Log Levels in LevelStackTrace wich may rise the same Exceptions
May be you have an Idea what's the Problem.
in mORMot the Problem does not exists - but i saw that you did a big rework in TSynLog

#17 Re: mORMot Framework » mORMot2 Oracle - Patch » 2021-07-13 17:56:03

k next time i try the correct way

#18 mORMot Framework » mORMot2 Oracle - Patch » 2021-07-13 17:37:40

itSDS
Replies: 2

Hi AB i use mORMot2 with Oracle and got error in GetFields.
Hier is my Patch for this

procedure TSqlDBUniDACConnectionProperties.GetFields(const aTableName: RawUtf8;
  out Fields: TSqlDBColumnDefineDynArray);
var
  meta: TDAMetaData;
  n: integer;
  F: TSqlDBColumnDefine;
  FA: TDynArray;
  hasSubType: boolean;
  Owner, Table: RawUtf8;
begin
  meta := (MainConnection as TSqlDBUniDACConnection).fDatabase.CreateMetaData;
  try
    FA.Init(TypeInfo(TSqlDBColumnDefineDynArray), Fields, @n);
    FA.Compare := SortDynArrayAnsiStringI; // FA.Find() case insensitive
    FillCharFast(F, sizeof(F), 0);
    meta.MetaDataKind := 'Columns';
    Split(aTableName, '.', Owner, Table);
    if Table = '' then
    begin
      Table := Owner;
      Owner := '';
    end;

// PATCH
    if (Owner = '') and
       (fDBMS <> dOracle) then
      Owner := MainConnection.Properties.DatabaseName; // itSDS
// PATCH

    if Owner <> '' then
      meta.Restrictions.Values['TABLE_SCHEMA'] := Utf8ToString(UpperCase(Owner))
    else
      meta.Restrictions.Values['SCOPE'] := 'LOCAL';
    meta.Restrictions.Values['TABLE_NAME'] := Utf8ToString(UpperCase(Table));
    meta.Open;
    hasSubType := meta.FindField('DATA_SUBTYPE') <> nil;
    while not meta.Eof do
    begin
      F.ColumnName := StringToUtf8(meta.FieldByName('COLUMN_NAME').AsString);
      F.ColumnTypeNative := StringToUtf8(meta.FieldByName('DATA_TYPE').AsString);
      if hasSubType then
        F.ColumnTypeNative := F.ColumnTypeNative +
          StringToUtf8(meta.FieldByName('DATA_SUBTYPE').AsString);
      F.ColumnLength := meta.FieldByName('DATA_LENGTH').AsInteger;
      F.ColumnScale := meta.FieldByName('DATA_SCALE').AsInteger;
      F.ColumnPrecision := meta.FieldByName('DATA_PRECISION').AsInteger;
      F.ColumnType := ColumnTypeNativeToDB(F.ColumnTypeNative, F.ColumnScale);
      if F.ColumnType = ftUnknown then
      begin
        // UniDAC metadata failed -> use SQL
        Fields := nil;
        inherited GetFields(aTableName, Fields);
        exit;
      end;
      FA.Add(F);
      meta.Next;
    end;
    Setlength(Fields, n);
    GetIndexesAndSetFieldsColumnIndexed(aTableName, Fields);
  finally
    meta.Free;
  end;
end;

#19 Re: mORMot Framework » Problem compiling mormot2 (E2251) » 2021-07-13 17:31:45

as Solution you should not overload the function and instead rename the second Function e.g to Utf8ToStringP

/// convert any UTF-8 encoded String into a generic VCL Text
// - it's prefered to use TLanguageFile.Utf8ToString() in mORMoti18n,
// which will handle full i18n of your application
// - it will work as is with Delphi 2009+ (direct unicode conversion)
// - under older version of Delphi (no unicode), it will use the
// current RTL codepage, as with WideString conversion (but without slow
// WideString usage)
function Utf8ToString(const Text: RawUtf8): string; // itSDS overload;
  {$ifdef HASINLINE}inline;{$endif}

/// convert any UTF-8 encoded String into a generic VCL Text
procedure Utf8ToStringP(const Text: RawUtf8; var result: string); // overload;
  {$ifdef HASINLINE}inline;{$endif}

what do you think

#20 Re: mORMot Framework » Problem compiling mormot2 (E2251) » 2021-07-13 17:26:25

i testet something:

there was a former Version of mormot.core.unicode.pas without generating the error:


/// convert any UTF-8 encoded String into a generic VCL Text
// - it's prefered to use TLanguageFile.Utf8ToString() in mORMoti18n,
// which will handle full i18n of your application
// - it will work as is with Delphi 2009+ (direct unicode conversion)
// - under older version of Delphi (no unicode), it will use the
// current RTL codepage, as with WideString conversion (but without slow
// WideString usage)
function Utf8ToString(const Text: RawUtf8): string;
  {$ifdef HASINLINE}inline;{$endif}

/// convert any UTF-8 encoded buffer into a generic VCL Text

#21 mORMot Framework » Problem compiling mormot2 (E2251) » 2021-07-13 17:25:25

itSDS
Replies: 4

There is a problem compiling 32Bit mORMot2 with Rad Studio 10.4.2

Errror: [dcc32 Fehler] xxxx.pas(196): E2251 Doppeldeutiger überladener Aufruf von 'UTF8ToString'
  System.pas(40375): Verwandte Methode: function UTF8ToString(const RawByteString): string;
  mormot.core.unicode.pas(3896): Verwandte Methode: function Utf8ToString(const UTF8String): string;

actual i put mormot.core.unicode.UTF8ToString( in my code but i have a lot of code with UTF8ToString
Is there a easy solution ?

System.pas is included in any unit or ?

#22 Re: mORMot Framework » mORMot2 Wrapper generation broken » 2021-06-14 13:47:07

hi Arnaud,

i had a look in the Source code and compared the Units "mORMotWrappers" and "mORMot.soa.codegen"

the TWrapperContext.ContextOneProperty seems to produce different structure.
But i have no idea how to fix it and where exactly the Problem is.
But in mORMot2 the nestedRecord Property is filled and in mORMot not for the same "TResultRec"

mORMot2:

{
	"typeWrapper": "wRecord",
	"typeSource": "TresultRec",
	"typeDelphi": "TresultRec",
	"typePascal": "TresultRec",
	"typeCS": "TresultRec",
	"typeJava": "TresultRec",
	"typeTS": "TresultRec",
	"typeSwagger": "TresultRec",
	"isRecord": true,
	"toVariant": "TresultRec2Variant",
	"fromVariant": "Variant2TresultRec",
	"propName": "resultRec",
	"fullPropName": "resultRec",
	"isSimple": null,
	"nestedRecord": {
		"nestedRecord": null,
		"fields": [
			{
				"typeWrapper": "wRawUtf8",
				"typeSource": "UTF8String",
				"typeDelphi": "RawUtf8",
				"typePascal": "String",
				"typeCS": "string",
				"typeJava": "String",
				"typeTS": "string",
				"typeSwagger": "{\"type\":\"string\"}",
				"propName": "erfolgJN",
				"fullPropName": "resultRec.erfolgJN",
				"nestedIdentation": "  ",
				"isSimple": true
			},
			{
				"typeWrapper": "wRawUtf8",
				"typeSource": "UTF8String",
				"typeDelphi": "RawUtf8",
				"typePascal": "String",
				"typeCS": "string",
				"typeJava": "String",
				"typeTS": "string",
				"typeSwagger": "{\"type\":\"string\"}",
				"propName": "fehlertext",
				"fullPropName": "resultRec.fehlertext",
				"nestedIdentation": "  ",
				"isSimple": true
			},
			{
				"typeWrapper": "wRawUtf8",
				"typeSource": "UTF8String",
				"typeDelphi": "RawUtf8",
				"typePascal": "String",
				"typeCS": "string",
				"typeJava": "String",
				"typeTS": "string",
				"typeSwagger": "{\"type\":\"string\"}",
				"propName": "hinweistext",
				"fullPropName": "resultRec.hinweistext",
				"nestedIdentation": "  ",
				"isSimple": true
			},
			{
				"typeWrapper": "wInteger",
				"typeSource": "Integer",
				"typeDelphi": "Integer",
				"typePascal": "Integer",
				"typeCS": "integer",
				"typeJava": "int",
				"typeTS": "number",
				"typeSwagger": "{\"type\":\"integer\"}",
				"propName": "resultcount",
				"fullPropName": "resultRec.resultcount",
				"nestedIdentation": "  ",
				"isSimple": true
			}
		]
	}
}

mORMot:

{
	"typeWrapper": "wRecord",
	"typeSource": "TresultRec",
	"typeDelphi": "TresultRec",
	"typePascal": "TresultRec",
	"typeCS": "TresultRec",
	"typeJava": "TresultRec",
	"typeTS": "TresultRec",
	"typeSwagger": "TresultRec",
	"isRecord": true,
	"toVariant": "TresultRec2Variant",
	"fromVariant": "Variant2TresultRec",
	"propName": "resultRec",
	"fullPropName": "resultRec",
	"isSimple": null
}

My be you have an idea how to fix it ?! It would be a great help. Ty

#23 Re: mORMot Framework » Problem: Cookie Handling in MVC Server is Case sensitive » 2021-05-05 11:24:34

Yes i like it smile

I applied the same Patch to mORMot V2. (mormot.rest.http.server.pas - Line 1010)

#24 Re: mORMot Framework » Problem: Cookie Handling in MVC Server is Case sensitive » 2021-05-05 08:47:54

Hi Arnaud, late feedback.
I testet it now and there is a little change i made to the Option:

In Line 927 of MORMotHttpServer i added a '/' slash in front of the serv.model.root, because else there's a kind of recursion generting wrong url (It repeats the serv.Model.Root serveral Times)

    if fRedirectServerRootUriForExactCase and (match=rmMatchWithCaseChange) then begin
      // force redirection to exact Server.Model.Root case sensitivity
      call.OutStatus := HTTP_TEMPORARYREDIRECT;
      call.OutHead := 'Location: /'+serv.Model.Root+                                /// <<<---- SLASH ADDED !
        copy(call.Url,length(serv.Model.Root)+1,maxInt);
    end else begin

#25 Re: mORMot Framework » mORMot2 Wrapper generation broken » 2021-04-10 11:05:06

@flydev the Problem is here with nestet Records and Array of...

Here is a link to download my sample

for mORMot2 define USE_MORMOTV2 in the options

https://cloud.diestelmann-it-gmbh.de/s/iqQ9zCbRwKMmW8M

#26 Re: mORMot Framework » mORMot2 Wrapper generation broken » 2021-04-09 09:47:35

i didn't dig in the deep - yet. No proposals atm.

#27 Re: mORMot Framework » mORMot2 Wrapper generation broken » 2021-04-08 14:51:24

If i generate the Wrapper with mORMot and the SOA Service with mORMot2 it works smile

#28 Re: mORMot Framework » mORMot2 Wrapper generation broken » 2021-04-08 14:37:03

Same Code with mORMot

unit mORMotClient;

{
  WARNING:
    This unit has been generated by a mORMot 1.18.6262 server.
    Any manual modification of this file may be lost after regeneration.

  Synopse mORMot framework. Copyright (C) 2021 Arnaud Bouchez
    Synopse Informatique - http://synopse.info

  This unit is released under a MPL/GPL/LGPL tri-license,
  and therefore may be freely included in any application.

  This unit would work on Delphi 6 and later, under all supported platforms
  (including MacOSX, and NextGen iPhone/iPad), and the Free Pascal Compiler.
}

interface

uses
  SynCrossPlatformJSON,
  SynCrossPlatformSpecific,
  SynCrossPlatformREST;
  

type // define some enumeration types, used below
  TPeopleSexe = (sFemale, sMale);
  TRecordEnum = (reOne, reTwo, reLast);

type // define some record types, used as properties below
  TresultRec = record
    erfolgJN: String;
    fehlertext: String;
    hinweistext: String;
  end;

  TTestCustomJSONArraySimpleArray = record
    F: String;
    F1: TresultRec;
    G: array of String;
    H: record
      H1: Integer;
      H2: String;
      H3: record
        H3a: Boolean;
        H3b: TSQLRawBlob;
      end;
    end;
    I: TDateTime;
    J: array of record
      J1: Byte;
      J2: TGUID;
      J3: TRecordEnum;
    end;
  end;

  TResultRecord = record
    resultRec: record
      erfolgJN: String;
      fehlertext: String;
      hinweistext: String;
    end;
    FResult1: String;
    FResult2: String;
    FResult3: String;
    FResult4: String;
  end;

  TSimpleRecord = record
    A: Integer;
    B: Integer;
    C: String;
  end;

#29 Re: mORMot Framework » mORMot2 Wrapper generation broken » 2021-04-08 14:34:57

Example from mORMot2

unit mORMotClient;

{
  WARNING:
    This unit has been generated by a mORMot 2.0.1 server.
    Any manual modification of this file may be lost after regeneration.

  Synopse mORMot framework. Copyright (C) 2021 Arnaud Bouchez
    Synopse Informatique - http://synopse.info

  This unit is released under a MPL/GPL/LGPL tri-license,
  and therefore may be freely included in any application.

  This unit would work on Delphi 6 and later, under all supported platforms
  (including MacOSX, and NextGen iPhone/iPad), and the Free Pascal Compiler.
}

interface

uses
  SynCrossPlatformJSON,
  SynCrossPlatformSpecific,
  SynCrossPlatformREST;
  

type // define some enumeration types, used below
  TPeopleSexe = (sFemale, sMale);

type // define some record types, used as properties below
  TresultRec = record
      erfolgJN: String;
      fehlertext: String;
      hinweistext: String;
  end;

  00e21f50 = record
        H3a: Boolean;
        H3b: RawBlob;
  end;

  00e21ea0 = record
      H1: Integer;
      H2: String;
      H3: 00e21f50;record
        H3a: Boolean;
        H3b: RawBlob;
      end;
  end;

  TTestCustomJSONArraySimpleArray = record
    F: String;
    F1: TresultRec;record
      erfolgJN: String;
      fehlertext: String;
      hinweistext: String;
    end;
    G: RawBlob;
    H: 00e21ea0;record
      H1: Integer;
      H2: String;
      H3: 00e21f50;record
        H3a: Boolean;
        H3b: RawBlob;
      end;
    end;
    I: TDateTime;
    J: RawBlob;
  end;

  00e213a0 = record
      erfolgJN: String;
      fehlertext: String;
      hinweistext: String;
  end;

#30 mORMot Framework » mORMot2 Wrapper generation broken » 2021-04-08 14:31:25

itSDS
Replies: 11

Hi Arnaud, i generated a soa interface for a new service and created the CrossPlatform Wrappers for an app.
But the generated pas - Sourcecode ist broken. I send you an example via EMail.

#31 Re: mORMot Framework » New Statics for mORMot » 2021-03-29 19:42:53

@ab i also have a question,

i compile my sqlite.obj sqlite.o with bcc32/64 from Rad Studio 10.4.2 and they work, is there a reason not to do this ?

#32 mORMot Framework » SynDBUniDAC - Patch from matkov does not work with my environment » 2021-03-29 19:25:47

itSDS
Replies: 3

Hi AB today i update mORMot to the actual Version and testet it
We use SynDBUniDAC.
But some of the changes from matkov throw unexpected SQL Errors with MySQL and MSSQL
I had to revert SynDBUniDac to the "old" Version.

MySQL Error:

Erste Gelegenheit für Exception bei $76A4A8B2. Exception-Klasse EMySqlException mit Meldung '#HY000Unerlaubte Mischung von Sortierreihenfolgen (latin1_german2_ci, IMPLICIT) und (utf8_general_ci, COERCIBLE) für Operation '=''. Prozess imsys.exe (7000)

with Query:

delete from tabellenbeziehungen where (beziehungsart = :("MZ_MDELizenzen"):) and (referenztabelle = :("monteure"):) and (referenzfeld = :("monteurid"):) and (bezug = :("DFCloud.Lizenzen"):) and (bezugsfeld = :("Lizenzcode"):) and (referenzwert = :(53):)

MS-SQL Error:

Erste Gelegenheit für Exception bei $76A4A8B2. Exception-Klasse EUniError mit Meldung 'Operandentypkollision: nvarchar(max) ist inkompatibel mit sql_variant'. Prozess imsys.exe (7000)

with Query:

SELECT stammdatenid f0, parentID f1, kategorie f2, auswahl f3, anzeigen f4, feld01 f5, hostwert f6, unplausibel_meldungstext f7, extrem_unplausibel_meldungstext f8 FROM stammdaten where (kategorie = :("Vorgangsgrund"):) order by stammdatenid
(and other select queries)

Removing the Prepare in line 768:

function TSQLDBUniDACStatement.DatasetPrepare(const aSQL: string): boolean;
begin
  (fQuery as TUniQuery).SQL.Text := aSQL;
//  TUniQuery(fQuery).Prepare;
  fQueryParams := TUniQuery(fQuery).Params;
  result := fQueryParams<>nil;
end;

solves the Problem also, but as i don't know what matkov used to do with the patch, i reverted complete to the former SynDBUniDAC.pas - i think i don't need the patch

#34 Re: mORMot Framework » The mORMot on Android » 2020-05-13 10:52:50

Interesting work.

i would like to test it on RS 10.4 do you think it will work ?

#35 mORMot Framework » Question: Using 1 Database for multiple mORMot Clients » 2020-05-13 10:50:55

itSDS
Replies: 3

Using an SQL Server for Example MySQL with mORMot TSQLRecords i have the Problem at a Customer:

We need 1 mORMot in DMZ and 1 internal but using the same SQL Server.
Both Client insert in the same TSQLRecord.

now wi get duplicate key errors.

Is it possible (by option) that both Client get the latest free key before inserting ?

#36 Re: mORMot Framework » Problem with BLOB/UniDAC/REST/MSSQL » 2020-03-20 20:08:42

I made it a little "Smarter" smile

procedure TSQLDBUniDACStatement.DataSetBindSQLParam(const aArrayIndex, aParamIndex: integer; const aParam: TSQLDBParam);
var
  P : TDAParam;
begin
// SynDBLog.Enter('DataSetBindSQLParam(%, %, %)', [aArrayIndex, AParamIndex, Length(aParam.VData)], Self);
  if fQueryParams[aParamIndex] is TDAParam then begin
    with aParam do begin
      P := TDAParam(fQueryParams[aParamIndex]);
      P.ParamType := SQLParamTypeToDBParamType(VInOut);
      if VinOut <> paramInOut then
        case VType of
          SynTable.ftBlob: begin
{$ifdef UNICODE}
            if aArrayIndex>=0 then
              P.SetBlobData(Pointer(VArray[aArrayIndex]),Length(VArray[aArrayIndex]))
            else
              P.SetBlobData(Pointer(VData),Length(VData));
{$else}
            if aArrayIndex>=0 then
              P.AsString := VArray[aArrayIndex]
            else
              P.AsString := VData;
{$endif}
            exit;
          end;
        end;
    end;
  end;
  inherited DataSetBindSQLParam(aArrayIndex, aParamIndex, aParam);
end;

#37 Re: mORMot Framework » Problem with BLOB/UniDAC/REST/MSSQL » 2020-03-20 19:45:53

I just made a copy and fixed the BLOB Part - But its possible to only change the BLOB Part for sure.

#39 Re: mORMot Framework » Problem with BLOB/UniDAC/REST/MSSQL » 2020-03-20 12:56:31

Hi AB,

today i found the real Solution for the BUG.
My Previuosly change is not correct and can be removed.

UniDAC has overriden the TParam with TDAParam in DBAccess.
Your TSQLDBDatasetStatement.DataSetBindSQLParam uses TParam.SetBlobData function and does not check that TDAParam has another Implementation for SetBlobData (Its not overrride / virtual)

As Solution i added TSQLDBUniDACStatement.DataSetBindSQLParam which checks wether TParam is a TDAParam and then calls the correct SetBlobData function.

Pls change my BUG FIX as follows:

SynDBUniDAC.pas

class declaration:

  ///	implements a statement via a UniDAC connection
  TSQLDBUniDACStatement = class(TSQLDBDatasetStatement)
  protected
    /// initialize and set fQuery: TUniQuery internal field as expected
    procedure DatasetCreate; override;
    /// set fQueryParams internal field as expected
    function DatasetPrepare(const aSQL: string): boolean; override;
    /// execute underlying TUniQuery.ExecSQL
    procedure DatasetExecSQL; override;
    procedure DataSetBindSQLParam(const aArrayIndex, aParamIndex: integer; const aParam: TSQLDBParam); override;
  public
  end;
procedure TSQLDBUniDACStatement.DataSetBindSQLParam(const aArrayIndex, aParamIndex: integer; const aParam: TSQLDBParam);
var P: TDAParam;
    I64: Int64;
    tmp: RawUTF8;
begin
// SynDBLog.Enter('DataSetBindSQLParam(%, %, %)', [aArrayIndex, AParamIndex, Length(aParam.VData)], Self);
  if fQueryParams[aParamIndex] is TDAParam then begin
    with aParam do begin
      P := TDAParam(fQueryParams[aParamIndex]);
      P.ParamType := SQLParamTypeToDBParamType(VInOut);
      if VinOut <> paramInOut then
        case VType of
          SynTable.ftNull: begin
            P.Clear;
            {$ifdef UNICODE}
            P.AsBlob := nil; // avoid type errors when a blob field is adressed
            {$else}
            P.AsString := '';
            {$endif}
          end;
          SynTable.ftInt64: begin
            if aArrayIndex>=0 then
              I64 := GetInt64(pointer(VArray[aArrayIndex])) else
              I64 := VInt64;
            {$ifdef UNICODE}
            P.AsLargeInt := I64;
            {$else}
            if (PInt64Rec(@I64)^.Hi=0) or (PInt64Rec(@I64)^.Hi=Cardinal(-1)) then
              P.AsInteger := I64 else
              if TSQLDBDatasetConnectionProperties(Connection.Properties).
                 fForceInt64AsFloat then
                P.AsFloat := I64 else
                P.Value := I64;
            {$endif}
          end;
          SynTable.ftDouble:
            if aArrayIndex>=0 then
              P.AsFloat := GetExtended(pointer(VArray[aArrayIndex])) else
              P.AsFloat := unaligned(PDouble(@VInt64)^);
          SynTable.ftCurrency:
            if aArrayIndex>=0 then
              P.AsCurrency := StrToCurrency(pointer(VArray[aArrayIndex])) else
              P.AsCurrency := PCurrency(@VInt64)^;
          SynTable.ftDate:
            if aArrayIndex>=0 then begin
              UnQuoteSQLStringVar(pointer(VArray[aArrayIndex]),tmp);
              P.AsDateTime := Iso8601ToDateTime(tmp);
            end else
              P.AsDateTime := PDateTime(@VInt64)^;
          SynTable.ftUTF8:
            if aArrayIndex>=0 then
              if (VArray[aArrayIndex]='') and
                 fConnection.Properties.StoreVoidStringAsNull then
                P.Clear else begin
              UnQuoteSQLStringVar(pointer(VArray[aArrayIndex]),tmp);
              if fForceUseWideString then
                P.Value := UTF8ToWideString(tmp) else
                P.AsString := UTF8ToString(tmp);
            end else
              if (VData='') and fConnection.Properties.StoreVoidStringAsNull then
                P.Clear else
              if fForceUseWideString then
                P.Value := UTF8ToWideString(VData) else
                P.AsString := UTF8ToString(VData);
          SynTable.ftBlob:
            {$ifdef UNICODE}
            if aArrayIndex>=0 then
              P.SetBlobData(Pointer(VArray[aArrayIndex]),Length(VArray[aArrayIndex]))
            else
              P.SetBlobData(Pointer(VData),Length(VData));
            {$else}
            if aArrayIndex>=0 then
              P.AsString := VArray[aArrayIndex] else
              P.AsString := VData;
            {$endif}
          else
            raise ESQLDBDataset.CreateFmt(
              '%.DataSetBindSQLParam: Invalid type % on bound parameter #%d',
              [self,ord(VType),aParamIndex+1]);
          end;
    end;
  end else
    inherited DataSetBindSQLParam(aArrayIndex, aParamIndex, aParam);
end;

I made some more modifications to SynDBUniDac. i will send it to you by mail.

#40 mORMot Framework » BUG NewStatementPrepared - AddObject » 2020-03-19 21:49:04

itSDS
Replies: 1

Hi AB i found a litte BUG in NewStatementPrepared:

see the line with // itSDS

function TSQLDBConnection.NewStatementPrepared(const aSQL: RawUTF8;
  ExpectResults, RaiseExceptionOnError, AllowReconnect: Boolean): ISQLDBStatement;
var Stmt: TSQLDBStatement;
    ToCache: boolean;
    ndx,altern: integer;
    cachedSQL: RawUTF8;

  procedure TryPrepare(doraise: boolean);
  var Stmt: TSQLDBStatement;
  begin
    Stmt := nil;
    try
      InternalProcess(speActive);
      try
        Stmt := NewStatement;
        Stmt.Prepare(aSQL,ExpectResults);
        if ToCache then begin
          if fCache=nil then
            fCache := TRawUTF8List.Create([fObjectsOwned,fNoDuplicate,fCaseSensitive]);
          if fCache.AddObject(aSQL,Stmt)>=0 then			// itSDS
            Stmt._AddRef else // will be owned by fCache.Objects[]
            SynDBLog.Add.Log(sllWarning,'NewStatementPrepared: unexpected '+
              'cache duplicate for %',[Stmt.SQLWithInlinedParams],self);
        end;
        result := Stmt;
      finally
        InternalProcess(speNonActive);
      end;
    except
      on E: Exception do begin
        with SynDBLog.Add do
          if [sllSQL,sllDB,sllException,sllError]*Family.Level<>[] then
            LogLines(sllSQL,pointer(Stmt.SQLWithInlinedParams),self,'--');
        Stmt.Free;
        result := nil;
        StringToUTF8(E.Message,fErrorMessage);
        fErrorException := PPointer(E)^;
        if doraise then
          raise;
      end;
    end;
  end;

the former used cachedSQL - Value is sometimes empty

#41 Re: mORMot Framework » Problem with BLOB/UniDAC/REST/MSSQL » 2020-03-19 21:19:33

Results: After a while of Debugging in found that the Problem is in UNIDAC. I get the same error with MySQL / MSSQL - Provider.
I reproduced the behavior every time. The Problem with mORMot i have only with the SynCrossPlatform Client. Here SynDBUniDAC is used. As a Workaround i modified TSQLDBUniDACConnectionProperties.

My Code is not perfect normally i should set
UseCache := false
in Create.

function TSQLDBUniDACConnectionProperties.IsCachable(P: PUTF8Char): boolean;
// UNIDAC Probleme mit Update - Statements mit BLOB Parametern.
// Bei gecachten Statement wird der BLOB immer aus dem "Cache" genommen
begin
  result := not IdemPChar(P,'UPDATE ');
  if result then
    result := inherited IsCachable(P);
end;

There is some Strange Behavior in UniDAC, where i could not find the error. SetBlobParam set's the Blob correctly, but TCustomDASQL.AssignParamValue( seems to use a wrong Value from "i don't know where" it is taken.

#42 Re: mORMot Framework » Problem with BLOB/UniDAC/REST/MSSQL » 2020-03-18 07:51:39

Actually i use synoledb for test i ll post my results

#43 mORMot Framework » Problem with BLOB/UniDAC/REST/MSSQL » 2020-03-17 19:47:23

itSDS
Replies: 11

I have a Problem with Updating a TSQLRecord's Blob Data. The Problem is visible in this Picture (Screen from LOG Viewer)

LOG Snippet

I update 3 "BinaerdatenRecord" after i insert them. I update 2 fields, BLOB Field Binaerdaten and Integer Field GroesseinBytes

In the First Call mORMot / UniDAC calls Prepare for the Update Statement.
In the following calls the Prepared Statement is used.

As you can see in the violet boxes the BLOB - Data has different sizes 143.5 / 119.2 and 100.4KB
the Blob Parameter is 110210 Byte

The Error is:

All 3 Database Records are filled with the Same BLOB - Data

Now my Question:
Is it a mORMot or a UniDAC Problem ? As Database Server i Use MS-SQL 2012
Is it Possible to disable Prepared Statement for Queries with BLOB Parameter

#44 Re: mORMot Framework » Revision 2.x of the framework » 2020-03-16 09:39:27

I like your upgrade thoughts and filled out the survey
What i was missing is : will complete CrossPlatform support available with 10.4 ? (They change something with arc ?)

#45 Re: mORMot Framework » SynDBUniDAC with prDirect compared to prNativeClient(prAuto) » 2019-11-30 09:26:17

Hi mpv i used the syndboledb before, but offen i get Exception that free was called from wrong thread in disconnect.
and we have customer in great business where the installation of sqlncli is not possible.
Wih new UniDAC 8.1.2 i wanted to give Unidac a try with SQL Server.Provider=prDirect where no extra Software ist needed.

Yesterday i found the solution for the UniDAC Connect "lag":
Just set SQL Server.ConnectionTimeout to 0 in Specialoptions.

#46 mORMot Framework » SynDBUniDAC with prDirect compared to prNativeClient(prAuto) » 2019-11-29 09:40:19

itSDS
Replies: 2

Hi i use UniDAC 8.1.2 for SQL Server 11 with mORMot's SynDBUniDAC.
Here i made some Speedtests and compared the divers SQL Server.Provider Options.
The Queries itself are nearly with the same Speed. But in the first Connect Part of any ServerRequest the prDirect Option uses 120ms on my System to Connect. the prAuto only 10ms that is 12times slower.

We use mORMot as Rest/Soa Service, for every Rest Request the Connection is newly opened.
Some Heavily transfers use 2seconds with prAuto and 10s with prDirect.
The Reason ist the 120ms Connection Time.

Does anybody have a idea why direct connect is that slower ?

#47 Re: mORMot Framework » TID Guid » 2019-10-07 08:47:59

I think it will not work cause the TID as int64 is essential for mORMot and massivly used internally

#48 mORMot Framework » Problem to create Query Params for MS-SQL RetrieveDocVariantArray » 2019-08-01 21:10:18

itSDS
Replies: 1

Hi Arnaud,

i try to select some SQLRecord from External MS-SQL Database.
we wan't to select all record where the field (Messzeitpunkt : TDateTime) = date

i tried a lot of valid ms-sql statements, but every time the mORMot Parser makes errors:

Version1:
whereStatement = convert(date, GETDATE()) = convert(date, Messzeitpunkt)

20190801 22095955  2 warn    mORMotDB.TSQLRestStorageExternal(02c45990) TSQLRestStorageExternal.AdaptSQLForEngineList: statement too complex -> would use SQLite3 virtual engine [SELECT ID,CreationDate,LastEditDate,AuftragStartEventID,Gruppierung,Ursprung,IPAdresse,Port,Messzeitpunkt,Barcode,Drehmoment,DrehmomentErgebnis,Drehwinkel,DrehwinkelErgebnis,GesamtErgebnis,Daten,SpindelTag,ControllerName,TighteningID,TorqueUnits,BatchCount,BatchSize,BatchStatus,CountOfScrewSteps,Screwprogram,Torquehighlimit,Torquelowlimit,Anglehighlimit,Anglelowlimit,ResultUniqueID,EORTimeStamp FROM EOR_QSYSOpenProtocolRecord WHERE convert(date, GETDATE()) = convert(date, Messzeitpunkt)]


Verstion 2:
whereStatement = CONVERT(nvarchar(max), messzeitpunkt, 23)=?, ['2019-08-01']
Error:
mORMotDB.TSQLRestStorageExternal(02ab5990) TSQLRestStorageExternal.AdaptSQLForEngineList: unsupported function CONVERT() for [SELECT ID,CreationDate,LastEditDate,AuftragStartEventID,Gruppierung,Ursprung,IPAdresse,Port,Messzeitpunkt,Barcode,Drehmoment,DrehmomentErgebnis,Drehwinkel,DrehwinkelErgebnis,GesamtErgebnis,Daten,SpindelTag,ControllerName,TighteningID,TorqueUnits,BatchCount,BatchSize,BatchStatus,CountOfScrewSteps,Screwprogram,Torquehighlimit,Torquelowlimit,Anglehighlimit,Anglelowlimit,ResultUniqueID,EORTimeStamp FROM EOR_QSYSOpenProtocolRecord WHERE CONVERT(nvarchar(max), messzeitpunkt, 23)=:('2019-08-01'):]

do you have an idea how to get the desired records ?

Is it a bug or do i use it wrong ?

#49 Re: mORMot Framework » Error Linking new 3.29 sqlite.obj to my Project » 2019-07-29 20:46:24

yes i'm in contact with bruneau from embarcadero who found the reason in sqlite.c. SQLite 3.29 includes math.h but 3.28 does not.
if you have access to the embarcadero discourse page you can read about it

#50 Re: mORMot Framework » Error Linking new 3.29 sqlite.obj to my Project » 2019-07-28 15:05:19

Hi AB, just to close this issue.
the external symbol __ieee_32_p_inf is defined in math.h if INFINITY is not defined

in 3.28 there seems to be INFINTY defined (i can not find out where ..)
in 3.29 it is not defined resulting in using the definition from math.h

in Line 30821 of 3.29 sqlite.c it is used. In 3.28 the constant and in 3.29 the external definition.
As work around in changed the code to use the constant in 3.29 as in 3.28 - Now i can link it again.

          }else{
// #ifdef INFINITY  // auskommentiert by itSDS
//            result = INFINITY*s;  // auskommentiert by itSDS
//#else  // auskommentiert by itSDS
            result = 1e308*1e308*s;  /* Infinity */
//#endif  // auskommentiert by itSDS
          }

Board footer

Powered by FluxBB