#51 Re: mORMot 1 » Lazarus 2.0.8 & FPC 3.0.4 » 2020-04-24 08:38:43

It may be a lot of bugs in Lazarus or just one bug with cardinal values in compiler.
Since 2.0.8 is stable version, more likely it was bug in compiler.

#52 Re: mORMot 1 » Lazarus 2.0.8 & FPC 3.0.4 » 2020-04-23 21:25:09

Nice, now demo project pass build. 

By the way, 2020-04 lazarus-2.0.8-fpc-3.2.0_fixes-44680 not works.
I can't run empty form project due error (don't work if Application.DoubleBuffered).
If i disable it, error appear in another module. I have many problems with empty project.
Suppose that issue comes from compiler itself.

Will test another version.
---
https://synopse.info/forum/viewtopic.ph … 695#p31695
FPC: "fixes3.2" and Lazarus: "fixes2.0" works.

#54 mORMot 1 » Lazarus 2.0.8 & FPC 3.0.4 » 2020-04-22 13:24:32

George
Replies: 13

Hello!

Just installed Lazarus 2.0.8 (win64) which comes with FPC 3.0.4.

Tried to compile sample "04 - HTTP Client-Server".
Can't compile with error: PFPCInterfaceData = TypInfo.PInterfaceData; (SynFPCTypInfo)

Found in documentation:

If you want to use the FPC trunk, please modify line #262 in Synopse.inc to enable the FPC_PROVIDE_ATTR_TABLE conditional and support the latest trunk RTTI changes.
{$if not defined(VER3_0) and not defined(VER3_2) and not defined(VER2)}
    {$define FPC_PROVIDE_ATTR_TABLE} // to be defined since SVN 42356-42411
    // on compilation error in SynFPCTypInfo, undefine the above conditional
    // see https://lists.freepascal.org/pipermail/ … 00612.html
{$ifend}

It is undefined by default.
Unit "typinfo" In FPC 3.0.4, does not contain PInterfaceData (as well as PVmtMethodParam, PIntfMethodTable, PIntfMethodEntry).

So, does this mean, that latest mORMot 1.8 does not support box version of Lazarus and FPC?
As i see, FPC 3.0.4 is not new, and seems, should be supported, because mORMot supports all recent Delphi and FPC is main target for mORMot 2.0.

FPC trunk SVN 40491

Is it actual recommended version from 2018 year?

Can someone clarify?

#55 Re: mORMot 1 » Revision 2.x of the framework » 2020-03-09 16:36:12

TortoiseGIT - nice git client, works perfectly with gitlab as well.
I use it with beyond compare. Worth to try.

#56 Re: mORMot 1 » Revision 2.x of the framework » 2020-03-06 21:20:12

Documentation is already in a markdown-like format (closer to RTF in fact), and maintained within the source code. See https://synopse.info/fossil/finfo?name= … mework.pro

My thoughts was about html documentation.
Currently, md format is primary documentation format, used everywhere.
For example, https://angular.io/guide/architecture
And https://docusaurus.io is just one of many services that can help with that.

#57 Re: mORMot 1 » Revision 2.x of the framework » 2020-03-03 21:05:30

Agree. It's time to move on)
Instead of non UI component wrappers, would be nice to refresh documentation. High level classes is good idea too.

Maybe this helps: https://docusaurus.io
https://mikro-orm.io/docs/defining-entities

Also i agree about opinion to drop old compiler support. Not worth to waste time.
FPC is good choice as main target, because, embarcadero actively ruining Delphi community, which are almost gone, unfortunately.

Would be nice to beat .net core and support windows, linux and mac.
FPC and high level classes can help with that.

May be also a git as a main repository (to prevent periodical sync problems)?

+1

#59 mORMot 1 » Detailed hardware info » 2019-07-10 15:16:56

George
Replies: 2

Hello!

Can't find, but maybe i'm blind,
can i get detailed hardware info under windows and linux?

#61 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2018-02-21 14:14:29

Hello!
readDir returns folders without trailing delimiter (\).
How correctly evaluate folders?

filesAndFolders = readDir('path', true); // get files and folders
And check every item using directoryExists?

#62 Re: mORMot 1 » Help for new user » 2017-12-28 07:49:01

I'm looking for predefined functions for RawUTF8, similar to "LeftStr(str, count)", "Copy(str, start, len)".
Seems SynCommons does not contain what I'm looking for.
Am i wrong?

#63 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-11-14 20:01:26

About long-live objects i understand.
I'm going to create a new empty object from delphi side, add some fields (or instantiate object using known js class), fill data and then return it as result.
From js side, code may looks like listed below:

function exec() {
    // local context variable that store result until end of method execution
    let result = process.binding('delphi').getSomeObject();
    // do something
}

I found sample code in SyNodeBinding_fs.
In fs_fileStat method, steps are exact same as i described in previous post)

#64 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-11-13 20:52:55

Hello!

When delphi function returns js object (via vp: JSArgRec) with some fields, what is correct steps to be sure that JS garbage collector will not destroy object too early?
1. create local rooted object on delphi.
2. fill.
3. assign to vp.rval and call FreeRootedObject?

Or RootedObject should be used only for objects that was passed to delphi as parameters (to add reference and prevent object destruction while working with it)?

#65 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-10-27 22:36:49

How to access to prototype field "fld1" from binded delphi method?

var TBaseTest = (function () {
    function TBaseTest() {
    }
    return TBaseTest;
}());
TBaseTest.prototype.fld1 = 'fff';

bindedFunc(TBaseTest);

I use GetPrototype method, but in result object can't access to fld1 property...

#66 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-10-19 16:16:27

Hello, MPV!

mpv wrote:

We use a SpiderMonkey 52 in SyNode

Do you have compiled files for version 52.4.1?

#67 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-10-11 12:06:14

How to get access to TSMEngine.ThreadData from cx: PJSContext?
TSMEngine(cx.PrivateData).ThreadData

#68 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-10-02 19:53:13

I have code sample that cannot be executed in SyNode, but run without any problems inside node.js or pure ES2015
Seems iterator object for "arguments" is missing.
Where that internal member initialize?)

"use strict";
function test(...args) {
    console.log(`param count is: ${arguments.length}`);
}
function testExecutor(p1, p2) {
    test(...arguments); // <<<<<<<< arguments is not iterable
}
testExecutor('param1', 'param2');

#70 Re: mORMot 1 » Debug SyNode using VSCode » 2017-09-30 14:25:15

What about synode.js, i was implemented automatic core modules search with index.js support (when module has index.js it may be loaded as folder name).
With that change, new modules will not require changes in synode.js. Pretty handy isn't it?

dirty hacks in firefox-remote-debugger VSCode plugin

What changes was necessary? Version 1.6.0 of debugger work, only issue was path comparing that case sensitive (afaik it will be insensitive soon).

Now I think how to reduce both synode & firefox to one protocol

And you can cooperate (suggestions, ideas or may be pull requests) with debugger plugin developer smile
To make both projects better to work together.

#72 Re: mORMot 1 » Debug SyNode using VSCode » 2017-09-22 11:40:16

With debugger developer we done some work to provide compatibility.
I patched SyNode sources to get work debugger correctly, modules placed in folder Units_PatchedModules
I'm not sure about one place, where i get thread id (in SyNodeRemoteDebugger.pas), it may be incorrect thread id (i want pass to debugger thread id that processing corresponding smEngine).
Also i patched JS code (Win64\core_modules\). Beyond compare may help evaluate differences.

Here is compiled project with sources (created in delphi 10.2).
Project include use cases of both SyNode demos with additional feature demonstration.
In addition it include vscode project written in typescript (Win64\web.apps\app1\).
Debugging work, even more, source maps work too.

@mpv, take a look, some (or almost all) changes may be imported to SyNode, as well as demo project.

#73 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-09-18 21:29:47

Cant find reference for method readDir(path, true) from fs.js.
Is it incomplete or defined somewhere in tricky way?
I get error readDir is not defined

function findAllCoreModules(path) {
    let result = new Array;
    let filesAndFolders = fs.readdirSync(path);
    for (let item of filesAndFolders) {
        result.push(item);
    }
    return result;
}

#75 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-09-12 07:54:20

Inside folder "core_modules" present file "console.js", inside file i see comment:

Modified by UnityBase core team to be compatible with SyNode

Module initialization relies on process.stdout, process.stderr.
Maybe someone already have usage sample (per engine global console implementation linked with callback from delphi side)?
Or information about how that can be done..

I want create simple demo application that will use more features than shown in current two demos.
With vscode debugger support.

#76 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-09-04 20:43:12

Need little help, i get strange results while debugging Debugger.js.

    constructor (actorID, source, parent) {
        super(actorID, parent);
        parent._sourcesMap.set(source, this)
        this._source = source;
        this._breakpoints = {};
    }
    ...
    get _resp(){
        let source = this._source;// || this.generatedSource;
        consoleLog(stringify(source));   // -> [object undefined]
        consoleLog(source.url);          // -> ModuleLoader.js
        ...

How that possible?

With JSON.stringify i get:

    get _resp(){
        let source = this._source;// || this.generatedSource;
        consoleLog(JSON.stringify(source)); // -> {}
        consoleLog(source.url);             // -> ModuleLoader.js
        ...

I use output log to debug Debugger.js, is better way exists?

#77 Re: mORMot 1 » Debug SyNode using VSCode » 2017-08-31 19:37:22

On GIT available debugger branch that going to support SyNode.
Now, all changes available from main branch, no need to install special version of debugger, use plugin library from vscode.

Some fixes also required on SyNode side.
Here is some news, in case if anyone would like to enjoy.

#78 Re: mORMot 1 » Debug SyNode using VSCode » 2017-08-29 18:01:48

Should break points work in current implementation?
Looks like vscode debug plugin trying to attach to tab instead of attaching to addon. That's how it seen from wireshark.
In addition, firefox can attach, i think that issue on vscode plugin side. Well, i'll post here if get solution.

#80 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-08-28 20:55:46

Hi, mpv!

What is the best approach to add "console" emulation for JS context?
Should i create a class with all required methods, instantiate it and then call aEngine.GlobalObject.ptr.DefineProperty?
Is there a way to group few methods in one variable (like console.log, console.clear) without class instance on delphi side?
PS: dll extension can provide such behavior, but i'm interested to implement console internally.

#81 mORMot 1 » TRawUTF8ListHashed and generics » 2017-07-18 14:46:52

George
Replies: 0

Hello.

I found very handy to use TRawUTF8ListHashed with generic syntax.
AFAIK some classes in mORMot already support generic syntax.
So, i've implemented new class based on TRawUTF8ListHashed.

This is not great code and not universal.
Does anyone have better TRawUTF8ListHashed extension that support generic syntax?

unit SynCommons.Generics;

interface

uses
  System.Rtti,
  SynCommons;

type

  TRawUTF8ListHashed<T> = class(TRawUTF8ListHashed)
  public
    // TRawUTF8ListHashed
    function AddObjectIfNotExisting(const aText: RawUTF8; aObject: T; wasAdded: PBoolean = nil): PtrInt; reintroduce;

    // TRawUTF8List
  type
    GenericObjectArray = array of T;
    PGenericObjectPointerArray = ^GenericObjectArray;
  private
    procedure PutObject(Index: PtrInt; const Value: T);
    function GetObjectPtr: PGenericObjectPointerArray;
  public
    function GetObject(Index: PtrInt): T; {$IFDEF HASINLINE}inline; {$ENDIF}
    function GetObjectByName(const Name: RawUTF8): T;
    function AddObject(const aText: RawUTF8; aObject: T): PtrInt;
    function IndexOfObject(aObject: T): PtrInt;
    property Objects[Index: PtrInt]: T read GetObject write PutObject;
    property ObjectPtr: PGenericObjectPointerArray read GetObjectPtr;
  end;

implementation

{ TRawUTF8ListHashed<T> }

{$REGION 'TRawUTF8ListHashed'}

function TRawUTF8ListHashed<T>.AddObjectIfNotExisting(const aText: RawUTF8; aObject: T; wasAdded: PBoolean): PtrInt;
var
  Val: TValue;
begin
  Val := TValue.From<T>(aObject);
  // Class
  if Val.Kind = tkClass then
    Result := inherited AddObjectIfNotExisting(aText, Val.AsObject, wasAdded);
  // Interface
  if Val.Kind = tkInterface then
    Result := inherited AddObjectIfNotExisting(aText, Val.AsInterface as TObject, wasAdded);
end;

{$ENDREGION}
{$REGION 'TRawUTF8List'}

procedure TRawUTF8ListHashed<T>.PutObject(Index: PtrInt; const Value: T);
var
  Val: TValue;
begin
  Val := TValue.From<T>(Value);
  // Class
  if Val.Kind = tkClass then
    inherited PutObject(Index, Val.AsObject);
  // Interface
  if Val.Kind = tkInterface then
    inherited PutObject(Index, Val.AsInterface as TObject);
end;

function TRawUTF8ListHashed<T>.GetObject(Index: PtrInt): T;
var
  Value: TValue;
begin
  Value := TValue.From(inherited GetObject(Index));
  Result := Value.AsType<T>;
end;

function TRawUTF8ListHashed<T>.GetObjectByName(const Name: RawUTF8): T;
var
  Value: TValue;
begin
  Value := TValue.From(inherited GetObjectByName(Name));
  Result := value.AsType<T>;
end;

function TRawUTF8ListHashed<T>.AddObject(const aText: RawUTF8; aObject: T): PtrInt;
var
  Value: TValue;
begin
  Value := TValue.From<T>(aObject);
  // Class
  if Value.Kind = tkClass then
    Result := inherited AddObject(aText, Value.AsObject);
  // Interface
  if Value.Kind = tkInterface then
    Result := inherited AddObject(aText, Value.AsInterface as TObject);
end;

function TRawUTF8ListHashed<T>.IndexOfObject(aObject: T): PtrInt;
var
  Value: TValue;
begin
  Value := TValue.From<T>(aObject);
  // Class
  if Value.Kind = tkClass then
    Result := inherited IndexOfObject(Value.AsObject);
  // Interface
  if Value.Kind = tkInterface then
    Result := inherited IndexOfObject(Value.AsInterface as TObject);
end;

function TRawUTF8ListHashed<T>.GetObjectPtr: PGenericObjectPointerArray;
begin
  Result := PGenericObjectPointerArray(GetObjectPtr());
end;

{$ENDREGION}

end.

#83 Re: Low level and performance » Fast TStringList » 2017-04-18 20:06:46

Why not just call Hash.Rehash ?

Not helps, since TRawUTF8ListHashed.Hash.Rehash not change TRawUTF8ListHashed.fChanged which is "true".
When call indexOf (first time) rehashing executes even if we called TRawUTF8ListHashed.Hash.Rehash previously.

Maybe better to move fChanged to TDynArrayHashed with proper handing..

#84 Re: Low level and performance » Fast TStringList » 2017-04-18 19:19:06

Valuable information, thanks.

Would you like to add ReHash method directly to TRawUTF8ListHashed class?

TRawUTF8ListHashed = class(TRawUTF8List)
...
public
...
    /// manual rehashing
    function ReHash: boolean;
...
end

function TRawUTF8ListHashed.ReHash: boolean;
begin
  result := fHash.ReHash;
  fChanged := not result;
end;

#85 Re: Low level and performance » Fast TStringList » 2017-04-18 18:28:14

Thanks, i've changed code.
There is no big overhead when searching 100k items smile
I've tried Dictionary.Hash.ReHash to make proper comparison (no difference).
Finally i've added first search outside of the counter and results now looks great:

TObjectDictionary:
Add time = 812.96 ms
Search time = 15.74 ms
TRawUTF8ListHashed:
Add time = 194.22 ms
Search time = 6.13 ms


// Add time = 812.96 ms
// Search time = 15.74 ms
procedure TForm1.ButtonTObjectDictionaryClick(Sender: TObject);
var
  Dictionary: TObjectDictionary<String, TTest>;
  i: Integer;
  pt: TPrecisionTimer;
  Time: RawUTF8;
  TestObj: TTest;
  IdsForSearch: array of string;
begin
  // Init
  Dictionary := TObjectDictionary<String, TTest>.Create([doOwnsValues]);
  SetLength(IdsForSearch, 100000);
  for i := Low(IdsForSearch) to High(IdsForSearch) do
    IdsForSearch[i] := IntToStr(i + 1500001);
  pt.Init;
  // Add values
  pt.Start;
  for i := 0 to 2000000 do
    Dictionary.Add(i.ToString, TTest.Create(i));
  Time := pt.Stop;
  ShowMessage('add time: ' + UTF8ToString(Time));
  // Perform search 100000 elements
  pt.Start;
  for i := Low(IdsForSearch) to High(IdsForSearch) do
    Dictionary.TryGetValue(IdsForSearch[i], TestObj);
  Time := pt.Stop;
  if not Assigned(TestObj) or (IntToStr(TestObj.Id) <> IdsForSearch[High(IdsForSearch)]) then
    ShowMessage('err');
  ShowMessage('search value time: ' + UTF8ToString(Time));
  Dictionary.Free;
end;

// Add time = 194.22 ms
// Search time = 6.13 ms
procedure TForm1.ButtonTRawUTF8ListHashedClick(Sender: TObject);
var
  Dictionary: TRawUTF8ListHashed;
  i: Integer;
  pt: TPrecisionTimer;
  Time: RawUTF8;
  idx: int64;
  IdsForSearch: array of RawUTF8;
begin
  // Init
  idx := -1;
  Dictionary := TRawUTF8ListHashed.Create(True);
  SetLength(IdsForSearch, 100000);
  for i := Low(IdsForSearch) to High(IdsForSearch) do
    IdsForSearch[i] := Int32ToUtf8(i + 1500001);
  pt.Init;
  // Add values
  pt.Start;
  for i := 0 to 2000000 do
    Dictionary.AddObject(StringToUTF8(i.ToString), TTest.Create(i));
  Time := pt.Stop;
  ShowMessage('add time: ' + UTF8ToString(Time));
  // Perform manual hashing
  // Dictionary.Hash.ReHash; // no difference
  Dictionary.IndexOf(IdsForSearch[0]); // to force hash calculations
  // Perform search 100000 elements
  pt.Start;
  for i := low(IdsForSearch) to High(IdsForSearch) do
    idx := Dictionary.IndexOf(IdsForSearch[i]);
  Time := pt.Stop;
  if (idx = -1) or (Int32ToUtf8(TTest(Dictionary.GetObject(idx)).Id) <> IdsForSearch[High(IdsForSearch)]) then
    ShowMessage('err');
  ShowMessage('search value time: ' + UTF8ToString(Time));
  Dictionary.Free;
end;

#86 Re: Low level and performance » Fast TStringList » 2017-04-18 14:52:45

Hello!

TObjectDictionary perform search faster than TRawUTF8ListHashed, while TRawUTF8ListHashed is faster for add operation.
Is it expected behavior?
Also, if max "i" value is increased up to 20 000 000, out of memory occurs with TRawUTF8ListHashed, while TObjectDictionary works.

// Add time = 2256 ms
// Search time = 0 ms
procedure TForm1.ButtonTObjectDictionaryClick(Sender: TObject);
var
  Dictionary: TObjectDictionary<String, TTest>;
  i: Integer;
  sw: TStopwatch;
  TestObj: TTest;
begin
  Dictionary := TObjectDictionary<String, TTest>.Create([doOwnsValues]);
  sw := TStopwatch.StartNew;
  for i := 0 to 6000000 do
    Dictionary.Add(i.ToString, TTest.Create(i));
  sw.Stop;
  ShowMessage('add time (ms): ' + sw.ElapsedMilliseconds.ToString);
  sw.Reset;
  sw.Start;
  if not Dictionary.TryGetValue('1500000', TestObj) or (TestObj.Id <> 1500000) then
    ShowMessage('err');
  sw.Stop;
  ShowMessage('search value time (ms): ' + sw.ElapsedMilliseconds.ToString);
  Dictionary.Free;
end;

// Add time = 809 ms
// Search time = 360 ms
procedure TForm1.ButtonTRawUTF8ListHashedClick(Sender: TObject);
var
  Dictionary: TRawUTF8ListHashed;
  i: Integer;
  sw: TStopwatch;
  idx: int64;
begin
  Dictionary := TRawUTF8ListHashed.Create(True);
  sw := TStopwatch.StartNew;
  for i := 0 to 6000000 do
    Dictionary.AddObject(i.ToString, TTest.Create(i));
  sw.Stop;
  ShowMessage('add time (ms): ' + sw.ElapsedMilliseconds.ToString);
  sw.Reset;
  sw.Start;
  idx := Dictionary.IndexOf('1500000');
  if (idx = -1) or (TTest(Dictionary.GetObject(idx)).Id <> 1500000) then
    ShowMessage('err');
  sw.Stop;
  ShowMessage('search value time (ms): ' + sw.ElapsedMilliseconds.ToString);
  Dictionary.Free;
end;

#87 Re: mORMot 1 » Custom serializer reader to return objectlist » 2017-04-13 15:30:31

AB, can you take a look at this module to approve that it use TDocVariant by design?

There is 4 classes for serialization / deserialization:
TComplicatedClass
TCustomObjectWithNestedObjLists
TSimpleObjectOne
TSimpleObjectTwo

One class to execute test:
TComplSerializationWithTDocVariantTest

I have one place where i can't add array item by reference:

class function TComplicatedClass.SerializeAsVariant(ComplicatedClass: TComplicatedClass): Variant;
var
  idx: Int64;
  CustomObjectWithNestedObjLists: TCustomObjectWithNestedObjLists;
  VObj: Variant;
begin
  with TDocVariantData(Result) do
    begin
      // Init result
      InitObject([], DocVariantOptionsForSerialization);
      // Add class info
      AddValue('className', Self.QualifiedClassName);
      // Add data
      { Name }
      AddValue('name', ComplicatedClass.Name);
      { field1 }
      // add empty array, to save items from TObjectList<T>
      idx := AddValue('field1', _Arr([], DocVariantOptionsForSerialization));
      // direct access to field2 by index by reference
      with _safe(Value[idx], dvArray)^ do
        // serialize ComplicatedClass.Field1 per item and add it to array
        for CustomObjectWithNestedObjLists in ComplicatedClass.Field1 do
          begin
            VObj := TCustomObjectWithNestedObjLists.SerializeAsVariant(CustomObjectWithNestedObjLists);
            
            AddItem(VObj); // << Here VObj is Variant with TDocVariant object
            VObj := Unassigned; // Without this line i have memory leaks, so AddItem() not owning VObj as i want.

          end;
    end;
end;

#88 Re: mORMot 1 » Custom serializer reader to return objectlist » 2017-04-13 15:06:59

Welcome back to my blog smile

I updated test/demo project with TDocVariant (with TDocVariantData) use case.
Works good, TDocVariant is very powerful part of framework.. Again, not simple as pie, but check the demo and don't forget that every mORMot method well commented.

#89 Re: mORMot 1 » Custom serializer reader to return objectlist » 2017-04-10 15:14:02

Can anyone help with complicated class deserialization (UnitComplicatedObjectSerializationTest)?
Added test case with class that include TObjectList fields with nested objects that include another TObjectList.
Serialization works well, but i can't restore objects from json. I've used documentation that says:

won't handle TObjectList (even if ObjectToJSON is able to serialize them) since has no way of knowing the object type to add (TCollection.Add is missing), unless: 1. you set the TObjectListItemClass property as expected, and provide a TObjectList object, or 2. woStoreClassName option has been used at ObjectToJSON() call and the corresponding classes have been previously registered by TJSONSerializer.RegisterClassForJSON()

Both conditions are implemented, but without luck.

#90 Re: mORMot 1 » Custom serializer reader to return objectlist » 2017-04-10 09:01:22

Test project updated, now looks more simple, use TObjectList serialization to serialize/deserialize TObjectList<T> objects.

#91 Re: mORMot 1 » Understanding mORMot » 2017-04-09 20:47:11

Hello!
Check out this thread.
There is simple test project available, it include: ObjectToJSON, ObjectLoadJSON, JSONToObject, RegisterCustomSerializer and TObjectList / TObjectList<T> serialization / deserialization.
I'm not sure that i've done everything "by design", but almost all works (there is memory leak when json is incorrect, and field mapping not work yet for some reason).

mORMot is powerful and well optimized framework, with a lot of documentation and samples.
But samples not cover everything and may look hard to understand.
Sometimes you may think that code hard to understand, but this is cost of optimizations and FPC support.
Learning path is not easy and sometimes i can't find answers, but i prefer better performance when possible..
As alternative, you can use internal Delphi serialization.

#92 Re: mORMot 1 » Custom serializer reader to return objectlist » 2017-04-06 21:32:07

George wrote:

Personally i have question about generic version of TObjectList<T>.

Found answer here: https://synopse.info/forum/viewtopic.php?id=2943

Not like dependency on REST.Json.
So, i've changed test case code to use mORMot functionality for TObjectList<TCustomObjectForGenerics> serialization / deserialization.
There is memory leak in JSONToObject, when json text is not correct.

#93 Re: mORMot 1 » Custom serializer reader to return objectlist » 2017-04-06 10:21:03

Personally i have question about generic version of TObjectList<T>.

Found answer here: https://synopse.info/forum/viewtopic.php?id=2943

#94 Re: mORMot 1 » Custom serializer reader to return objectlist » 2017-04-05 15:25:02

Hello!

I have simple test case, that probably can help you.
TObjectList - serialization and deserialization works as expected.
Also, i included code that should map fields, but that not works, last line of code (commented).

Personally i have question about generic version of TObjectList<T>.
With similar usage, serialized text not contain objects (that behavior included in test case), while documentation says:

You could also create a TObjectList, or - even better for newer versions of Delphi supporting the generics syntax - a TObjectList<T>

  {$M+}
  TCustomClass = class
  private
    FField1: RawUTF8;
    FField2: RawUTF8;
  published
    property Field1: RawUTF8 read FField1 write FField1;
    property Field2: RawUTF8 read FField2 write FField2;
  end;
  {$M-}
procedure TForm1.Serialize();
var
  i: Integer;
  CustomClassObject: TCustomClass;
  CustomClassList: TObjectList;
begin
  CustomClassList := TObjectList.Create(True);
  // fill test data
  for i := 0 to 4 do
    begin
      CustomClassObject := TCustomClass.Create();
      CustomClassObject.FField1 := 'value ' + StringToUTF8(i.ToString);
      CustomClassObject.FField1 := 'another value ' + StringToUTF8(i.ToString);
      // TObjectList
      CustomClassList.Add(CustomClassObject);
    end;
  // Serialize and show results in memo
  MemoObjectList.Lines.Text := UTF8ToString(ObjectToJSON(CustomClassList, [woStoreClassName, woHumanReadable]));
  // Cleanup
  CustomClassList.Free();
  // Additional generic serialization test
  MemoGenericObjectList.Lines.Text := UTF8ToString(GenSerializationTest.DoSerializeTest());
end;
initialization

// TJSONSerializer.RegisterCustomSerializerFieldNames(TCustomClass, ['field1', 'field2'], ['RenamedField1', 'RenamedField2']);

#95 Re: mORMot 1 » Debug SyNode using VSCode » 2017-04-01 18:24:38

Great!

This opens a possibility to debug a SyNode based apps from IDE (great!)

Not only SyNode, vscode supports multi debug sessions, that means we should be able to debug client and server side in same time, from single IDE smile

but VSCode use some commands, not implemented in our FRDP implementation

Does this prevent breakpoints from working? (or i missed something, debugger skips my breakpoints smile).
I created test.js in addon folder and executed script from SyNode via require("./addon/test.js").

#96 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-03-31 22:42:19

mpv wrote:

Not sure about VSCODE, but you can use Firefox remote debugger. AFAIK map files should work.

I hope that should be way to debug js from vscode...
Found special extension that can successfully connect with spidermonkey debugger.
But breakpoints not work.

As i saw in firefox, spidermonkey app determines as firefox addon.
Extension page says that 3 types of addons are supported: addonSdk, webExtension and legacy.
Regarding of addon type, corresponding config file is required.
Which type of addon SyNode simulate for debugging?

#97 Re: mORMot 1 » ORM and Dynamic models » 2017-03-21 17:26:37

PostgreSQL is just great, and JSONB is really a killing feature.
We use PostgreSQL with some older projects, and it is clearly a killer DB - a real alternative to MSSQL or Oracle, for most usecases.

Awesome! That's just what i wanted to read)

Found awesome tool for PostgreSQL - http://pgmodeler.com.br/ (not just modeler).
Open source or 10$ for pre-compiled version.
Similar software for other DBMS is about 1000$ and higher with less functionality.

I like SQLite3 too, (i used it for small data with low IO), work like a charm.

#98 Re: mORMot 1 » ORM and Dynamic models » 2017-03-20 18:44:30

Thanks! I appreciate your opinion.

Sometimes it is impossible to completely avoid logical references between entities, that mean, some kind of transactions are required (at least on application level).
Pretty hard to provide freedom for users to customize data structures, without native transactions support from DBMS...

SQLite3 support only single writer and as stated on their site, SQLite cant replace big RDBMS like MSSQL or PostgreSQL.
I expect heavy load to database system from different threads, each with own connection (probably from pool).

PostgresSQL:
Since PostgreSQL manual promise advanced JSON support, it may be a solution that gives freedom and data consistency in same time.
https://www.postgresql.org/docs/9.6/sta … -json.html
https://www.postgresql.org/docs/current … -json.html

https://blog.2ndquadrant.com/jsonb-type … resql-9-4/
Conclusions

With the introduction of the JSONB type and the GIN indexes
using jsonb_path_ops operator class, PostgreSQL combines the elasticity of the JSON format at an amazing data access speed.

Today it is thus possible to store and process data in JSON format with high performance while enjoying the robustness and flexibility that PostgreSQL has habitually provided us with over the years.

http://blog.endpoint.com/2013/06/postgr … ation.html
On the other hand you could of course add a trigger checking the JSON, before saving it to database, to check the list of available fields. This way you could prevent adding new fields by the application.

MongoDB
I like how looks Mongo site, installer, folder structure, admin UI pretty stylish and handy, CLI access present too, (single process, while PostgreSQL use 5-6 processes to operate), many other advantages.
Only one limitation - no atomic batches, that feature was requested in 2010, hope, someday they add any kind of internal transactions that will work when requested (while in most cases it should not be used).
They really have such plans in JIRA tracker, but without dates.
I still suppose that for now, transactions may be implemented on application layer (when impossible to aggregate some data).

Do you have any negative experience with PostgreSQL?

#100 Re: mORMot 1 » ORM and Dynamic models » 2017-03-18 23:09:48

Also, interesting thing, for storing files they implemented GridFS, does mORMot support it?
-- regarding change log and current source file, answer is - no.

Do you suggest direct access to mongoDB via SynMongoDB (is it enough updated to work with mongoDB 3.4?)
or maybe use somehow with mORMot's ORM firedac connector (which not support GridFS too)?
or would be better for now to use node.js library with all new features like GridFS (from SpiderMonkey)?

Board footer

Powered by FluxBB