I am getting answer from DB and need to check if it is not null before placing it's to value.
I tried few variants of checking, but my code is still crush:
foreach(i, point;myPointsLonLat)
{
try
{
carGPSPoint cargpspoint;
cargpspoint.id = point[0].coerce!ulong;
cargpspoint.recordDate = DateTime.fromSimpleString(point[1].coerce!string).toISOExtString(); // some magic to get string in 2016-10-31T15:37:24 format
if(point[2].hasValue) //check if we have some data
cargpspoint.velocity = point[2].coerce!double;
if(point[3].hasValue)
cargpspoint.lat = point[3].coerce!double;
if(point[4].hasValue)
cargpspoint.lon = point[4].coerce!double;
cargpspoints[i] = cargpspoint;
b.next();
}
catch(Exception e)
{
writeln("\n----------------------------ERRRRRR-----------------------");
writeln(point);
writeln("1111: ", point[2].coerce!double);
writeln("2222: ", point[3].coerce!double);
writeln("3333: ", point[4].coerce!double);
writeln(e.msg);
}
}
Output:
----------------------------ERRRRRR-----------------------
Row([1478698195002489886, 2016-Nov-09 13:29:55, 153, null, null], [false, false, false, true, true])
1111: 153
object.Exception@C:\D\dmd2\windows\bin\..\..\src\phobos\std\variant.d(823): Type typeof(null) does not convert to double
As you see it's print 1111: 153. But crashing on other null variables.
I also tried:
if(point[2].type !is null) //check if we have some data
cargpspoint.velocity = point[2].coerce!double;
if(point[3].type !is null)
cargpspoint.lat = point[3].coerce!double;
if(point[4].type !is null)
cargpspoint.lon = point[4].coerce!double;
Same result. What I am doing wrong?
hasValue checks if it has been initialized, and the database library does initialize it, just to null.
I'd suggest checking the type directly:
if(auto pt = point[3].peek!double)
cargpspoint.lat = *pt;
peek checks if it has that exact type and returns a pointer to the value if it does. It is an exact match, meaning if it is float or something else, this won't work, so make sure you are matching what the database gives you (that's best for performance and accuracy anyway), but then it will be null and thus skip the if it isn't right and you can set if it is.
Just repeat that pattern for all your points.
Here's a solution to implement the isNull function and a hasValue2 function in the way you wanted:
import std.variant;
import std.stdio;
void main()
{
Variant v;
writefln("%s %s %s", v.hasValue, !v.isNull, v.hasValue2);
v = null;
writefln("%s %s %s", v.hasValue, !v.isNull, v.hasValue2);
v = "";
writefln("%s %s %s", v.hasValue, !v.isNull, v.hasValue2);
}
@property bool isNull(Variant v)
{
return v.type == typeid(typeof(null));
}
@property bool hasValue2(Variant v)
{
return v.hasValue && !v.isNull;
}
Result:
false true false
true false false
true true true
So in your code you should check for typeid(typeof(null)) instead. You might be right that hasValue should check for typeof(null) as well. IIRC Variant predates typeof(null), nowadays it might even make sense to use only typeof(null) and never allow uninitialized Variants.
Please start a discussion at https://forum.dlang.org/group/general or file a bug report at https://issues.dlang.org to discuss this with the appropriate library maintainers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With