#1 2013-10-07 14:13:21

Gigo
Member
From: Split, Croatia
Registered: 2012-01-27
Posts: 14

Currency fields, virtual methods

Hi Arnaud,
I encountered an issue with Currency fields in mORMot framework, that affects Win32 only.

This definition works fine :

TTestRec = class(TSQLRecord)
private
  FTestMoney : Currency;
published
  property TestMoney : Currency read FTestMoney write FTestMoney;
end;

but this does not :

TTestRec = class(TSQLRecord)
private
  FTestMoney : Currency;
published
  property TestMoney : Currency read GetTestMoney write SetTestMoney;
end;


function TTestRec.GetTestMoney: Currency;
begin
  Result := FTestMoney;
end;

procedure TTestRec.SetTestMoney(const Value: Currency);
begin
  FTestMoney := Value;
end;

With later code mORMot writes garbage to Currency field. If I try to add record again, exception "floating point stack check" is raised.
Float (double) fields works fine.

Here's what I've tried to fix this issue:
  - tried forcing USETYPEINFO / doesn't work
  - tried using older builds (down to 1.16) / doesn't work
  - tried to compile code with D7 instead of XE3 / doesn't work
  - traced source from TSQLRecord.GetJSONValues through TSQLPropInfoRTTIInt32.GetJSONValues and finally down to GetInt64Prop function, and found out that method GetTestMoney is actually called but result variable of GetInt64Prop is not filled with result of GetTestMoney.
  - finally I tied to change this code in mORMot.pas

procedure TSQLPropInfoRTTICurrency.GetJSONValues(Instance: TObject; W: TJSONSerializer);
begin
  // temp fix
  {$IFDEF CPU64}
  W.AddCurr64(GetInt64Prop(Instance,pointer(fPropInfo)));
  {$ELSE}
  W.Add(GetFloatProp(Instance,pointer(fPropInfo)));
  {$ENDIF}
end;

procedure TSQLPropInfoRTTICurrency.GetValueVar(Instance: TObject;
  ToSQL: boolean; var result: RawUTF8; wasSQLString: PBoolean);
begin
  if wasSQLString<>nil then
    wasSQLString^ := false;
  // temp fix
  {$IFDEF CPU64}
  result := Curr64ToStr(GetInt64Prop(Instance,pointer(fPropInfo)));
  {$ELSE}
  result := FloatToStr(GetFloatProp(Instance,pointer(fPropInfo)));
  {$ENDIF}
end;

and it works ! (but I guess with speed penalty)

Cheers

Offline

#2 2013-10-08 09:09:47

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: Currency fields, virtual methods

Now double/currency published properties will use getter/setter as expected...
I did a deep code review to ensure it should work for all methods (not only GetJSONValues and GetValueVar).
See http://synopse.info/fossil/info/01672224ef

Thanks a lot for the report!

Offline

Board footer

Powered by FluxBB