#51 Re: mORMot 1 » how change table data without using sql? » 2012-01-25 13:14:40

No, it is not yet official possible (only if you change source code), but it is on roadmap. See the last valid point about BriefCase model.

#52 Re: mORMot 1 » SQLite3Service.TService (windows service) does not work as expected » 2012-01-19 00:59:58

Hi, Arnaud.

I did small changes to the SQLite3Service unit (TService).
I only added common property ControlHandler for setting the callback handler and some minor changes to fit it properly in code.
If the handler is not set from "outside" then your hack is used.
So this "outside discipline" is some how similar to the SvcMgr.TService approach.
The difference is that our TService does not force you to subclassing (no abstract procedure), it could be easily used in composition scenario too (I moved DoCtrlHandle to the public visibility for that reason).
Anyway I think that this approach is good (it's just added choice, we lose nothing), even if the asm (automatic router smile) code would be corrected.
This always works, because is just basic Pascal smile.

I sent you code via mail (I don't want to bloat the forum smile).

#53 Re: mORMot 1 » SQLite3Service.TService (windows service) does not work as expected » 2012-01-17 12:51:43

I'm not fan of bloated implementations either.
Your TService is some kind well wrapped direct Win API solution.
I'll definitely take your class as base (at first my implementation was as composition, now sub-classing fits better) and only change that callback portion to "manual" Pascal way (I do not understand enough of assembler to correct your "automatic" way smile).

#54 mORMot 1 » SQLite3Service.TService (windows service) does not work as expected » 2012-01-17 10:49:30

Leander007
Replies: 5

or am I missing something?

Arnaud, you already explained usage of TService and somebody (Mick) already comment it, that some features does not work.

I'll be more precise:
You are using assembler tricks to call method of class instance instead of plain (stdcall) procedure :

Srv.FStatusHandle := RegisterServiceCtrlHandler(pointer(Srv.fSName), Srv.FJumper);

And this is just not working in my scenario (Delphi 2009, Vista as target). It looks that this jumper cannot run at all from service controller.

If I run this "jumper code" manually (from my code), then it works:

type
  TCtrlHandler = procedure(CtrlCode: DWord); stdcall;
(...)
  TCtrlHandler(Srv.FJumper)(SERVICE_STOPPED);

If I use plain (stdcall) procedure, then it works from service controller too:

procedure MyDoCtrlHandle(Code: DWORD); stdcall;
begin
  (...)
end;
(...)
Srv.FStatusHandle := RegisterServiceCtrlHandler(pointer(Srv.fSName), Addr(MyDoCtrlHandle));

I really don't have a clue what is wrong, maybe is just simpler to have some "safe fallback" similar to SvcMgr.TService:

TServiceController = procedure(CtrlCode: DWord); stdcall;
(...)
TService = class(TDataModule)
(...)
function GetServiceController: TServiceController; virtual; abstract;

This is less intuitive, but is more Pascal way smile. I don't know if this problem is easy solvable for you or is it better to add some kind of safe fallback too.

#55 Re: mORMot 1 » Basic help » 2012-01-09 11:20:46

Some suggestions from my personal experience:

1. It won't be easy trip if you want to use the framework "to the end"
2. As already told, framework is not RAD (forget quick designing) but SOA oriented (benefits come later). This is nice explained in SAD documentation.
3. For all-in-one applications with "tons" of GUI element, you rather stick with some RAD solution based on TDataSet. You have many (free and payable) out there, just search with google. You can do this kind of application with mORMot  too, but believe me, you will be slower. Except if you use mORMot user interface generation and that fits your needs. Mine has been totally different, so I have done it, all by myself (takes time). If you are using (and used to) some advanced grid, this you'll be missing most.
4. Think in objects, (almost) forget SQL. If you are used of tons of hand written SQL sentences you can used them in mORMot too, but this is not the right way and you are mixing two approaches often prematurely. Sometimes you must mixed them if you want some benefits from database (if you use only one type of persistence) which are not included in framework at same level.
5. For multi-tier or huge and complex applications the SOA way is the right way. So here the mORMot wins or better say it, is worth all effort invested it.

#56 Re: mORMot 1 » Basic help » 2012-01-09 10:43:01

1. Entry point is here http://synopse.info/fossil/wiki?name=SQLite3+Framework.
2. This follows you to the download page.
3. Download and Read SAD documentation (ok, you already did)
4. Download official code at http://synopse.info/files/SynopseSQLite3.zip or bleeding edge code from the source control web interface (read about it here)
5. Look at examples in ...\Synopse\SQLite3\Samples\
6. Investigate the code (and comments in code) "playing" with examples or with your "samples"
7. Search first in this forum, because many questions was already asked, then ask...

Iterate all of the points again and again smile.

#57 Re: mORMot 1 » Fix the comments to be in DocType format with /// prefix » 2012-01-07 23:30:16

You can see, that this was discussed already too smile.
Regarding xmldoc starts from here.

#58 Re: mORMot 1 » Why TSQLRequest = object? This is arcane. » 2012-01-07 23:25:47

This was discussed at least in two topics:
First in favor to object.
And second, yes there are possible problems with them too.

#59 Re: mORMot 1 » TSQLTable get fields name » 2012-01-06 23:20:24

Small example:
First one (Get*) returns name of column (fetching first 0 indexed row, data is from 1 on).
Second one first un-camels name and potentially gets localized version of that text, if you use SQLite3i18n unit.

  var 
   table: TSQLTable;
   i: integer;

   (...)
   for i := 0 to table.FieldCount - 1 do
   begin
       writeln('col '+IntToStr(i)+' has name '+string(table.GetS(0,i))); 
       writeln('col '+IntToStr(i)+' has caption '+table.GetCaption(0,i)); 
   end;
   (...)        

#61 mORMot 1 » Error calling TSQLRecord.FillRow with non existing properties » 2012-01-05 22:55:05

Leander007
Replies: 2

Hi, Arnaud.

Since 20.7.2011 I didn't refreshed local copy of mORMot framework from your fossil repository, until today.
I got some unexpected behavior on my "test polygon", when calling FillRow after CreateAndFillPrepare. Inner TSQLTable is that way already fetched, so I want to reuse cached data for update. I'm doing something based on TSQLTableToGrid, so I need this "more general" approach versus ORM way.

_masterRec: TSQLRecord;
(...)
_masterRec.FillRow(nodeData^.RowNum); //cause of error: ID was set to 0
_masterRec.SetFieldValue('Acknowledged', '1');
_client.Update(_masterRec); //error: this line then fails
(...)

The reason why the upper code does not work is in next code:
unit SQLite3Commons, line 11262

procedure TSQLRecordFill.Fill(aTableRow: PPUtf8CharArray);
var f: integer;
begin
  if (self=nil) or (aTableRow=nil) then
    exit;
  for f := 0 to fTableMapCount-1 do
    with fTableMap[f] do
      if DestField=nil then
        Dest.ID := GetInteger(aTableRow[TableIndex]) else
        DestField^.SetValue(Dest,aTableRow[TableIndex]);
end;

In database table are some columns which do not map to the published properties of my TSQLRecord descendant and they evaluate to the fTableMap[f].DestField=nil too, what is setting Dest.ID to false 0 value.

I changed condition:

if DestField=nil then

to the (if the ID is set, don't set it any more):

if (DestField=nil) and (Dest.ID = 0) then

Update:
This is not ok, because if I call several times in a roll FillRow on same TSQLRecord, then the ID is not fetched.
Some other, better identification is needed (f=0 or first occurrence of DestField=nil) to distinguish between RowID/ID field and "not mapped" fields, which (I think so) always come after ID field. For me it works either solution, but you will now what is best in several cases which may appear.

#62 PDF Engine » Proposition: Avoding "hardcoded" behavior for TGDIPages... » 2011-09-26 10:24:08

Leander007
Replies: 1

Hello Arnaud.

In my application I'm using TGDIPages for report generation and I noticed that some procedures have fixed behavior (they are not "obeying" custom settings; the work via SaveLayout -> RestoreSavedLayout).
I know that I can easily derive my own class from it and provide different behavior. But it would be more proper if this is done already at TGDIPages.

E.g. DrawTitle and DrawTextAcrossCols have fixed behavior.
DrawTitle has fixed rule for Font size and alignment (forcing left align) via TitleFlags.
DrawTextAcrossCols is (recently) forcing via PrintColumnHeaders no word wrapping (WordWrapLeftCols := false).

I think that these procedures should by default be customizable via global settings using save\restore layout and the fixed one (with fixed layout) should be renamed if really needed . If this is not an option, because of existing code, then at least there should be provided custom alternatives (e.g. TitleFlags should be writable property or procedures with custom suffix should be introduced -> DrawTitleCustom).

This is just proposition smile.

#63 Re: PDF Engine » Invalid output of TGDIPages using PDF Export and WordWrapLeftCols » 2011-09-26 09:07:17

Thanks to you for finding the real issue smile.
Now works as expected.

#64 Re: mORMot 1 » please help! » 2011-09-23 12:28:52

I already showed you with previous post.

What you are naming Database is named in my case as rest.

So lets repeat and complete with your variables smile:

var
 TableRole: TSQLTable;
 sql: string;
begin
  sql := StringToUTF8('your join sql here');
  TableRole := TSQLTableDB.Create(Database,[TSQLUserRoles, TSQLUserRole], sql, false);
  TSQLTableToGrid.Create(dgRoles, TableRole, Database);
end;

That is all. You must first read the SAD documentation and take MainDemo as first reference and Arnaud code (and comments) as MASTER REFERENCE !

#65 Re: PDF Engine » Invalid output of TGDIPages using PDF Export and WordWrapLeftCols » 2011-09-23 12:17:10

It is not the stretch part, because plain draw fails too:

BMP.Canvas.Draw(0,0, TMetaFile(Pages.Objects[i]));

So, for now only your DrawEmfGdip does the job, when you wish to print as it is shown on the screen!

#66 Re: PDF Engine » Invalid output of TGDIPages using PDF Export and WordWrapLeftCols » 2011-09-23 11:16:54

This is somehow related to the scaling of the "elements", because in BMP (print as bitmap) case
following code works well (copied from PaintPreview, case for GDI+):

rec := Rect(0,0,Bmp.Width,Bmp.Height);
if not ForceNoAntiAliased then
   DrawEmfGdip(BMP.Canvas.Handle,TMetaFile(Pages.Objects[i]), rec,ForceInternalAntiAliased);

and this does not (original code for ForcePrintAsBitmap in TGDIPages.PrintPages function), which does some stretching (scaling)  - I'm guessing from the name of procedure:

BMP.Canvas.StretchDraw(Rect(0,0,Bmp.Width,Bmp.Height), TMetaFile(Pages.Objects[i]));

and with pdf export must be same issue when using "metafile to pdf commands".

Hopefully this narrow the problem down...
For me this solution becomes from "show stopper" to "accepted workaround", because at least I need working printing (pdf export is fine feature, but not the requirement in my application).

#67 Re: PDF Engine » Invalid output of TGDIPages using PDF Export and WordWrapLeftCols » 2011-09-23 09:45:20

I have been investigating what is wrong in output pdf. First I converted output pdf to plain pdf commands (/FlateDecode).
Then I moved the "invisible" text (Td command) via Y axis for some amount and the content was shown.
So obviously the content is overwritten via some "pdf object".

I thought that pdf content is wrongly generated, but then I used ForcePrintAsBitmap of TGDIPages and result was the same.
So the problem is already at TMetafile level.


Why is content rendered correctly in preview form, but not when flushed to the BMP via ForcePrintAsBitmap?
Flushing of PreviewSurfaceBitmap is obviously ok.

Arnaud do you have a clue what is going on?

#68 PDF Engine » Invalid output of TGDIPages using PDF Export and WordWrapLeftCols » 2011-09-20 22:39:30

Leander007
Replies: 6

Hello Arnaud.

I found some invalid behavior with PDF export when WordWrapLeftCols is used. Content rendered with ShowPreviewForm is correctly shown on the screen, but when exporting report to the pdf is done, all texts which are short (word wrapping is not needed) following the first column which needs word wrapping are "INVISIBLE" (they are there, if you try to copy data, but not visible ?!).

This code snippet will reproduce the issue:

(...)
    WordWrapLeftCols := true;
    AddColumns([10,22,22,22,22]);
    AddColumnHeaders(['#','Two','Three','4','5'],true,true);
    for i := 1 to 50 do
      DrawTextAcrossCols([IntToStr(i),'Column '+IntToStr(i),
      'This is some big text which must be justified on multiple lines. Text "four" and "five" will be invisible in pdf...',
      'four','five']);
(...)

As it's already written only short texts ('four', 'five') following at least one long text will be invisible in PDF output.

Please, could you look at it.
You will find the causing problem faster then me.

#69 Re: mORMot 1 » please help! » 2011-09-13 12:20:30

It is very simple if you use TSQLTable directly e.g.:

  (...)
  sql := StringToUTF8('select * from T1 left join T2 on ...');
  table := SQLite3.TSQLTableDB.Create(rest,[TSQLT1, TSQLT2], sql, false);
(...)

#70 Re: mORMot 1 » Compact the database » 2011-09-01 00:12:07

I think you could do it simply via direct call of EngineExecute('VACUUM') of TSQLRest instance.

But you should read first about VACUUM command, that you call it at proper time, synchronized on server side.

#71 Re: mORMot 1 » Access violation when running MainDemo with D2009 » 2011-07-26 09:50:30

This is somehow related to the Delphi 2009 object (keyword) issue .

You can see that "TP is an object" which is inherited from other object. So the quick solution (for now) is that you copy all fields from source object to the target object and the demo works then in Delphi 2009 too.

#72 Re: mORMot 1 » Internationalization » 2011-07-20 11:08:39

You have one small lapsus (which is show stopper smile) in SQLite3i18n at line 1904:

      text := ppi^.GetGenericStringValue(comp);

should be

      old := ppi^.GetGenericStringValue(comp);

#73 mORMot 1 » Internationalization » 2011-06-30 14:26:04

Leander007
Replies: 3

In unit SQLite3i18n at procedure ExtractAllResources is possible stack overflow!

More precisely this happens at iterative procedure AddClass when you use e.g. "Master/Detail" approach with TSQLRecordMany, which contains as  property "Source" object which contains this TSQLRecordMany...

My quick solution is that I check which classes were already iterated:

procedure ExtractAllResources(const EnumTypeInfo: array of pointer;
  const Objects: array of TObject; const Records: array of TClass;
  const CustomCaptions: array of WinAnsiString);
(...)
var F: Text;
    (...)
    clist: array of TClass;
    ccount: integer;

  procedure AddClass(C: TClass);
  var i,j: integer;
      (...)
      cfound: boolean;
  begin 
    if C=nil then
      exit; // no RTTI information (e.g. reached TObject level)

    cfound := false;
    for j:=0 to ccount-1 do
      if C = clist[j] then
      begin
        cfound := true;
        break;
      end;

    if not cfound then
    begin
      clist[ccount] := C;
      Inc(ccount);
      if Length(clist) = ccount then
        SetLength(clist, Length(clist) + 3);
    end;

    AddClass(C.ClassParent); // add parent properties first
    CP := InternalClassProp(C);
    if CP=nil then
      exit;

    P := @CP^.PropList;
    for i := 1 to CP^.PropCount do begin // add all field names
      AddOnceDynArray(WinAnsiString(TSQLRecord.CaptionName(@P^.ShortName)));
      // for Delphi 2009/2010/XE: CaptionName converted into a WinAnsiString
      with P^.PropType^^ do
      case Kind of
      tkClass:       // add contained objects
      begin
        cfound := false;
        for j:=0 to ccount - 1 do
          if ClassType^.ClassType = clist[j] then
          begin
            cfound := true;
            break;
          end;
        if not cfound then
          AddClass(ClassType^.ClassType);
      end;
(...)
begin
  // all code below use *A() Win32 API -> only english=Ansi text is expected here
  assign(F,ChangeFileExt(paramstr(0),'.messages'));
  SetLength(buf,65536);
  SetLength(clist, Length(Objects)+Length(Records));
  ccount := 0;
(...)

#74 Re: mORMot 1 » Error To compile SQLite3UIEdit version 1.14 » 2011-06-17 12:36:19

ab wrote:
Leander007 wrote:

You missed the first change:

Group: TGroupBox absolute C;

Without this the code does not work, because you are assigning different "C" control.

I didn't miss this one, but the correct missing line was this one:

fFieldComponents[i] := Group;

With first code excerpt goes this too:

fFieldComponents[i] := C;
continue;

I was not thinking about the "long" version, but only about upper comparison, because later you use continue word, so the flow control is changed and the "extra" code

if (C<>nil) and (C<>self) and (C<>Scroll) then begin

is never reached in set case.
So It seems that you were using C only for common handling of controls and TGroupBox does not count in it.
From technical aspect usage of the upper is the same, but cleaner design is assigning Group, not the C.

#75 Re: mORMot 1 » Error To compile SQLite3UIEdit version 1.14 » 2011-06-17 11:01:56

Arnaud you made lapsus in 215dfe5ac7.

Unit SQLite3UIEdit

line 394:

if E^.MaxValue>31 then // up to 32 elements in tkSet (GetOrdValue)
  SetMax := 31 else
  SetMax := E^.MaxValue;
Sets := P^.GetOrdValue(aRecord);
E := P^.PropType^^.SetEnumType;

should be:

Sets := P^.GetOrdValue(aRecord);
E := P^.PropType^^.SetEnumType;
if E^.MaxValue>31 then // up to 32 elements in tkSet (GetOrdValue)
  SetMax := 31 else
  SetMax := E^.MaxValue;

I saw that you did some cleanup in this procedure smile, but excluding this, is there any real difference with

Group: TGroupBox absolute C;

approach as you did for other controls and this latest code when you assign Group directly?

#76 Re: mORMot 1 » Error To compile SQLite3UIEdit version 1.14 » 2011-06-17 10:37:42

coblongpamor, if you need really customized look of edit form, then don't use TRecordEditForm, but develop custom GUI by "hand" (using Delphi RAD approach) as is done in Main Demo in FileEdit.pas (TEditForm) and manipulate with TSQLRecord as you wish.

Looking at the code should be enough, because basics of the framework are used in it.

#77 Re: mORMot 1 » Error To compile SQLite3UIEdit version 1.14 » 2011-06-16 14:06:26

You missed the first change:

C: TWinControl;
Group: TGroupBox absolute C;

Without this the code does not work, because you are assigning different "C" control.

You are still having minor compile errors in SQLite3i18n unit.
Please could you check version in fossil (I must synch each way when I download smile), maybe you are having right working copy, but wrong check-in in fossil version control. 

unit SQLite3i18n:

procedure ExtractAllResources...

line 2850 is

AddOnceDynArray(WinAnsiString(TSQLRecord.CaptionName(@P^.Name)));

should be

AddOnceDynArray(WinAnsiString(TSQLRecord.CaptionName(@P^.ShortName)));

line 2890 is

AddOnceDynArray(WinAnsiString(CaptionName(@P^.Name)));

should be

AddOnceDynArray(WinAnsiString(CaptionName(@P^.ShortName)));

#78 Re: mORMot 1 » Documentation updated to revision 1.13 » 2011-06-16 13:22:16

Quick look through comments in your code give me the filling of only <summary> node usage and missing others (as see, seealso, param...), which are used in chm, MS Help 2, HTML and other help formats used as API description in Delphi IDE and similar.

E.g. automatically inserted template (with regions of course) with typing almost only ///:

{$REGION 'xmldoc'}
/// <summary>
/// Register a specified test to this class instance
/// </summary>
/// <param name="aMethod">Comment here the aMethod param</param>
/// <param name="aName">Comment here the aName param</param>
{$ENDREGION}
procedure Add(aMethod: TSynTestEvent; const aName: string);

with excerpt of generated xml doc (which is really verbose, too verbose, but quickly generated by compiler and you can guess that all xml tags are not completely the same as in .NET, but this is not the problem):

(...)
<procedure name="Add" visibility="public">
<devnotes>
<summary>
 Register a specified test to this class instance 
</summary>
<param name="aMethod">
Comment here the aMethod param
</param>
<param name="aName">
Comment here the aName param
</param>
</devnotes>
<parameters>
<parameter name="aMethod" type="TSynTestEvent"/>
<parameter name="aName" type="string" paramflags="const"/>
</parameters>
</procedure>
(...)

versus

/// register a specified test to this class instance
procedure Add(aMethod: TSynTestEvent; const aName: string);

Xml Doc is indeed more verbose (with more information in this case) when used for commenting the code, but with using regions that is not any problem, because they are collapsible and you don't see this as nagging text.

-------------
I saw that you have some special tags in comments, but I don't know if they could achieve same effect as regular xml doc tags?
Are this comment tags used in your code described anywhere?
In SynProject you have some kind of version control, but is it possible (with minor work) to attach some 3rd version control, such as subversion or fossil smile?

I'll definitely look at SynProject in details to become more familiar with used concepts. Then I can properly make a comment, what could be done to easily interface (or extend) with existing tools, practices...

#79 Re: mORMot 1 » Error To compile SQLite3UIEdit version 1.14 » 2011-06-16 09:52:19

Yes, that was my comment about "several calls to InheritsFrom, this could be changed" smile , because I realized that fFieldComponents was not assigned for sets smile.
I did not realized if commenting continue will break something, because I changed the flow control (dirty and long version) where is not set related.
I will test it later if all works with your new version.

#80 Re: mORMot 1 » Documentation updated to revision 1.13 » 2011-06-16 09:42:37

Yes, that was my point, only replacing PasDoc parser with xml doc parser, what Delphi itself is already. So if they add some new feature to Pascal language, we don't feel this, because xml doc output format is consistent and parsing xml is very easy.

Don't forget not only that you are compatible with .NET commenting, but you get Help Insight, compiler warnings about wrong referenced "classes" and maybe refactoring tools too. In short Embercadero is enforcing Microsoft standards and they (both) make tools for us.

I think would be best to use the Delphi generated xml output and parse it to some intermediate format which would fit in SynProject.
This way we don't need custom parser implementation for xml comments in code, rather we parse the well formated generated xml from Delphi compiler.
In this way you have generated xml with all classes, functions, records even if you did not comment anything. You get all hierarchy and you could easily generate final documentation only for "elements" which are commented if you wish.

What you think about that?

#81 Re: mORMot 1 » Error To compile SQLite3UIEdit version 1.14 » 2011-06-16 01:39:50

I have test it your TRecordEditForm with sources dating 2011-06-11. I saw that sets (TGroupBox implementation) could not be editable (the result was not really set to the TSQLRecord on BtnSaveClick).
So I changed the code that it works (at least it looks like that smile) and "render" properly and nothing else (several calls to InheritsFrom, this could be changed).

I have done four changes in SetRecord procedure:

procedure TRecordEditForm.SetRecord(aClient: TSQLRestClient;
  aRecord: TSQLRecord; CSVFieldNames: PUTF8Char=nil; Ribbon: TSQLRibbon=nil;
  FieldHints: string=''; FieldNamesWidth: integer=0; aCaption: string='');
var i,j, aID, Y, aHeight, aWidth, CW: integer;
    (...)
    C: TWinControl;
    Group: TGroupBox absolute C; // -----------------------------------------------------> CHANGE 1
    (...)
begin
         (...)    
          sftSet: begin
            (...)
            for j := 0 to E^.MaxValue do
              with TCheckBox.Create(Scroll) do begin // add set checkboxes
                (...)
              end;
            inc(Y,Group.Height+12);
            //continue; // --------------------------------------------------------------> CHANGE 2
          end;
          (...)
      if (C<>nil) and (C<>self) and (C<>Scroll) then begin
        (...)
        if not C.InheritsFrom(TCheckBox) then
        if C.InheritsFrom(TLabeledEdit) then begin
          (...)
        end else if not C.InheritsFrom(TGroupBox) then // -------------------------------> CHANGE 3
        with TLabel.Create(Scroll) do begin // add label left-sided to the field
          (...)
        if C.InheritsFrom(TDateTimePicker) then begin
          (...)
        end
        else if not C.InheritsFrom(TGroupBox) then // -----------------------------------> CHANGE 4
          C.SetBounds(FieldNamesWidth,Y,200,22);
        fFieldComponents[i] := C;
        inc(Y,aHeight);
      end;
    end;
  end;

#82 Re: mORMot 1 » Documentation updated to revision 1.13 » 2011-06-15 23:26:42

By mistake I named SynProject as Synopse smile in my last post. I'm aware (from your description, not really used it) of your completeness of this documenting program.

Maybe is not totally proper that I opened different but somehow connected subject, when I mentioned XML (with XSLT you have the power needed) as possible output for documentation and at the same time I was talking about XML DOC comments, which are standard at least in Microsoft world.

I really like xml doc comments, because I don't take this kind of xml as evil (opposite from that I see SOAP as too verbose). If you have proper tools at your hand this is not the obstacle. With tools I mean, using regions to hide comments, auto generated templates (automatically extracted arguments...) for procedures and functions for example,  help insight showing your comments in Delphi IDE, Delphi checks referencing comments integrity when compiling and I can bet that some tool is capable to refactor referencing comments when you e.g. rename class.

If I understand correctly you use modified PasDoc (as I know all old parsers brake on new features of Delphi language, so constant update of them is the must) for comment extraction and then you generate pro file.
As I see it, xml doc could be replacement (or the extra possibility) only for PasDoc parser (not as the whole) as intermediate format, which has well formed xml format and could be easily parsed and transformed into pro format (or could be used for totally different cases, because it is standardized...).

In short, if I want to comment code in xml doc and use the generated Delphi xml documentation output as source for SynProject, which parts need the change? Is it only the PasDoc parser or is the "picture" more complex?
If this is not too hard, maybe I can try and add support for Delphi generated XML documentation, which is the code (with or without comments) extraction only.

#83 Re: mORMot 1 » Documentation updated to revision 1.13 » 2011-06-15 15:05:51

Maybe is even more reasonable to take XML approach as from Delphi 2006 there is option to generate XML documentation (same as in .NET) and could be used for extraction for code comments in future and could be combined with other XML output. What is really nice if you have some cross links (e.g. see, seealso ...) which points to some non existing type, you get warning on compilation.

Ok, if the comments in code are converted to the xml doc format, then documentation from code could not be generated with Delphi prior 2006 (maybe Doc-O-Matic Express...) with Delphi itself.

This are just some thoughts, because I already use (still experimental) in some projects Doc-O-Matic Express for xml doc conversion to the chm (html) help, but I want to work directly with Delphi xml doc and having some custom logic (as you did with Synopse) which works with "static" help pages or even with wiki approach.

With CnPack or GExperts (it's peaty that this auto commenting features are not included in Delphi by default as it is in Visual Studio) is very easy to quickly comment units, classes, procedures. I'm using regions to expand or collapse comments, that is very handy too.

{$REGION 'xmldoc'}
/// <summary>
/// Token importance degree. 0 is for informative message, 1 is alarm and so on.
/// </summary>
{$ENDREGION}
property AlarmType: integer read _alarmType write _alarmType;

#84 Re: mORMot 1 » Documentation updated to revision 1.13 » 2011-06-15 14:28:33

Yes, HTML would be better and user editable...
Maybe even better as custom XML (raw data) with some XSLT transformation to get HTML or some other output.

#85 Re: mORMot 1 » Documentation updated to revision 1.13 » 2011-06-15 12:33:28

Arnaud, is it possible to generate pdf bookmarks when you generate sampledoc pdf-s?
It would be very helpful when navigating through growing documentation.
I didn't look yet through Synopse project, so I don't know if this is easy to do automatically or not.
As I understand you don't use your pdf engine for output pdf-s, instead output from pro file is word document (doc) and then you use pdf export from Word.

#87 Re: mORMot 1 » How to Implement Trigger and Stored Procedure » 2011-06-15 10:54:52

No , this is not correct. FieldName is name of field (column).

With test

if FieldName = '' then 

you know that the table is in CREATION faze (could be named OnCreateTable) and you can execute the trigger creation at this stage (Table is created, so create the trigger too). You don't need other checks (this is the benefit of this approach).
Just override mentioned procedure for each TSQLRecord descendant which needs trigger (your case) or something else.

You must provide whole DDL sentence for trigger creation in Server.EngineExecuteAll(WholeDDLneeded).

#88 Re: mORMot 1 » How to Implement Trigger and Stored Procedure » 2011-06-15 10:38:27

You don't need to check for trigger existence, because you know that is not yet created, so just call "create trigger...".

#89 Re: mORMot 1 » How to Implement Trigger and Stored Procedure » 2011-06-15 10:17:48

Forget RTTI, that was just used in my example.

You just need to override next procedure in your derived class in which you need the trigger on related table:

public
  class procedure InitializeTable(Server: TSQLRestServer; const FieldName: RawUTF8); override; 
(...)

and then in implementation:

class procedure TSQLToken.InitializeTable(Server: TSQLRestServer;
  const FieldName: RawUTF8);
begin
  inherited InitializeTable(Server, FieldName);
  if FieldName = '' then begin //'' empty string means that the table is in creation faze (alias OnCreateTable)...
    //Here comes your code which initialize some table data (in my case Token table) or do something else
    //You could create your trigger at this stage with Server.EngineExecuteAll 
  end;
end;

This is the proper object way, but you can achieve the same goal in many ways.

#90 Re: mORMot 1 » How to Implement Trigger and Stored Procedure » 2011-06-15 09:38:23

I was using InitializeTable for filling the delphi enum in some reference table (on table creation), where the enum's could be translated (not i18n) in some other text.

#91 Re: mORMot 1 » How to Implement Trigger and Stored Procedure » 2011-06-15 09:35:46

Here is the way how the InitializeTable is used in my example:

TSQLToken = class(TSQLRecord)
(...)
public
  class procedure InitializeTable(Server: TSQLRestServer; const FieldName: RawUTF8); override;
(...)

and then in implementation

class procedure TSQLToken.InitializeTable(Server: TSQLRestServer;
  const FieldName: RawUTF8);
var
(...)
begin
  inherited InitializeTable(Server, FieldName);
  if FieldName = '' then begin //'' is for table creation in e.g. CreateMissingTables
    TI := TypeInfo(TSystemMessage);
    AddEnumToTable(TI);
    TI := TypeInfo(TPumpMessage);
    AddEnumToTable(TI, true);
  end;
end;

#92 Re: mORMot 1 » Synopse SQlite3 Unit Tests » 2011-06-11 12:44:09

I didn't really looked the code, just run the tests and look for results smile.

Now all tests pass just fine.

#93 Re: mORMot 1 » Synopse SQlite3 Unit Tests » 2011-06-10 22:43:48

I checked your latest code (/FontBBox independace), but it does not work, the test still fails on:

Check(H=$2636C99E);

The fontbbox is still "/FontBBox [-628 -376 2000 1010 ]"

#94 Re: mORMot 1 » Synopse SQlite3 Unit Tests » 2011-06-09 09:08:46

Yes indeed looks that PAnsiChar casting was guilty for hidden conversion.
Super smile, now there is only one failing test left and that is the PDF check:

Unit SynSelfTest

813:

H := Hash32(MS.Memory,MS.Position);
Check( (H=$93D859A5) or (H=$9FB359A7) ); // Arial,Bold and Tahoma FontBBox
MS.SaveToFile(ChangeFileExt(paramstr(0),'.pdf'));

Is the date below in resulting pdf correct?

/CreationDate (D:20100610191717)
/ModDate (D:20100610191717)

Is the webcontact01 mail or is web link in some page (that I can send you the resulting pdf for quick diff with yours expected one)?

#95 Re: mORMot 1 » Synopse SQlite3 Unit Tests » 2011-06-08 22:42:03

Ok, I did not find where is webcontact01, but any way I think the file wont help much, because I already said which bytes are different from expected result and the issue exists prior JSON encoding.
When we read from database we get "97 233 231" sequence instead of "224 233 231". So it must be wrong writing to the database or reading from the database.
I will test it further in this days when I'll have spare time.
Moggco said that "next" test is solved in general way with chr(...) solution.
Strange is that this "direct file test" fails even when we use this approach (at least when used cp 1250, but assuming other coding will fail too).

#96 Re: mORMot 1 » Synopse SQlite3 Unit Tests » 2011-06-08 13:26:32

Hm, next error is strange for me, you will get it much faster than me, what is going on.

Direct access file test failure:
When I look in Test1.json dump file, created with different exe-s (1252,1250), the only difference is in BLOB part:

Unit SQLite3

  R.Bind(1,PAnsiChar(chr(224)+chr(233)+chr(231)+'dsjdsBLOB23'),14); // Bind Blob
(...)
  JS := Demo.ExecuteJSON(Req); // get result in JSON format
  FileFromString(JS,'Test1.json');
  Check(Hash32(JS)=$221D7DBD,'Expected ExecuteJSON result not retrieved');//line 5623

Here are JSON excerpts (Difference is in 2 Bytes in BLOB ?! Are we not forcing this with chr(...) to be correct, where is the problem?):
1250: "Mônet","YennZHNqZHNCTE9CMjM=",1840,1926,19, -> Ye is $59 $65
1252: "Mônet","4OnnZHNqZHNCTE9CMjM=",1840,1926,19, -> 4O is $34 $4F

Ok, with debugger I saw that sqlite3_column_blob api in

W.WrBase64(sqlite3_column_blob(Request,i),
                sqlite3_column_bytes(Request,i),true);

returned for those 3 Bytes next values for 1250:
$61 $E9 $E7 -> 97 233 231 //strange, the first one is incorrect?!

and for 1252:
$E0 $E9 $E7 -> 224 233 231 //all three are correct

#97 Re: mORMot 1 » Synopse SQlite3 Unit Tests » 2011-06-08 11:31:18

My correction about code page.
TestSQL3 build in OS with code page set to 1252 runs all tests (excluding last PDF test) just fine in OS with code page set to e.g. 1250. 
So the problem is in literals. All must be corrected as you did before with chr(number) in consistent way and all will work.

#98 Re: mORMot 1 » Synopse SQlite3 Unit Tests » 2011-06-08 09:49:42

No this does not work, I think that there is no way to change system code page without restarting the OS.

#99 Re: mORMot 1 » Synopse SQlite3 Unit Tests » 2011-06-07 20:15:35

All upper tests excluding this last post (TPdfDocumentGDI test) are code page related.
They fail if I change system locale code page to something else as 1252 (in my case 1250).

Only TPdfDocumentGDI test (last check) fails in all circumstances in which I run tests.

#100 Re: mORMot 1 » Synopse SQlite3 Unit Tests » 2011-06-07 18:29:22

Yes, using break is the shortest one smile.

With next PDF test I really don't have a clue what could be wrong and how to test it, because I don't know what to expect in intermediate steps.

Unit SynSelfTests

Check on line 792 is OK,
but the check on line 813 fails:

H := Hash32(MS.Memory,MS.Position); //MS.Position=6725, H=$93E059A5 
Check( (H=$93D859A5) or (H=$9FB359A7) ); // Arial,Bold and Tahoma FontBBox

Board footer

Powered by FluxBB