You are not logged in.
Hi,
I'm trying to consume mORMot WebSocket server with Javascript client.
Do you have an aproach to do this?
IMHO this is better aproach.
TSQLSampleRecord = class(TSQLRecord)
private
fQuestion: RawUTF8;
fName: RawUTF8;
fTime: TModTime;
public
function GetQuestion: RawUTF8;
published
property Time: TModTime read fTime write fTime;
property Name: RawUTF8 read fName write fName;
property Question: RawUTF8 read fQuestion write fQuestion;
end;
function TSQLSampleRecord.GetQuestion: RawUTF8;
begin
result := 'Msg: '+ fQuestion;
end;
It doesn't matter if you agree, quoted strings are not doubles and the JSON definition is clear about it.
Thanks
I am totally lost...
I put logstart method on example (09 - HttpApi web server) and is crashing as well...
Has someone the same problem?
So change your model to next one :
TR = packed record
errorId : Integer;
errorCode : String;
errorDescription : String;
status : String;
solution :
record
text : string;
url : string;
end;
cost : string;
ip : String;
createTime : Integer;
endTime : Integer;
solveCount : string;
end;
Correct your JSON :
s:= '{"errorId":0,"status":"ready","solution":{"text":"failed","url":"http:\/\/69.39.239.233\/101\/147884423179984.png"},"cost":0.001000,"ip":"95.143.198.250","createTime":1478844231,"endTime":1478844239,"solveCount":0}';
turrican
This is not JSON from my side. :\
and every thing works if change double to string,
but i think it must work without this change.
So, where is crashing? Or where is the fault of the program?
This is working to me...
Two things :
1.- You are passing in JSON a (cost) Double variable like a string, this will not be parsed. Pass it without quotes.
2.- You are passing in JSON a (solveCount) Integer variable like a string, this will not be parsed. Pass it without quotes.
Look at your JSON and adapt it.
Do you have some examples of the method THttpApiServer.LogStart() ? I reviewed the documentation multiple times and I think I am doing well.
Here is my server constructor :
constructor TCDIHTTPServer.Create;
begin
inherited Create(False);
//Unlimit connections
SetMaxConnections(0);
//Max queue lenght UNTIL 503 error
SetHTTPQueueLength(10000);
//We load config
if not FileExists('.\config.json') then CDIConfig := TCDIConfigLoader.NewConfig('.\config.json')
else CDIConfig := TCDIConfigLoader.LoadConfig('.\config.json');
//Add BASE URL load from config
Self.AddUrl('', CDIConfig.Port.ToString, False, CDIConfig.BindHostname, True);
//Init W3C Server Logging // Not working Crash HERE
LogStart('.\logs');
//Add CALLBACK
Self.OnRequest := Process;
{$IFNDEF DEBUG}
//Clone the HTTP.SYS Process if not debug mode, because DEBUGGER can't follow 256 threads well
Clone(256);
{$ENDIF}
end;
Hi,
I'm implementing your simple and fastest WinAPI HTTP.sys HTTPServer and works like a charm (better than all others servers I tested). Now when I want to start logging (client calls W3C) with the method LogStart(), thread crash.
HttpSetUrlGroupProperty failed: The parameter is incorrect (87)
I debugged and found this :
EHttpApiServer.RaiseOnError(hSetUrlGroupProperty,
Http.SetUrlGroupProperty(fUrlGroupID, HttpServerLoggingProperty,
@logInfo, SizeOf(logInfo)));
I think fUrlGroupID is not inizialized because INT64 value my debugger is poiting to random address memory.
How can I solve this?
I tested on Windows 10 and Windows Server 2012R2 with HTTPApi 2.0 with elevated permissions.
Hi,
Quite easy to achieve with mORMot. I did from client side but also can be implemented on the server side.
This is my implementation :
//Prepare paging
current_id := 0;
while continue do
begin
try
//Not continue if no rows fetched
continue := False;
//Try to fetch no more than 5000 rows
person := Person.CreateAndFillPrepare(CurrentContext.ORMServer, 'ID > ? limit 5000', [current_id]);
while person.FillOne do
begin
try
//Do something with person
finally
//Store the row id
current_id := person.ID;
continue := True;
end;
end;
finally
person.free;
end;
end;
end;
Hi JD,
Yes I am doing the same of you and works (but you need to be careful)... But the best way to do this (and more complex because mORMot needs a pivot table to establish relationship) is to use TSQLRecordMany implementation.
Hi Ab,
Yes of course, I'm doing it as background process with 500 row per batch update transaction.
Thanks for your suggestions.
Are you using static linked SQLite3 Library or external library? I am using the last SQLite3 library and a 7GB database no corruption.
SQLite3 to MSSQLServer
I'm suffering perfomance problems with SQLite3. Update batches are veeeeeryy slow on a 7GB table (no hardware issues or slow disk/network). I need to update more than a milion rows and it's painful.
Hi,
I need to clone a database with all the objects inside and I don't need synchronization. I want to change database engine to another but first I need to clone structure and data inside.
There is a TSQLRest clone method to another TSQLRest without using syncronization? Or what is the best way to do this with mORMot.
Thanks!
Hi Jars,
If you can match websocket interface with the user sesion at the server side you can achive this easily.
Hi,
There are many ways to achive this. Use server jobs with TSynBackgroundThreadProcess to send messages to each WebSocket registered client .
See here : http://synopse.info/files/html/api-1.18 … EADPROCESS
Thanks AB, I am going to implement your solution.
Hi,
I have a SQLite database with a 2 millions of rows in a Table. I can load this database with mORMot without problems and can insert and update rows.
But now, I need to iterate the table and I have memory problems.
The way I am iterating table is the next one :
begin
try
Log := TMailLog.CreateAndFillPrepare(CurrentContext.ORMServer, 'MailResume is null');
while log.FillOne do
begin
// do something
end;
finally
log.free;
end;
end;
Memory increasing until crash.
I don't know why FillOne method is wasting memory and make the process die.
Thank you Warley.
It's a good idea. We are going to do the implementation of dedicated services and test if it works.
Nice idea AB!
You need to do two transactions to achieve this. Because TSQLRecord.Add() needs to be commited to get the ID.
Thanks AOG for your quick response.
So... I am going to generate a Model for the Public area with the specified methods, and a private one for administration roles.
Sorry if this question is made already but I didn't find them. This gonna slow down things and redo most of my code...
Another question for the same context : How did you manage to split private methods and public methods? Have you used mORMot Auth?
No responses to this post? I think this post is very constructive for the framework and cannot be avoided.
How did you resolve this problem. I have the same problem. I need a row level security, 'CreateAndFillPrepare() with a 'Owner=?' that is i'm doing, but if user knows the way to use the REST API via Javascript for instance he can list all table without limitation. How can I manage this?
What do you want?
- Declare a constant for this record :
TPosData = packed record
PosNumber: Word;
UserId: Word;
PosFlags: set of TPosFlag;
end;
const
POSTDATA : TPosData = (PosNumber : 10; UserID : 11; PosFlags : [pfInService]);
Hi,
Currently I'm developing a simple application for multiple users and database sensitive data.
So, I am using TSQLRestServerAuthenticationDefault for security and it works at expected (no HTTP server security problems at all). But I have questions about tables and users...
Imagine the next scenario.
Table Books -> On this table I will R/W the authenticated user's books. So I put permissions to User group to manage this table, but this table also contains books of another users. If user (HTTP GET /books ) returns all the books of the table and the books of the other users I don't want to show them.
So what i have to do?
Aproach MVC -> Control GET/POST actions with on a server controllers. For example GET /bookscontroller (From here I can customize the searches) slower to develop.
Now i'm completly lost... I need to clarify concepts and ideas...
Somebody help me!
Hash your server plain password and compare the hash.
Hi,
Imagine the next scenario :
Pseudo Code :
type
DiskDatabase = TSQLRestServerDB;
MemDatabase = TSQLRestServerFullMemory;
TName = class(TSQLRecord)
private
fnam : RawUTF8;
published
property Nam : RawUTF8 read fnam write fnam;
end;
end;
Two database context with one SQLRecord class inside (Two Databases share the same model). No problems here.
Suppose this :
var
Nam : TName;
MemoryContext : TSQLRestServerFullMemory;
DiskContext : TSQLRestServerDB;
begin
//Create two context one from memory and another from disk file and search one TName record on Memory (we added one) database (WHERE Name = Turrican)
//... Context creation Skipped ...
Nam := TName.CreateAndFillPrepare(MemoryContext , 'Name=?', ['Turrican'])
if Nam.Fillone
begin
//We insert TName record to disk file database
DiskContext.AddOrUpdate(Nam);
end;
end;
DiskContext.AddOrUpdate(Nam); //Doesn't fail but doesn't insert or update the record.
The previous code tries to insert one record from a memory server to a physical database server. This isn't working...
Did you know what fails to make this approach of the previous pseudo-code?
Thanks!
There is any benchmark mORMot with Delphi compiler VS FPC Compiler?
Interface the class.
Thanks, sorry for the inconveniences.
Source : Delphi XE8 Using Generics
Case : RetrieveList() returns nil list. Access violation while iterate list.
Inside code : Investigating a little I see the next method :
function TSQLRest.RetrieveList<T>(const FormatSQLWhere: RawUTF8; const BoundsSQLWhere: array of const; const aCustomFieldsCSV: RawUTF8): TObjectList<T>;
innacessible due a not defined constant in the compiler conditional :
{$ifdef ISDELPHI2010}
So, the compiler calls another method instead
function RetrieveList(Table: TSQLRecordClass; const FieldNames, SQLWhere: string; const BoundsSQLWhere: array of const): TObjectList;
I don't know why this constant isn't defined in XE8...
Hi,
TObjectList<T>(TSQLRestServerDB.RetrieveList()) seems broken (or I don't know to invoke these) .
This code fails :
uses
System.SysUtils,
mormot,
mORMotSQLite3,
mORMotDB,
System.Generics.Collections,
synsqlite3static;
type
TUser = class(TSQLRecord)
private
fname: UTF8String;
fgroupid: TID;
published
property IDGroup: TID read fgroupid write fgroupid;
property Name: UTF8String read fname write fname;
end;
var
fSQLContext: TSQLRestServerDB;
userlist: TObjectList<TUser>;
user: TUser;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
fSQLContext:=TSQLRestServerDB.Create(TSQLModel.Create([TUser], 'root'),'prueba.db3');
fSQLContext.CreateMissingTables;
for user in TObjectList<TUser>(fSQLContext.RetrieveList(TUser, 'IDGroup=?', [4])) do
begin
writeln(user.Name);
end;
readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
This don't :
uses
System.SysUtils,
mormot,
mORMotSQLite3,
mORMotDB,
System.Contnrs,
synsqlite3static;
type
TUser = class(TSQLRecord)
private
fname: UTF8String;
fgroupid: TID;
published
property IDGroup: TID read fgroupid write fgroupid;
property Name: UTF8String read fname write fname;
end;
var
fSQLContext: TSQLRestServerDB;
user: Pointer;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
fSQLContext:=TSQLRestServerDB.Create(TSQLModel.Create([TUser], 'root'),'prueba.db3');
fSQLContext.CreateMissingTables;
for user in TObjectList(fSQLContext.RetrieveList(TUser, 'IDGroup=?', [4])) do
begin
writeln(TUser(user).Name);
end;
readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Hi,
I have read documentation and I cannot find a example using an easy way to do "Has Many" relationship.
I need to implement an aproach to "Lazy loading" of nested records relation in a table.
My aproach is the next, but I don't know if is a best way to do this :
uses
System.SysUtils,
mormot,
mORMotSQLite3,
mORMotDB,
System.Contnrs,
synsqlite3static;
type
TUser = class(TSQLRecord)
private
fname: UTF8String;
fgroupid: TID;
published
property IDGroup: TID read fgroupid write fgroupid;
property Name: UTF8String read fname write fname;
end;
TGroupe = class(TSQLRecord)
private
fclient: TSQLRestServerDB;
fname: UTF8String;
fusers: TObjectList;
public
function GetUsers(aClient: TSQLRestServerDB): TObjectList;
function AddUser(aClient: TSQLRestServerDB; aUser: TUser): TID;
published
property Name: UTF8String read fname write fname;
end;
function TGroupe.GetUsers(aClient: TSQLRestServerDB): TObjectList;
begin
if Assigned(fusers) then fusers.Free;
fusers:=aClient.RetrieveList(TUser, 'IDGroup=?', [ID]);
Result:=fusers;
end;
function TGroupe.AddUser(aClient: TSQLRestServerDB; aUser: TUser): TID;
begin
aUser.IDGroup:=ID;
Result:=aClient.AddOrUpdate(aUser);
end;
var
fSQLContext: TSQLRestServerDB;
x: Integer;
user: Pointer;
group: TGroupe;
groupid: TID;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
fSQLContext:=TSQLRestServerDB.Create(TSQLModel.Create([TUser, TGroupe], 'root'),'prueba.db3');
fSQLContext.CreateMissingTables;
Writeln('Create Group');
group:=TGroupe.Create;
group.Name:='Test Group';
Writeln('Storing group');
groupid:=fSQLContext.Add(group, True);
Writeln('Adding users to group');
for x := 0 to 100 do
begin
user:=TUser.Create;
TUser(user).Name:='Name ' + x.ToString;
writeln('Added user with id : ' + Int64(group.AddUser(fSQLContext,User)).ToString);
TUser(user).Free;
end;
Writeln('Users added, freeing group');
group.Free;
Writeln('Create group again and retrieve users');
group:=TGroupe.Create;
fSQLContext.Retrieve(groupid,group);
begin
for user in group.GetUsers(fSQLContext) do
begin
writeln(TUser(user).Name);
end;
end;
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Help me!
Hi,
I want to implement a simple TCP I/O protocol with TCrtSocket class.
Where i can find documentation or an example to implement TCrtSocket class?
Hi,
I have an ASP.NET REST WebAPI and I would like use mORMot Framework to consume these.
I can publish a public WebAPI with some models to make tests if you want.
Thanks ab,
I managed to do this with your help!
Thanks again!
Hi ab,
- You can call the TJSONSerializer.RegisterCollectionForJSON() method to register the collection type and its associated item class.
This works ok with serialization.
But here at unserialization crash :
Collection1:=TMyCollection.Create(TItem);
JSONFileToObject('.\file1.txt', Collection1, nil);
It's unable to parse JSON again.
My edited code :
program JSONSerializer;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Classes,
mORMOt,
SynCommons,
System.Generics.Collections;
type
TSubItem = class(TCollectionItem)
private
ftext: string;
published
property Text: string read ftext write ftext;
end;
TItem = class(TCollectionItem)
private
fname: string;
fsubitems: TCollection;
published
property Name: string read fname write fname;
property SubItems: TCollection read fsubitems write fsubitems;
public
destructor Destroy; override;
end;
TMyCollection = class(TCollection)
public
destructor Destroy; override;
function Serialize: string;
procedure Searlizetofile(tofile: string);
end;
destructor TMyCollection.Destroy;
var
Item: TCollectionItem;
begin
for Item in Self do Item.Free;
end;
function TMyCollection.Serialize: string;
begin
TJSONSerializer.RegisterCollectionForJSON(TMyCollection, TItem);
Result:=ObjectToJSON(Self);
end;
procedure TMyCollection.Searlizetofile(tofile: string);
begin
TJSONSerializer.RegisterCollectionForJSON(TMyCollection, TItem);
ObjectToJSONFile(Self,tofile);
end;
destructor TItem.Destroy;
begin
if Assigned(fsubitems) then SubItems.Free;
end;
var
Collection1: TMyCollection;
Item: TItem;
Subitem: TSubItem;
X: Integer;
Y: Integer;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
Writeln(GetTickCount64.ToString);
Collection1:=TMyCollection.Create(TItem);
for X := 1 to 3 do
begin
Item:=TItem(Collection1.Add);
Item.Name:='Iteration ' + X.ToString;
Item.SubItems:=TCollection.Create(TSubItem);
for Y:= 1 to 500 do
begin
Subitem:=TSubItem(Item.SubItems.Add);
Subitem.Text:='Subitem ' + Y.ToString;
end;
end;
Collection1.Searlizetofile('.\file1.txt');
Collection1.Free;
Collection1:=TMyCollection.Create(TItem);
JSONFileToObject('.\file1.txt', Collection1, nil);
Writeln(Collection1.Serialize);
Writeln(GetTickCount64.ToString);
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Thanks ab,
What kind of class did you recommend me to serialize/deserialize complex objects?
Hi,
I'm very new with mORMot Framework. I am looking for the best Delphi's ORM and I found this framework, a piece of wonderful code. Thanks for your great work.
Today I was playing with Object to JSON Serialization and went very well, but i try to deserialize the JSON again with bad result.
There is my testing code :
program JSONSerializer;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Classes,
mORMOt,
SynCommons,
System.Generics.Collections;
type
TMyCollection = class(TCollection)
public
destructor Destroy; override;
function Serialize: string;
procedure Searlizetofile(tofile: string);
end;
TSubItem = class(TCollectionItem)
private
ftext: string;
published
property Text: string read ftext write ftext;
end;
TItem = class(TCollectionItem)
private
fname: string;
fsubitems: TCollection;
published
property Name: string read fname write fname;
property SubItems: TCollection read fsubitems write fsubitems;
public
destructor Destroy; override;
end;
destructor TMyCollection.Destroy;
var
Item: TCollectionItem;
begin
for Item in Self do Item.Free;
end;
function TMyCollection.Serialize: string;
begin
TJSONSerializer.RegisterClassForJSON(Self.ClassType);
Result:=ObjectToJSON(Self);
end;
procedure TMyCollection.Searlizetofile(tofile: string);
begin
TJSONSerializer.RegisterClassForJSON(Self.ClassType);
ObjectToJSONFile(Self,tofile);
end;
destructor TItem.Destroy;
begin
if Assigned(fsubitems) then SubItems.Free;
end;
var
Collection1: TMyCollection;
Item: TItem;
Subitem: TSubItem;
X: Integer;
Y: Integer;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
Writeln(GetTickCount64.ToString);
Collection1:=TMyCollection.Create(TItem);
for X := 1 to 3 do
begin
Item:=TItem(Collection1.Add);
Item.Name:='Iteration ' + X.ToString;
Item.SubItems:=TCollection.Create(TSubItem);
for Y:= 1 to 500 do
begin
Subitem:=TSubItem(Item.SubItems.Add);
Subitem.Text:='Subitem ' + Y.ToString;
end;
end;
Collection1.Searlizetofile('.\file1.txt');
Collection1.Free;
Collection1:=TMyCollection.Create(TItem);
JSONFileToObject('.\file1.txt', Collection1, nil);
Writeln(Collection1.Serialize);
Writeln(GetTickCount64.ToString);
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Serialization does all ok.
What i'm doing wrong?
Thanks!
Hi,
I make a powershell script to download and uncompress mORMot last build automatically :
# Update MORMOT Nightly
Add-Type -assembly "System.IO.Compression.FileSystem"
$mormotURL = "[url]http://synopse.info/files/mORMotNightlyBuild.zip[/url]";
$directory = "YOUR_MORMOTPATH"
$filename = "mORMotNightlyBuild.zip";
if (![System.IO.Directory]::Exists($directory)){
try {
[System.IO.Directory]::CreateDirectory($directory)
}
catch [Exception] {
Write-Host $_.Exception.Message;
}
}
try{
wget $mormotURL -OutFile $directory$filename;
[System.IO.Compression.zipfile]::ExtractToDirectory($directory + $filename, $directory)
}
catch [Exception] {
Write-Host $_.Exception.Message;
}