Reputation: 9859
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?
Upvotes: 3
Views: 1693
Reputation: 517
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.
Upvotes: 2
Reputation: 25595
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.
Upvotes: 2