#201 Re: mORMot 1 » 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

#202 Re: mORMot 1 » 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

#204 mORMot 1 » 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 ?

#205 Re: mORMot 1 » 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...

#207 mORMot 1 » 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;

#208 Re: mORMot 1 » 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.

#209 Re: mORMot 1 » 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

#210 mORMot 1 » 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

#211 Re: mORMot 1 » 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...

#212 mORMot 1 » 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;

#213 mORMot 1 » 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

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

k next time i try the correct way

#216 mORMot 1 » 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;

#217 Re: mORMot 1 » 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

#218 Re: mORMot 1 » 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

#219 mORMot 1 » 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 ?

#220 Re: mORMot 1 » 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

#221 Re: mORMot 1 » 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)

#222 Re: mORMot 1 » 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

#223 Re: mORMot 1 » 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

#224 Re: mORMot 1 » mORMot2 Wrapper generation broken » 2021-04-09 09:47:35

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

#225 Re: mORMot 1 » 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

#226 Re: mORMot 1 » 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;

#227 Re: mORMot 1 » 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;

#228 mORMot 1 » mORMot2 Wrapper generation broken » 2021-04-08 14:31:25

itSDS
Replies: 12

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.

#229 Re: mORMot 1 » 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 ?

#230 mORMot 1 » 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

#232 Re: mORMot 1 » 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 ?

#233 mORMot 1 » 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 ?

#234 Re: mORMot 1 » 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;

#235 Re: mORMot 1 » 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.

#236 Re: mORMot 1 » Problem with BLOB/UniDAC/REST/MSSQL » 2020-03-20 15:21:21

sry ab didn't think about the size

#237 Re: mORMot 1 » 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.

#238 mORMot 1 » 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

#239 Re: mORMot 1 » 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.

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

Actually i use synoledb for test i ll post my results

#241 mORMot 1 » 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

#242 Re: mORMot 1 » 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 ?)

#243 Re: mORMot 1 » 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.

#244 mORMot 1 » 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 ?

#245 Re: mORMot 1 » 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

#246 mORMot 1 » 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 ?

#247 Re: mORMot 1 » 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

#248 Re: mORMot 1 » 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
          }

#249 Re: mORMot 1 » Error Linking new 3.29 sqlite.obj to my Project » 2019-07-27 11:11:00

Oh nothing wrong with, but i build them by myself because i also build the 64Bit Versions

#250 Re: mORMot 1 » Error Linking new 3.29 sqlite.obj to my Project » 2019-07-26 22:38:42

But i do not get this error using compiled SQLite 3.28 obj. It came with 3.29.
Normally i would say that the linker is missing a lib file with the named function...

Embarcadero made a lot changes to bcc in 10.3.2 and it may be a solution to use an older Version but why - if its only a missing function ?

Board footer

Powered by FluxBB