You are not logged in.
I prefer that when downloading mORMot all things together but as I cannot update the "ThirdParty\EMartin" folder maybe I should use github. I'll put in this thread when I have created the distribution in github.
Best regards.
That's the thing - you can clone the mORMot repository, and upload your changes to your repository. Then, by performing a pull request, you make things easier for @ab to merge your changes.
Also, it means that other users of the mORMot repository can pull your changes before they get merged into the main repository.
And you get your own set of goodies: commit history, submit issues, etc.
For example, I made a fix to your code in my own repository and then requested a pull: https://github.com/synopse/mORMot/pull/36
It's way, way better than zip archives in shared folders.
Esteban,
Why don't you clone the mORMot github repo and push your changes to it? It would be much more easier to get your patches this way.
Regards,
Leo
Well, I'll be. Calling CreateMissingTables did the trick. I still cannot find the documentation part where this is stated, and I don't understand what's going on. Can somebody explain it to me? I did some debugging but couldn't wrap my head around it.
Calling CreateMissingTables, as documented, may help.
Really? Where in the documentation? I thought this method would create missing tables in the database, which I really don't want to do. I just want to retrieve records from the existing table...
By the way, some log info:
20170406 02553523 + mORMotSQLite3.TSQLRestServerDB(025CF020).URI(GET root/Factura/10810 inlen=0)
20170406 02553714 EXC ESQLite3Exception {"ErrorCode":1,"SQLite3ErrorCode":"secERROR","Message":"Error SQLITE_ERROR (1) [SELECT RowID,Rut,Folio FROM Factura WHERE RowID=?;] using 3.18.0 - no such table: Factura, extended_errcode=1"} at 00624CE2 stack trace API 0054376B 00543794 00406F60
20170406 02553714 res {"TSQLDatabase(026D3488)":{"FileName":":memory:","IsMemory":true,"UseCache":true,"TransactionActive":false,"BusyTimeout":0,"CacheSize":-2000,"PageSize":4096,"PageCount":0,"FileSize":0,"WALMode":false,"Synchronous":"smFull","LockingMode":"lmNormal","MemoryMappedMB":0,"user_version":0,"OpenV2Flags":6,"BackupBackgroundInProcess":false,"BackupBackgroundLastTime":"","BackupBackgroundLastFileName":"","SQLite3Library":{"TSQLite3LibraryStatic(0260D1A0)":{"Version":"3.18.0 with internal MM"}}}}
20170406 02553714 debug mORMotSQLite3.TSQLRestServerDB(025CF020) TSQLRestRoutingREST.Error: { "errorCode":404, "errorText":"Not Found" }
20170406 02553714 srvr mORMotSQLite3.TSQLRestServerDB(025CF020) GET root/Factura ORM-Get -> 404 with outlen=47 in 1864500 us
20170406 02553714 - 01.864.506I see that it is effectively trying to do a query against some SQLite database, and it is not using my MySQL database nor mappings.
I'm doing some experiments with using MySQL and FireDAC. My code is as follows (simple form with a single button named btnConnect):
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
btnConnect: TButton;
procedure btnConnectClick(Sender: TObject);
end;
var
Form1: TForm1;
implementation
uses SynCommons, mORMot, mORMotDB, mORMotSQLite3, SynDBFireDAC, SynDB,
uADPhysMySQL, SynSQLite3Static;
type
TSQLRecordFactura = class(TSQLRecord)
private
FRut: Integer;
FFolio: Integer;
published
property Rut: Integer read FRut write FRut;
property Folio: Integer read FFolio write FFolio;
end;
{$R *.dfm}
procedure TForm1.btnConnectClick(Sender: TObject);
var
props: TSQLDBFireDACConnectionProperties;
aModel: TSQLModel;
aFactura: TSQLRecordFactura;
aRestServer: TSQLRestServerDb;
aClient: TSQLRestClientDb;
begin
TADPhysMySQLDriverLink.Create(Application).VendorLib :=
'D:\Projects\test\Debug\Win32\libmysql.dll';
props := TSQLDBFireDACConnectionProperties.Create('MySQL?localhost',
'testdb', 'usr', 'pwd');
try
aModel := TSQLModel.Create([TSQLRecordFactura], 'root');
try
VirtualTableExternalRegister(aModel, TSQLRecordFactura, props,
'facturas');
aModel.props[TSQLRecordFactura].ExternalDB.MapField('ID', 'factura_id');
aModel.props[TSQLRecordFactura].ExternalDB.MapField('Rut',
'empresas_empresa_rut');
aModel.props[TSQLRecordFactura].ExternalDB.MapField('Folio',
'factura_folio');
aRestServer := TSQLRestServerDb.Create(aModel, ':memory:', false);
try
aClient := TSQLRestClientDb.Create(aRestServer);
try
aFactura := TSQLRecordFactura.Create(aClient, 10810);
ShowMessage(Format('Factura: %d', [aFactura.Rut]));
finally
aClient.Free;
end;
finally
aRestServer.Free;
end;
finally
aModel.Free;
end;
finally
props.Free;
end;
end;
end.When trying to retrieve my object (aFactura := TSQLRecordFactura.Create(aClient, 10810);) I get the following exception, but the execution continues and the message gets shown with the text "Factura: 0":
Project Project1.exe raised exception class ESQLite3Exception with message 'Error SQLITE_ERROR (1) [SELECT RowID,Rut,Folio FROM Factura WHERE RowID=?;] using 3.18.0 - no such table: Factura, extended_errcode=1'.
Debugging I see that the connection seems to be working ok (dMySQL, and the mapping fields seem to be ok.) Also, if I access the connection object directly and execute queries against the database, it works, so it is connected to the actual MySQL database.
Any clues?
TSynRestDataset is not experimental, we will release it in production in the next weeks. The TSynRestDataset born into the need the migration three tier legacy software (RemObjects) to more stable application server, I did rewrite all legacy code for total use of mORMot benefits, and in the middle parallel running partial up to total migration.
Good to know. Hope they get in the main distribution soon. In the meantime, here's a pull request for some small fixes: https://github.com/synopse/mORMot/pull/36
It depends on what you'll do and how. If you only want to have a have a service oriented approach (call function from your client, pass some params and get results) two classes are needed, for example TSQLHttpServer and TSQLRestServerFullMemory. Take a look at docs for more details and in samples dir.
That's part of it, most likely updates and inserts.
Alternative (to classic DBGrids) is to use TDrawGrid and TSQLTableToGrid, it's quite fast and on paar with TDBGrid with features.
Yeah, but I have an application that relies heavily on DevExpress grids and components. Those are really hard to duplicate.
This has been discussed elsewhere, but this is to check if this migration strategy is possible.
Old and big database applications written in Delphi, written many years ago, usually have the same problems:
- many different dataset scattered across units
- lots of DB aware components depending on an active dataset
- many direct updates in-place using two-way datasets
- lot of direct database oprations (inserts, updated using SQL code)
- stored procedures
- mixed UI and database logic
In most cases, migrating such an application to mORMot is simply not an option. Business reasons vary, but most likely, it implies a total rewrite, and that's simply a big no-no.
The strategy: create a "fake" mORMot server inside the running executable. Make it work alongside the current logic.
In my head, this should be something like this:
- Add a new unit
- Create a "mORMot server" (I still have no idea what this is)
- Add a procedure to update certain existing object (something small, just to test if it works) using some form of direct database access ("update obj where ...")
- Add, during application startup, code to make this "mORMot server" start
- Add (or better yet, replace an existing functionality) code that instantiates the client part (TSQLRestClient using direct access?) and calls the new server method the mORMot way.
This leaves out the most complicated part: existing grids that use TDataSet objects. For this, one could use the (experimental?) TSynRestDataSet by Esteban Martin. The approach would be the same: replace existing datasets with TSynRestDataSet objects, and move the query logic to the server.
Wash, rinse, and repeat, until you have ported all your existing DB code to Restful code.
At this point, all is left is to split the application between the server and client part, and figure a way to migrate existing clients.
What do you guys think of such a plan?
Yeah, no, that's not useful when you want to migrate an existing application.
I think the missing piece for more adoption of mORMot is a comprehensive articles series (or even a book) on migrating an old-style data-aware and datamodule based application to mORMot: tips, best practices, strategy, etc.
Right now, it's an all-or-nothing proposal which is not an option for large, established codebases.
I've seen, for example, that the Fish Facts demo was indeed ported to mORMot:
https://synopse.info/forum/viewtopic.php?id=1236
But to me, this is a missing opportunity. What about converting the actual Fish Facts demo (or something very similar to it) to mORMot, in-place, and documenting each step in a github repository? That would be excellent.
(I know, I know, I'm asking for free stuff. This is just an idea.)
Which docxtolatex program, there are several different ones? I'm using a Mac version of Word, some conversion programs try to use OLE and I can't use that. I also tried pandoc but it seems to generate many many errors in Latex, I gave up on it.
E
My bad, the program is actually named docx2tex: http://docx2tex.codeplex.com/ - it doesn't use any OLE magic.
Here's my $0.02: don't use Microsoft Word for writing a book. It's a waste of time.
(Before counting me off as some Microsoft basher, let me assure you that Excel and Word are my two favorites pieces of software of all time, period. I truly think they are a monument to human ingenuity.)
To write a book, the absolute best way is to use LaTeX. Easy to learn, fun, and, the best of all, it's plain text, so if you throw your favorite VCS to the mix (which is git, of course, right?) you get all you need to create a stunningly well designed book.
There are ready-made classes to create your book. For example, I took a sample chapter provided earlier in this thread, opened it with Word, saved as .docx, then used docxtolatex to convert the file. After some _very_ minor editing, got the following:
https://www.docdroid.net/7kU6ZQf/denormalize.pdf.html
Please have in mind that I didn't do much other than a few touches here and there. The design is all provided by this LaTeX class: https://github.com/Tufte-LaTeX
If you want, I can edit and convert your book for you. It's no big deal.
After some time bashing at it - my object is called "TFactura." I'm using AnyDAC instead of FireDAC and it still works. This is not using a class var but an instance variable. Can anybody confirm which way is better, and why?
procedure StartServer(aDbURI: RawUTF8);
var
aDbConnection: TSQLDBConnectionProperties;
aStockServer: TSQLRestServerFullMemory;
aHTTPServer: TSQLHttpServer;
begin
aDbConnection := TSQLDBFireDACConnectionProperties.Create(aDbURI, 'mydb',
'myusr', 'mypasswd');
aStockServer := TSQLRestServerFullMemory.CreateWithOwnModel([], False,
DEFAULT_SERVER_ROOT);
try
aStockServer.ServiceDefine(TFacturaQuery.Create(aDbConnection),
[IFacturaQuery]);
aHTTPServer := TSQLHttpServer.Create(DEFAULT_HTTP_PORT, [aStockServer], '+',
useHttpSocket);
try
aHTTPServer.AccessControlAllowOrigin := '*';
// allow cross-site AJAX queries
writeln('Background server is running.'#10);
writeln('Cross-Platform wrappers are available at ', DEFAULT_HTTP_PORT,
'/', DEFAULT_SERVER_ROOT);
write('Press [Enter] to close the server.');
readln;
finally
aHTTPServer.Free;
end;
finally
aStockServer.Free;
end;
end;Thank you!
It works, but I don't know if I'm understanding this correctly:
private
class var fDbConnection: TSQLDBConnectionProperties;
public
class procedure Init(const aProps: TSQLDBConnectionProperties);
constructor Create(const aProps: TSQLDBConnectionProperties); overload;How does this `class var` variable works in the context of the http server? Is it thread safe?
It doesn't matter if you agree, quoted strings are not doubles and the JSON definition is clear about it. It is up to you to use something like TryStrToFloat() with the given values to get your actual value. Perhaps use a secondary getter method or a intermediate class?
Thank you, I have modified my test. But I don't even get to the point the connection to the database is made; the HTTP request never get to the exposed method (it's always "400", "Bad Request".) I don't even know how to debug it, i.e., where to put a breakpoint.
I've been trying to make this work:
https://tamingthemormot.wordpress.com/2 … databases/
I managed to get it compiled (after a few changes) and kind of working. I only get error 400, bad request, for any requests I make.
Can anybody make this work with an up-to-date mORMot version and share the modifications needed?
Because that's not what I need... anyways, do you see something wrong in the code I'm using for PDF? Any missing calls, ordering, flags?
I'm trying to take a screenshot to PDF and it *almost* works. Saving a screenshot to a metafile works great (example code from Uwe Raabe: https://gist.github.com/UweRaabe/92021a … a0da28fbd):
procedure TForm77.Button1Click(Sender: TObject);
var
cnv: TMetafileCanvas;
emf: TMetafile;
notused: HWND;
begin
emf := TMetafile.Create;
try
emf.SetSize(ClientWidth, ClientHeight);
cnv := TMetafileCanvas.Create(emf, GetDeviceContext(notused));
try
Self.PaintTo(cnv, 0, 0);
finally
cnv.Free;
end;
emf.SaveToFile('c:\temp\Test.emf');
finally
emf.Free;
end;
end;When I try to do something similar but drawing to a PDF, I got different results:
procedure ScreenshotPDF(const Form: TForm);
var
Stream: TFileStream;
pdfObj: TPdfDocumentGDI;
begin
pdfObj := TPdfDocumentGDI.Create(false, 0, True, nil);
try
Stream := TFileStream.Create('c:\temp\Test.pdf', fmCreate);
try
pdfObj.SaveToStreamDirectBegin(Stream);
pdfObj.AddPage;
Form.PaintTo(pdfObj.VCLCanvas, 0, 0);
pdfObj.SaveToStreamDirectPageFlush;
pdfObj.SaveToStreamDirectEnd;
finally
Stream.Free;
end;
finally
pdfObj.Free;
end;
end;A zip file with both the resulting EMF and PDF files can be downloaded from here: http://www.filedropper.com/test_30
Is my code correct? Can it be improved?
I would love to help. I think this is needed:
- Remove the current properties completely (this is a breaking change but I think it is necessary to avoid unexpected behavior from the engine)
- Add a new "Orientation" property (the Printers unit already contains a TPrinterOrientation = (poPortrait, poLandscape) - we can use it or define our own type)
- Add the logic to print sideways (rotate the image 90º counter clockwise) when Orientation = poLandscape.
Of these, the first and second bullets are trivial, minor changes. However, I'm not in the same ballpark when comes to the third change - sure, it is really easy to get some blit algorithm and make an image rotate, but on the PDF side I got nothing (I stared at the PDF reference for a while but it looks Polish to me.) If you can provide me some leads to start digging in the code I can give it a try.
Regards,
Leonardo Herrera
Hello,
I've been using this marvelous library for a while but just today found the need to export a document that is wider than tall. This has proven a nuisance, because of what I think is a bug.
Landscape, in printing, means that your picture will be printed sideways. In SynPDF, it just means that the paper width is larger than its height (and SynPDF will actively try to "correct" it for you, making your page tall anyways.)
I think (from a distance, since I'm not expert in SynPDF nor PDF) that this landscape property should be removed entirely and replaced by a true Orientation property, which dictates if the contents will be rendered sideways (I think I've seen PDF docs with intermixed landscape and portrait pages: when displayed on the screen, you'll see wider pages being rotated so they can be read, but when printed they print correctly, sideways).
I've removed all the landscape code from my own copy of SynPDF and now I can export wide pages without problems.
Cheers,
Using mercurial on my side - in another thread Arnaud mentioned that he is considering moving from Fossil but he has no time to look into it yet (sorry if I'm paraphrasing here)
I'm willing to, but I haven't got around understanding Fossil... ![]()
I agree there is always lot of work to be done in a project like this, but attracting developers is one of the most difficult yet important tasks for any open source project. So any steps in that direction should be a priority. I think this is one of the most important Delphi projects around, and it should have the attention it deserves. So, even if I agree that TDataSet support is important because it would make migrating existing projects easier (and I'm personally interested in it) I still feel that having the project in a more popular infrastructure would be of great benefit in the long run.
Anyways, keep up the good work!
On the topic of source control management, I've never heard of Fossil before reading about it here. I think this project could gain much more traction if you moved to a more popular source control program. I know you are used to Fossil and its conveniences, but nowadays Git, for example, can have just as much (if not more) functionality. Github may be a good place to host.
Personally, I don't want to install Yet Another Source Control thing on my PC for just this project (I'm using zip packages to download your code.)
I think your choice of source control system is actually harming the spread of this awesome project.
I downloaded the latest version of the source code.
By the way, I keep getting a "403 Forbidden" trying to download Synopse.inc:
http://synopse.info/fossil/raw/Synopse. … f20dd1a110
I managed to fix this issue - first I changed the background color for the text element, and sure, the text was white. Since it was already set as black, I slightly altered it (changed to something like #010101) and the text appeared.
How can I produce a EMF file from my file?
I'm having this issue when exporting a report using FastReport: one of the fields (usually the first one) is rendered the same color as the page (usually white.) It's still there, thought. What can be a possible cause for this? I'm creating the file as PDF/A with embedded fonts.
Arnaud,
Your English is fine. While your document is frankly impressive, I'm quite sure that a "Migrate from client-server to N-tier in 10 steps" is something that would benefit this (and probably other) projects enormously.
What I envision is a document that tells me how to refactor my application without changing the underlying technology first, then switching backends. I know this is easier said than done, but it's the contention point I have to port my application (I need to have a running app at all times.)
Regards,
Leo
Hello,
Is it possible to have a good recipe or tutorial on moving a pretty standard Delphi Client-Server application to this framework? I think many Delphi developers (me included) would benefit of having a guide teaching them how to architect their code and, if possible, to port their old applications to this framework.
I know it is not an easy topic. I've been asking this to RemObjects for years (I bought a license but never got around to port my application to use DA.)
Regards,
Leonardo Herrera
Hello,
Tried this unit but I didn't got the complete document.
I'm expecting this: http://monserratinformatica.cl/nc62-good.pdf
But instead, I'm getting this: http://monserratinformatica.cl/nc62.pdf
(never mind the small text differences, those are expected.)
Any idea on what may be happening?