You are not logged in.
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
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
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
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
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
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
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.
Online
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
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
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
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
I solve this way. I hope that do not apear others type of variant.
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
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
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);
Online