#1 2023-08-16 20:50:47

mrbar2000
Member
From: Brazil
Registered: 2016-10-26
Posts: 56

TDocVariantData.AddOrUpdateValue seens dont work to variants values

var
  vValue: Variant;
  vQueryTmp: TSQLQuery;
  vParams: TDocVariantData;
const
  cSQL = ' SELECT DT_NASC FROM PACIENTE WHERE CD_PACIENTE = 1';
begin
  vQueryTmp := NewQuery(cSQL, []);
  try
    vQueryTmp.First;
    vValue := vQueryTmp.FieldByName('DT_NASC').Value;  // vValue here has '01/07/2020'
  finally
    FreeQuery(vQueryTmp);
  end;
  vParams.InitJson('{}');
  vParams.AddOrUpdateValue('MyInt', 10);
  vParams.AddOrUpdateValue('MyBoolean', True);
  vParams.AddOrUpdateValue('MyVariantDate', vValue);
 

   
  ShowMessage(vParams.ToJson)  => {"Myint":10,"MyBoolean":true,"MyVariantDate":null}' ?????

  I was expecting {"Myint":10,"MyBoolean":true,"MyVariantDate": '2020-07-01T00:00:00'}'

What I should?

Last edited by mrbar2000 (2023-08-17 12:00:03)

Offline

#2 2023-08-16 22:24:45

tbo
Member
Registered: 2015-04-20
Posts: 335

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

mrbar2000 wrote:

What I should?

Write following and see what type the Variant is.

ShowMessage(VarTypeAsText(VarType(vValue)));

This works:

var
  doc: TDocVariantData;
begin
  doc.InitFast;
  var vValue: Variant := Date;
  doc.AddOrUpdateValue('MyInt', 10);
  doc.AddOrUpdateValue('MyBoolean', True);
  doc.AddOrUpdateValue('MyVariantDate', vValue);
  ShowMessage(doc.ToJson);

And where is vParams used in source code?

With best regards
Thomas

Last edited by tbo (2023-08-16 22:35:59)

Offline

#3 2023-08-17 14:20:08

mrbar2000
Member
From: Brazil
Registered: 2016-10-26
Posts: 56

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

I have edited my post.

ShowMessage(VarTypeAsText(VarType(vValue))) => SQLTimeStampVariantType

looking for this type i found in SqlTimst.pas

TSQLTimeStampVariantType = class(TPublishableVariantType)
SQLTimeStampVariantType: TSQLTimeStampVariantType = nil;

I think that this type of variant not is treated by TDocVariantData

How we can resolve this?

Last edited by mrbar2000 (2023-08-17 14:24:38)

Offline

#4 2023-08-17 14:48:26

tbo
Member
Registered: 2015-04-20
Posts: 335

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

mrbar2000 wrote:

How we can resolve this?

For example, like this:

var
  doc: TDocVariantData;
begin
  doc.InitFast;
  var value: Variant := VarSQLTimeStampCreate(Date);
  ShowMessage(VarTypeAsText(VarType(value)));
  doc.AddOrUpdateValue('MyInt', 10);
  doc.AddOrUpdateValue('MyBoolean', True);
  doc.AddOrUpdateValue('MyVariantDate', TDateTime(value));
  ShowMessage(doc.ToJson);

With best regards
Thomas

Offline

#5 2023-08-17 20:55:15

mrbar2000
Member
From: Brazil
Registered: 2016-10-26
Posts: 56

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

I know that using. FieldByName('DT_NASC').AsDateTime or VarToDateTime(...) works
but some other programmer can do not use this way and cause erros on runtime!

There are something that can be done on mormot internal to dont need make this conversion by hand????

Offline

#6 2023-08-17 21:49:32

tbo
Member
Registered: 2015-04-20
Posts: 335

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

mrbar2000 wrote:

There are something that can be done on mormot internal to dont need make this conversion by hand????

Take another look at my source code.

With best regards
Thomas

Offline

#7 2023-08-18 07:31:55

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

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

This SQLTimeStampVariantType seems to be an external variant type, not known by mORMot, with no built-in JSON support.

You just need to explicitly convert this type to a TDateTime / varDate kind of variant, to have proper JSON serialization.
This type has no built-in conversion to string - so even mORMot CustomVariantToJson() does not know what to do with this value.

This is up to the "programmers" to use the proper method.

EDIT: from what I can see, it sounds like if the SQLTimeStampVariant data lifetime is tied to the actual SQL query itself.
So you definitively should not include directly this kind of variant to a TDocVariantData store, because the variant value may be undefined outside of the SQL query execution.
Converting to a temporary TDateTime seems like the way to to go, both safe and square.

Offline

#8 2023-08-18 14:27:59

mrbar2000
Member
From: Brazil
Registered: 2016-10-26
Posts: 56

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

Thanks guys.

A last question. There are something function to validate a variant type to know when mormot does not know what to do with the value of this variant?

Offline

#9 2023-08-18 15:07:31

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

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

I don't think such a method exists.

Offline

#10 2023-08-18 15:52:21

tbo
Member
Registered: 2015-04-20
Posts: 335

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

You can play a bit with SQLTimeStampVariantType. Delphi just needs to know what you want:

var value: Variant := VarSQLTimeStampCreate(Now);  // <- Variant of type SQLTimeStampVariantType
ShowMessage(TDateTime(value).ToString);
ShowMessage(DateTimeToStr(value.AsDateTime));
ShowMessage(Format('Date: %d.%d.%d', [Word(value.Day), Word(value.Month), Word(value.Year)]));
ShowMessage(Format('Time: %d:%d:%d', [Word(value.Hour), Word(value.Minute), Word(value.Second)]));
var dt: TDateTime := value;
ShowMessage(dt.ToString);

Or have a look in Unit Data.SqlTimSt at class TSQLTimeStampData and TSQLTimeStampVariantType.

With best regards
Thomas

Offline

#11 2023-08-18 18:16:20

mrbar2000
Member
From: Brazil
Registered: 2016-10-26
Posts: 56

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

ab wrote:

I don't think such a method exists.

But its possible make it?

Where I can find on source code mormot.variants what vartypes it can treat?

Offline

#12 2023-08-18 18:18:23

mrbar2000
Member
From: Brazil
Registered: 2016-10-26
Posts: 56

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

tbo wrote:

You can play a bit with SQLTimeStampVariantType. Delphi just needs to know what you want:

var value: Variant := VarSQLTimeStampCreate(Now);  // <- Variant of type SQLTimeStampVariantType

Or have a look in Unit Data.SqlTimSt at class TSQLTimeStampData and TSQLTimeStampVariantType.

With best regards
Thomas

I know that if i convert the variant all works TBO. But I need avoid that my programmers fails during use of this. then I was thinking generate a exception on cases were the mormot cannot identify the vartype! Do you understand?

Offline

#13 2023-08-18 19:43:34

mrbar2000
Member
From: Brazil
Registered: 2016-10-26
Posts: 56

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

I solve this way. I hope that do not apear others type of variant. smile

function TCallServerParams.SetParam(const pName: String; pValue: Variant): ICallServerParams;
var
  vSqlTimeStamp: TSQLTimeStamp;
  vDateTime: TDateTime;
begin
  if VarIsSQLTimeStamp(pValue) then
  begin
    vSqlTimeStamp := VarToSQLTimeStamp(pValue);
    vDateTime := SQLTimeStampToDateTime(vSqlTimeStamp);
    FParams.AddOrUpdateValue(pName, vDateTime)
  end else
    FParams.AddOrUpdateValue(pName, pValue);
  Result := Self;
end;

Offline

#14 2023-08-21 20:31:46

mrbar2000
Member
From: Brazil
Registered: 2016-10-26
Posts: 56

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

I think that I found a problem guys.

var
  vParams1, vParams2: TDocVariantData;
  vJson: String;
begin
  vParams1.InitJson('{}');
  vQueryTmp := NewQuery(' SELECT * FROM EST_ENTRADA_ITEM WHERE CD_ENTRADA_ITEM = 8', []);
  vParams.AddOrUpdateValue('RetVariant1', vQueryTmp.FieldByName('CD_ENTRADA_ITEM').Value);  // integer field
  vParams.AddOrUpdateValue('RetVariant2', vQueryTmp.FieldByName('VL_TOTAL').Value);  // float field VarTypeAsText(VarType(pValue)) => double
  vParams.AddOrUpdateValue('RetVariant3', vQueryTmp.FieldByName('ST_NOTA_ITEM').Value); // smallint field
  vParams.AddOrUpdateValue('RetVariant4', vQueryTmp.FieldByName('DT_CONFIRMACAO').Value);  // datetime field
  vParams.AddOrUpdateValue('RetVariant5', vQueryTmp.FieldByName('VL_RECEBIDO').Value); // numeric(15,2) field (currency)

  vJson := vParams1.ToJson;
  // vJson = '{"RetVariant1":8,"RetVariant2":39.9000015258789,"RetVariant3":1,"RetVariant4":"2019-03-15T16:12:21","RetVariant5":29.24}'

  vParams2.InitJson(vJson);
  vJson := vParams1.ToJson;
  // '{"RetVariant1":8,"RetVariant2":"39.9000015258789","RetVariant3":1,"RetVariant4":"2019-03-15T16:12:21","RetVariant5":29.24}'

Why RetVariant2 change to a string? Why not hold 39.9000015258789?

I see that if I does
vParams2.InitJson(vJson, [dvoAllowDoubleValue]);
the value is converted correctly.

by default the options is []?

Last edited by mrbar2000 (2023-08-21 20:41:47)

Offline

#15 2023-08-22 06:34:38

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

Re: TDocVariantData.AddOrUpdateValue seens dont work to variants values

This is as expected, because IEEE floats have a precision lost when transmitted over JSON..
https://synopse.info/files/html/Synopse … l#TITL_194

So you can e.g. write:

vParams1.Init(mFastFloat, dvObject);

Offline

Board footer

Powered by FluxBB