#151 Re: mORMot 1 » Lazarus support » 2013-09-23 05:59:21

I was only thinking of implementing the client side of Sample 4

#152 Re: mORMot 1 » Lazarus support » 2013-09-22 12:23:23

Out of interest I've just had a go with compiling mormot with Lazarus on a Mac which wasn't completely successful. Here's a bit of feedback:
1. Could {$I Synopse.inc} be put before the comment block of source files. Otherwise if delphi mode isn't already set the compiler gets confused by comment nesting.
2. It makes use of the libC unit which hasn't been ported to osx. see http://wiki.freepascal.org/libc_unit
3. The uses clause at line 540 of SynCommons:  SynLz should be SynLZ
4. TWindowsVersion type is not defined (at line 8057 of SynCommons).

It would be great if mac compatibility was there - at least enough to build an http client like in Sample 4.

#153 Re: mORMot 1 » TGDIPages footer page numbers » 2013-09-19 16:23:41

What I'm aiming for is a PDF with a set of reports with their original page numbers. Would it be possible to use

property Pages: TGDIPageContentDynArray read fPages;

to copy between two TGDIPages which are created at the same time. One would make all the sub-reports and the other would copy these as they are made and create a combined report at the end?

#154 mORMot 1 » TGDIPages footer page numbers » 2013-09-19 11:27:11

esmondb
Replies: 7

I want to create a report which is a concatenation of other reports and get the footer page numbering as shown in the original concatenated report ('Page #/#'). It doesn't seem that easy to do. Would one way be to add two private TIntegerDynArray variables to TGDIPages which parallel fPages in size? A 'ResetPageCount' function could be added to manage these new variables and then when EndDoc is called they would be used to build the footer page number text.

#155 Re: PDF Engine » MormotReport is making black images in PDF » 2013-09-17 10:34:07

Instead you could use a TPdfImage object which has a CreateJpegDirect constructor.

Then you can do TPdfDocument.Canvas.DrawXObject

This should also mean that there's no need to uncompress the jpeg file.

#156 Re: mORMot 1 » TSQLTableToGrid horizontal scroll jump when selecting row » 2013-09-13 06:32:10

Could there be a way of disabling TSQLTableToGrid.DrawGridKeyDown? At the moment it changes the sort order if the left or right arrow keys are pressed but if goRowSelect isn't defined it would be better to allow the default handling of changing the selected cell.

#158 mORMot 1 » TSQLTableToGrid horizontal scroll jump when selecting row » 2013-09-12 14:28:13

esmondb
Replies: 4

If a TSQLTableToGrid.drawgrid has lots of columns and is scrolled right selecting a row causes the horizontal scrollbar to jump back to the left.

I've found a solution on StackOverflow saying that it is caused by goRowSelect being in the DrawGrid options:
http://stackoverflow.com/questions/3355 … 404#336404

Is goRowSelect absolutely necessary for TSQLTableToGrid to work?

#159 Re: mORMot 1 » automating backup » 2013-09-12 10:41:00

From my point of view the official "backup API" looks best. The link above gives an example of a non-blocking way of using it at the bottom of the page. It warns that a large number of writes may stop a backup ever finishing but that is only if multiple threads are used and as mORMot only uses a single thread to access SQLite that shouldn't matter.

Not so concerned about solutions for dbs other than SQLite.

#160 mORMot 1 » automating backup » 2013-09-10 05:29:29

esmondb
Replies: 9

I'm trying to set up a backup system using TSQLRestServer.OnUpdateEvent

The update event checks a timestamp of when the server started and makes a backup if it hasn't been done recently. The problem is this falls over if a transaction is active with the error 'a vacuum can't be done inside a transaction' (using SQLite).

Would it be better to create a service on the server which gets triggered/co-ordinated on the client side instead of using OnUpdateEvent?

#161 mORMot 1 » IsRowID fails with fully qualified field name: tableName.ID » 2013-08-08 08:10:32

esmondb
Replies: 0

with SQLite I've found that in order to combine MATCH queries UNION has to be used instead of OR. This has the side affect that the field names returned to TSQLTable also include the table name in the form: tableName.fieldName which breaks TSQLTable.IDColumnHide.

I can get round this by using 'select ... as ...' but would it be worth putting in a feature request for the IsRowID function to be extended to handle these cases?

#162 Re: mORMot 1 » mORMot through internet » 2013-08-07 04:14:32

Hi, I've got a problem with setting

 CanSelect := False; 

within a TSQLTableToGrid.OnSelectCell procedure when onIdle is set.

If TSQLTableToGrid.OnSelectCell contains these lines

TSQLHttpClient(Database).ServerTimeStampSynchronize;
  CanSelect := False;

it is still possible to select rows by clicking but not by pressing the up and down keyboard buttons. If TSQLRestClientURI.onIdle is nil or the database call in onSelectCell is removed it works - ie clicking on a row doesn't select it. Any ideas where this is going wrong? Thanks

#163 Re: mORMot 1 » mORMot through internet » 2013-08-05 09:05:43

My network can be somewhat unreliable at times (I suspect a DNS problem but don't control the network).

If I set the DB.WinAPI.ConnectTimeout after DB.ServerTimeStampSynchronize; It can take 21 seconds before I get a timeout error (code 12002) but this is intermittent. (Also I find that the maximum timeout I can set is 21 seconds which maybe to do with Windows 7)

So ideally I would like to set  DB.WinAPI.ConnectTimeout before DB.ServerTimeStampSynchronize; to avoid a possible 21 second wait.

#164 Re: mORMot 1 » mORMot through internet » 2013-08-05 05:15:46

Yes, I was trying to find a shortcut but now see this isn't so ok.

I've got a connected problem. I'm trying to set TSQLHttpClient.WinAPI.ConnectTimeout before a connection is made but get an AV as WinAPI is only created the moment the first connection is made. Is there a way round this? My test code is:

  DB := TSQLHttpClient.Create('192.168.99.99', '80', TSQLModel.Create([]));//non-existant server
  DB.WinAPI.ConnectTimeout := 5000;
  DB.ServerTimeStampSynchronize;

#165 Re: mORMot 1 » mORMot through internet » 2013-08-04 19:16:11

Thanks also for this.

I was using using the new OnIdle event to catch exceptions, checking the LastErrorCode when ElapsedMS = -1.

This doesn't seem possible with the latest implementation. Is there another way to globally check the LastErrorCode?

#166 mORMot 1 » Audit trail » 2013-08-02 20:52:22

esmondb
Replies: 1

I'm trying to create an audit trail like in the MainDemo but I would also like to track the TSQLAuthUser ID as well.

Can this be done currently?

The implementation in the MainDemo seems to rely on:

  TNotifySQLEvent = function(Sender: TSQLRestServer; Event: TSQLEvent;
    aTable: TSQLRecordClass; aID: integer): boolean of object;

Would this also need the TSQLAuthUser record ID passed to implement this?

#167 Re: mORMot 1 » TSQLTableToGrid on sort feature request » 2013-08-02 20:49:48

Thanks for implementing the onSort event. It all seems to work fine smile

#168 Re: mORMot 1 » tDateTime unexpected behaviour » 2013-07-31 20:48:54

I had a similar problem and it seems TDateTimePicker.Date also includes a time part.

Try:  trunc(myTDateTimePicker.Date)

#169 mORMot 1 » TSQLTableToGrid options » 2013-07-21 08:34:45

esmondb
Replies: 0

Could goFixedRowClick be added to the drawgrid options which get set by TSQLTableToGrid.Create?

#170 mORMot 1 » TSQLTableToGrid on sort feature request » 2013-07-17 12:31:01

esmondb
Replies: 1

I'm trying to get multicoloured  per row font and background colours with a TSQLTableToGrid.

To do this I'm using two dynamic arrays of TColor which are initialised immediately after the TSQLTable is created based on an enumerated field. When onBackground is called this array is used to fillrect the background colour and set the font colour. This works but fails when a TSQLTableToGrid drawgrid gets sorted by a click on the header. To solve this I added an onAfterSort TNotifyEvent called at the end of TSQLTableToGrid.SortForce routine. This event then reinitialised the colour arrays.

Does this seem a practical way to do it? If so I'll add a feature request for an onAfterSort event.

#171 mORMot 1 » TSQLTable.FieldLengthMax and Enumerate type fields » 2013-07-17 12:21:07

esmondb
Replies: 0

Could FieldLengthMax be changed so that with sftEnumerate it gives the max caption length, like below?

function TSQLTable.FieldLengthMax(Field: integer; NeverReturnsZero: boolean): cardinal;
var i: integer;
    len: cardinal;
    U: PPUTF8Char;
begin
  result := 0;
  if (self<>nil) and (cardinal(Field)<cardinal(FieldCount)) then begin
    if not Assigned(fFieldType) then
       InitFieldTypes;
    if fFieldType[Field].ContentType = sftEnumerate then begin
      for i := 0 to PEnumType(fFieldType[Field].EnumTypeInfo)^.MaxValue do begin
        len := length(PEnumType(fFieldType[Field].EnumTypeInfo)^.GetCaption(i));
        if len > result then
          result := len;
      end;
    end else begin
      U := @fResults[FieldCount+Field]; // start reading after first Row
      for i := 1 to RowCount do begin
        len := StrLen(U^);
        if len>result then
          result := len;
        inc(U,FieldCount);
      end;
    end;
  end;
  if (result=0) and NeverReturnsZero then
    result := 1; // minimal not null length
end;

#172 Re: PDF Engine » Embedded font problems with barcode font "Code 2 of 5 interleaved" » 2013-07-17 10:33:51

Another option could be to draw the barcode directly without using a font. I've pulled out of an old project my attempt at 'interleaved 2 of 5' below which might be helpful.

type
  TBarCodeWidths = array[0..4] of shortint;

const
  bar0 : TBarCodeWidths = (10,10,30,30,10);
  bar1 : TBarCodeWidths = (30,10,10,10,30);
  bar2 : TBarCodeWidths = (10,30,10,10,30);
  bar3 : TBarCodeWidths = (30,30,10,10,10);
  bar4 : TBarCodeWidths = (10,10,30,10,30);
  bar5 : TBarCodeWidths = (30,10,30,10,10);
  bar6 : TBarCodeWidths = (10,30,30,10,10);
  bar7 : TBarCodeWidths = (10,10,10,30,30);
  bar8 : TBarCodeWidths = (30,10,10,30,10);
  bar9 : TBarCodeWidths = (10,30,10,30,10);

var
  digits: string;
  x, y, barHeight: integer;
  barA, barB : TBarCodeWidths;
  digit1, digit2 : char;

begin
  ...
              while length(digits)<6 do digits := '0'+digits;
              canvas.Brush.Style := bsSolid;
              canvas.Brush.Color := clBlack;
              barheight := 60;
              x := 0;
              y := 0;
              Canvas.FillRect(Rect(y,x,y+10,x+BarHeight));
              y := y+20 ;
              Canvas.FillRect(Rect(y,x,y+10,x+BarHeight));
              y := y+20 ;
              for ii := 0 to 2 do begin
                Digit1 := digits[(ii*2)+1];
                Digit2 := digits[(ii*2)+2];
                Case digit1 of
                  '0' : for z := 0 to 4 do bara[z] := bar0[z];
                  '1' : for z := 0 to 4 do bara[z] := bar1[z];
                  '2' : for z := 0 to 4 do bara[z] := bar2[z];
                  '3' : for z := 0 to 4 do bara[z] := bar3[z];
                  '4' : for z := 0 to 4 do bara[z] := bar4[z];
                  '5' : for z := 0 to 4 do bara[z] := bar5[z];
                  '6' : for z := 0 to 4 do bara[z] := bar6[z];
                  '7' : for z := 0 to 4 do bara[z] := bar7[z];
                  '8' : for z := 0 to 4 do bara[z] := bar8[z];
                  '9' : for z := 0 to 4 do bara[z] := bar9[z];
                end;
                Case digit2 of
                  '0' : for z := 0 to 4 do barb[z] := bar0[z];
                  '1' : for z := 0 to 4 do barb[z] := bar1[z];
                  '2' : for z := 0 to 4 do barb[z] := bar2[z];
                  '3' : for z := 0 to 4 do barb[z] := bar3[z];
                  '4' : for z := 0 to 4 do barb[z] := bar4[z];
                  '5' : for z := 0 to 4 do barb[z] := bar5[z];
                  '6' : for z := 0 to 4 do barb[z] := bar6[z];
                  '7' : for z := 0 to 4 do barb[z] := bar7[z];
                  '8' : for z := 0 to 4 do barb[z] := bar8[z];
                  '9' : for z := 0 to 4 do barb[z] := bar9[z];
                end;
                for z := 0 to 4 do begin
                  Canvas.FillRect(Rect(y,x,(y+bara[z]),x+BarHeight));
                  y := y+bara[z]+barb[z] ;
                end;
              end;
              canvas.FillRect(Rect(y,x,y+30,x+BarHeight));
              canvas.FillRect(Rect(y+40,x,y+50,x+BarHeight));

...

#173 mORMot 1 » TSQLTable sorting with a join » 2013-07-04 08:57:54

esmondb
Replies: 0

With a TSQLTable made from the SQL statement below using TSQLRestClientURI.ExecuteList sorting fails on the authors.name field (using a TSQLTableToGrid). Tracing through the code it seems TSQLTable.InitFieldTypes sets this field's type to sftID instead of sftUTF8Text which is the defined type of authors.name. I guess this is because authors.name is referred to by an record id. Is sorting on a joined field implemented yet or am I going about it the wrong way?

Select books.title, authors.name from books left join authors on books.author=authors.ID

#174 Re: mORMot 1 » TSQLTableToGrid auto-resizing columns » 2013-06-27 06:39:55

Just worked out that I needed to call TSQLTableToGrid.Refresh(true) after SetFieldLengthMean.

#175 Re: mORMot 1 » TSQLTableToGrid Refresh resizing columns » 2013-06-27 06:37:32

Just added a ticket. Sorry initially missed your response.

Thanks

#176 mORMot 1 » Column Picker Form » 2013-06-22 10:57:02

esmondb
Replies: 0

I've created a form for selecting fields from a TSQLRecord. As it's fairly generic it could be useful to others so I've posted it below.

BTW I found a small typo in TSynButton.CreateKind where the 'right' parameter should be 'top'.

unit ColumnPicker;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, mORMot, SynCommons, SynTaskDialog,
  Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.CheckLst;

type
  TColumnPickerForm = class(TForm)
    procedure ToggleAllCheckBoxClick(Sender: TObject);
    procedure FieldsCheckListBoxClickCheck(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  protected
    OKBtn, CancelBtn: TSynButton;
    BottomPanel: TPanel;
    ToggleAllCheckBox: TCheckBox;
    FieldsCheckListBox: TCheckListbox;
  private
    fTableName: RawUTF8;
    fFieldNames: TRawUTF8DynArray;
    function getToggleAllCheckboxState: TCheckBoxState;
    function getSelStatement: RawUTF8;
  public
    constructor Create(AOwner: TComponent; ARecord: TSQLRecord); reintroduce;
    property SelectStatement: RawUTF8 read getSelStatement;
  end;

implementation

{$R *.dfm}

constructor TColumnPickerForm.Create(AOwner: TComponent; ARecord: TSQLRecord);
var
  i : integer;
begin
  inherited Create(aOwner);
  width := 300;
  height := 400;
  fTableName := ARecord.RecordProps.SQLTableName;
  Caption := fTableName;
  ToggleAllCheckBox := TCheckBox.Create(self);
  ToggleAllCheckBox.Parent := self;
  ToggleAllCheckBox.Align := alTop;
  ToggleAllCheckBox.AlignWithMargins := true;
  ToggleAllCheckBox.Margins.Left := 1;
  ToggleAllCheckBox.OnClick := ToggleAllCheckBoxClick;
  BottomPanel := TPanel.Create(self);
  BottomPanel.Parent := self;
  BottomPanel.Caption := '';
  BottomPanel.Align := alBottom;
  BottomPanel.BevelOuter := bvNone;
  FieldsCheckListBox := TCheckListbox.Create(self);
  FieldsCheckListBox.BorderStyle := bsNone;
  FieldsCheckListBox.Parent := self;
  FieldsCheckListBox.Align := alClient;
  FieldsCheckListBox.OnClickCheck := FieldsCheckListBoxClickCheck;
  SetLength(fFieldNames, ARecord.RecordProps.Fields.Count);
  for i := 0 to ARecord.RecordProps.Fields.Count -1 do begin
    FieldsCheckListBox.Items.Append(UTF8toString(UnCamelCase(ARecord.RecordProps.Fields.Items[i].Name)));
    fFieldNames[i] := ARecord.RecordProps.Fields.Items[i].Name
  end;
  OKBtn := TSynButton.CreateKind(BottomPanel, cbOK, 180, 4, 89, 33);
  CancelBtn := TSynButton.CreateKind(BottomPanel, cbCancel, 80, 4, 89, 33);
  OnDestroy := FormDestroy;
end;

procedure TColumnPickerForm.FormDestroy(Sender: TObject);
begin
  SetLength(fFieldNames, 0);
end;

procedure TColumnPickerForm.ToggleAllCheckBoxClick(Sender: TObject);
begin
  if ToggleAllCheckBox.State <> cbGrayed then
    if ToggleAllCheckBox.Checked then
      FieldsCheckListBox.CheckAll(cbChecked, false, false)
    else
      FieldsCheckListBox.CheckAll(cbUnChecked, false, false);
end;

function TColumnPickerForm.getToggleAllCheckboxState: TCheckBoxState;
var
  i, cnt : integer;
  firstCheck: boolean;
begin
  result := cbUnchecked;
  if FieldsCheckListBox.Items.Count = 0 then exit;
  firstCheck := FieldsCheckListBox.Checked[0];
  if firstCheck then result := cbChecked;
  for i := 1 to FieldsCheckListBox.Items.Count-1 do
    if FieldsCheckListBox.Checked[i] <> firstCheck then begin
      result := cbGrayed;
      break;
    end;
end;

procedure TColumnPickerForm.FieldsCheckListBoxClickCheck(Sender: TObject);
begin
  ToggleAllCheckbox.State := getToggleAllCheckboxState;
end;

function TColumnPickerForm.getSelStatement: RawUTF8;
var
  i : integer;
begin
  result := 'SELECT ' + fTableName + '.ID';
  if ToggleAllCheckBox.Checked then
    result := 'SELECT *'
  else if ToggleAllCheckBox.State = cbGrayed then begin
    for i := 0 to FieldsCheckListBox.Items.Count-1 do
      if FieldsCheckListBox.Checked[i] then
        result := result + #32 + fTableName + '.' + fFieldNames[i];
  end;
end;

end.

#177 Re: mORMot 1 » getHTTP problem » 2013-06-20 08:10:09

Thanks, just tried it and it working fine.

#178 mORMot 1 » TSQLRestClientURI.SessionUser » 2013-06-19 13:57:08

esmondb
Replies: 0

In the code comments about TSQLRestClientURI.SessionUser (copied below) it gives an example of how to get the TSQlAuthUser fully filled out. Running the example gives me the error: 'Class TSQLAuthUser missing in model.' - I assume because TSQLAuthUser table is not visible client side. Could TSQLRestClientURI.SessionUser get the DisplayName and ID field filled out by default?

/// the current user as set by SetUser() method
    // - returns nil if no User is currently authenticated
    // - only available fields by default are LogonName and PasswordHashHexa:
    // you can run code similar to the following to fill all needed properties:
    // !  if fClient.SessionUser<>nil then
    // !  begin
    // !    fClient.Retrieve('LogonName=?',[],[fClient.SessionUser.LogonName],
    // !      fClient.SessionUser); // fill ID, DisplayName, GroupRights
    // !    fClient.RetrieveBlobFields(fClient.SessionUser); // optional Data
    // !  end;
    property SessionUser: TSQLAuthUser read fSessionUser;

#179 mORMot 1 » TGDIPages.ShowPreviewForm » 2013-06-19 10:26:42

esmondb
Replies: 0

The report preview form is shown with a default width a little less than a report page width. This causes a horizontal scrollbar to appear and cuts off the side of the report.

I've found changing line 4410 in mORMotReport.pas from:

 PreviewForm.Width := (cx*PreviewForm.Height) div y+(64+PANELWIDTH);

to:

 PreviewForm.Width := (cx*PreviewForm.Height) div y+(64+PANELWIDTH)+PANELWIDTH;

solves the problem but I don't fully understand the calculation. Why is the form height used to calculate PreviewForm.Width?

#180 mORMot 1 » TSQLTableToGrid auto-resizing columns » 2013-06-18 15:44:19

esmondb
Replies: 1

I'm trying to set the column widths with the following code but SetFieldLengthMean doesn't appear to work (using XE2). Can anyone see what's wrong?

  Table.CalculateFieldLengthMean(colwidths);
  s := '';
  for i := 0 to length(colwidths)-1 do
    s := s + Chr(colwidths[i] + 64);
  Grid := TSQLTableToGrid.Create(DrawGrid, Table, nil);
  Grid.SetFieldLengthMean(s, false);

#181 mORMot 1 » TSQLTableToGrid Refresh resizing columns » 2013-05-28 17:10:32

esmondb
Replies: 3

By default TSQLTableToGrid.Refresh auto resizes the column widths but I want to turn off this feature. Could a 'ResizeColumns' parameter be added to the function like below?

function TSQLTableToGrid.Refresh(ForceRefresh: Boolean=false; ResizeColumns: Boolean=true): boolean;
var Refreshed: boolean;
    aID: integer;
begin
  if self=nil then
    result := false else begin
    aID := Table.IDColumnHiddenValue(TDrawGrid(Owner).Row);
    if ForceRefresh then
      result := true else
      result := Client.UpdateFromServer([Table],Refreshed) and Refreshed;
    if result then
      AfterRefresh(aID, ResizeColumns);
  end;
end;

procedure TSQLTableToGrid.AfterRefresh(aID: integer, ResizeColumns: Boolean);
var CurrentRow: integer;
    Bulk: boolean;
begin
  with TDrawGrid(Owner) do begin
    if Table.RowCount=0 then
      RowCount := 2 else
      RowCount := Table.RowCount+1;
    if Table.FieldCount<>ColCount then begin
      // we get results from a void table for the first time
      ColCount := Table.FieldCount;
      SetLength(fFieldOrder,Table.FieldCount);
    end;
    CurrentRow := Table.RowFromID(aID);
    if CurrentRow=0 then
      CurrentRow := 1;
    Row := CurrentRow;
    TopRow := 1;
    Invalidate;
  end;
  if ResizeColumns then
    Resize(nil); // auto resize columns
  if Assigned(OnSelectCell) then
     OnSelectCell(Owner,0,CurrentRow,Bulk); // refresh details
end;

#182 Re: mORMot 1 » uniGUI with mORMot » 2013-05-22 11:02:17

So if I have mORMot running as an HTTP server is it perfectly ok to have a separate utility program to manage user accounts which accesses the same local SQlite3 data file directly? This seems a simpler and more secure way of managing user accounts than using services.

#183 Re: mORMot 1 » TSQLTableToGrid feature requests? » 2013-05-17 07:15:28

Just tried out the new features and they work great smile

I'm wanting to change for font colour on a per line basis. Is setting it in the OnValueText event the best way to do it? Seems to work ok.

Thanks

#184 Re: mORMot 1 » TSQLTableToGrid default row height » 2013-05-15 13:59:04

Yes, that fixes the issues. Could you update mORMotUI.

Many thanks

#185 mORMot 1 » TSQLTableToGrid default row height » 2013-05-15 08:19:00

esmondb
Replies: 3

I've got a problem changing the font when creating a TSQLTableToGrid in a form's onShow event.

  DrawGrid.Font.Size := 12;
  TableToGrid := TSQLTableToGrid.Create(DrawGrid, Table, database);

The Drawgrid font size gets set ok but the row height gets adjusted to the smaller default font size by the following lines in TSQLTableToGrid.Create

with aOwner.Canvas.TextExtent('jQH°;') do
    aOwner.DefaultRowHeight := cy+4;

I only get the problem if creating the TSQLTableToGrid in the form's onShow event.

Any suggestions on getting this working?

Thanks

#187 mORMot 1 » TSQLTableToGrid feature requests? » 2013-05-14 19:33:13

esmondb
Replies: 4

Can currency values displayed via TSQLTableToGrid be rounded to two decimal places and also be right-justified within the cell?

Could there be an alternate functionality for the id header checkbox whereby it selects/de-selects all marked items instead of sorting them. For some users this seems more instictive.

Many Thanks!

#188 Re: mORMot 1 » CSV text format » 2013-04-22 19:24:01

I'm not sure it is worth adding as a feature as everyone will probably want to customize the format differently.

Instead I've had a go at writing a version for my situation:

procedure TableToCSV(Table: TSQLTableJSON; CSV: TFileStream);
var
  i, row, col, FMax: integer;
  W: TTextWriter;
  s : string;
  E: PEnumType;
  EP: PShortString;
  P: TSQLPropInfo;
  Sets, SetMax: cardinal;
  SetItemName, RawSetItemName: RawUTF8;
begin
  if (Table.FieldCount<=0) or (Table.RowCount<=0) then
    exit;
  W := TTextWriter.Create(CSV,8196);
  FMax := Table.FieldCount -1;
  try
    W.AddShort(#$ef#$bb#$bf); // add UTF-8 Byte Order Mark
    for row := 0 to Table.RowCount -1 do
      for col := 0 to FMax do begin
        case Table.ExpandAsString(Row,Col,database,s) of
          sftBoolean: if s = '0' then
                        W.AddString('False')
                      else
                        W.AddString('True');
          sftTimeLog: if Table.GetU(row,col) <> '120795955200' then
                        W.AddString(QuotedStr(stringtoUTF8(s),'"'))
                      else
                        W.AddString('""');
          sftSet: begin
                    P := Table.QueryRecordType.RecordProps.Fields.List[col-1];
                    E := (P as TSQLPropInfoRTTISet).SetEnumType;
                    if E^.MaxValue>31 then // up to 32 elements in tkSet (GetOrdValue)
                      SetMax := 31
                    else
                      SetMax := E^.MaxValue;
                    Sets := GetInteger(pointer(s));
                    EP := @E^.NameList;
                    W.Add('"');
                    for i := 0 to SetMax do begin
                      if GetBit(Sets, i) then begin
                        setItemName := '';
                        RawSetItemName := ShortStringToAnsi7String(EP^);
                        SetLength(setItemName,PInteger(PtrInt(RawSetItemName)-sizeof(integer))^*2);
                        SetLength(setItemName,UnCamelCase(pointer(setItemName),TrimLeftLowerCase(RawSetItemName)));
                        W.AddString(setItemName);
                        W.Add(',');
                      end;
                      inc(PtrInt(EP),ord(EP^[0])+1); // next enumeration item
                    end;
                    W.CancelLastComma;
                    W.Add('"');
                  end;
          else
            W.AddString(QuotedStr(stringtoUTF8(s),'"'));
        end;
        if col=FMax then
          W.AddCR
        else
          W.Add(',');
      end;
    W.Flush;
  finally
    W.Free;
  end;
end;

#189 mORMot 1 » CSV text format » 2013-04-22 13:27:35

esmondb
Replies: 3

When using the function TSQLTableJSON.GetCSVValues I want the TTimeLog values to be formated as ISO 8601 text instead of the raw value. Is there a simple way to do this?

Also it would be nice if enumeration fields could be formated to make them more readable in CSV.

Thanks,
Esmond

#190 Re: mORMot 1 » Handling Unassigned dates » 2013-04-18 12:33:38

I guess using 0/0/0 isn't such a good idea. In my case business rules make certain dates invalid so I think I'll pick one of those as a 'magic' date to indicate unassigned.
Thanks

#191 mORMot 1 » Handling Unassigned dates » 2013-04-18 10:25:29

esmondb
Replies: 3

I'm planning on using the date 0/0/0 as a sort of NULL value but have a problem with TTimeLog to TDateTime conversions.

function Iso8601.ToDate: TDateTime;
begin
  if Value=0 then
    result := 0 else
    result := EncodeDate((Value shr (6+6+5+5+4)) and 4095,
                         1+(Int64Rec(Value).Lo shr (6+6+5+5)) and 15,
                         1+(Int64Rec(Value).Lo shr (6+6+5)) and 31);
end;

Converts 0/0/0 to 30/12/1899. Could it be changed to:

function Iso8601.ToDate: TDateTime;
begin
  if Value=0 then
    result := -693594 else ...

#193 mORMot 1 » RecordClassesToClasses() » 2013-04-02 14:49:50

esmondb
Replies: 2

I can't find the RecordClassesToClasses() function anymore which I thought was in mORMot.pas. Has it been removed?

#194 Re: mORMot 1 » Adding some generic-based methods to mORMot » 2013-04-02 10:53:22

It looks like the latest freepascal offer the Delphi syntax as an alternative:

http://wiki.lazarus.freepascal.org/User … elphi_mode

#195 Re: mORMot 1 » Latest Documentation » 2013-03-21 21:26:54

Thanks,

Managed to get TSynLabeledEdit installed the XE2 tool palette - don't know why but the compiler was trying to output C++ .obj files which caused problems.

#196 mORMot 1 » Latest Documentation » 2013-03-21 10:20:34

esmondb
Replies: 3

Where can I find the latest SAD documentation?

The version at:

http://synopse.info/files/pdf/Synopse%2 … 201.18.pdf

Is a few days old and I noticed in fossil that something had since been added about compiling mORMot in a package (I'm having trouble adding TSynLabeledEdit to an XE2 package)

#197 Re: mORMot 1 » Example 16: why I not see the list of tables of *.sqlite file? » 2013-02-15 17:27:49

I've just tried it and it works for some tables but not for others in XE2. The AuthGroup table shows fine but Users table gives this exception:

Project Project16Client.exe raised exception class EInterfaceFaceFactoryException with message 'Invalid fake IRemoteSQL.Execute interface call:'.

#198 Re: mORMot 1 » TSQLDBConnectionProperties.Execute on client side? » 2013-02-13 20:21:29

You could try something like:

var
  JSONBuffer: RawUTF8;

procedure example;
var
  Table: TSQLTable;
  Rows: ISQLDBRows;
begin
  Rows := Client.Execute('select * from SGRUSR01',[]);
  fJSONBuffer := Rows.FetchAllAsJSON(false);
  Table := TSQLTableJSON.Create([],'',pointer(fJSONBuffer),length(fJSONBuffer));
...

#199 Re: mORMot 1 » getHTTP problem » 2013-01-22 14:22:28

F.BufSize=1024 in XE2.

InputSock() is only called once before THttpSocket.GetBody. The rest of the calls are from GetBody.

One strange thing I've noticed is F.BufPtr gets truncated to 124 characters after the first call to InputSock when looked at at the start of the the InputSock function.

#200 Re: mORMot 1 » Documentation of the Synopse SQLite3 / mORMot Framework » 2013-01-22 13:54:19

"neither... nor" is different to "either.. or"

"neither Peter nor Jane will go to the party" means none of them will go to the party. neither is a bit like "not... either... or..."

"either Peter or Jane will go to the party" means only one of them will go to the party.

Board footer

Powered by FluxBB