Invalid date parameter format with nullables and MappedAs
Description
Environment
is related to
Activity
Frédéric Delaporte March 17, 2017 at 4:39 PM
PR done.
Frédéric Delaporte March 17, 2017 at 3:12 PM
The expression constant seen at HQL tree construction is still a DateTime?
because a second partial expression tree evaluation occurs from NhRelinqQueryParser
, after the parameters map build in NhLinqExpression
, when its Translate
method is called.
The parameters map build alters the expression by removing the non "evaluatable" MappedAs
call, yielding instead its first parameter value (the DateTime
in this case). This causes the wrapping convert to nullable to be "evaluatable", while it was not when the MappedAs
was still there.
Then the second partial expression tree evaluation further alter the expression, transforming the DateTime
constant to a DateTime?
, causing it to be no more "parameterized".
All that is worsen by the fact that the expression Key
has already been computed before this second evaluation, causing it to ignore the DateTime
value since it is supposed to be "parameterized". This causes the additional parameter value caching bug.
The NhRelinqQueryParser
partial expression tree evaluation seems unneeded, since it is used solely by NhLinqExpression
, which has already done it within its constructor. It looks safe to me to remove it (and all tests passes, going to PR that). Unfortunately, this may be a possible breaking change for some external library, since NhRelinqQueryParser
is public and could have other usages outside of NHibernate.
Frédéric Delaporte March 16, 2017 at 6:05 PMEdited
It seems the root of the trouble is the comparison of a "to be parameterized" DateTime
to a nullable property: the resulting expression tree wrap the DateTime
inside a convert causing it to be identified as a parameter candidate with a nullable DateTime?
type.
But when we additionally call MappedAs
on it, the wrapping convert can no more be evaluated by Re-Linq since MappedAs
cannot be evaluated. This causes somehow (still have to identify where precisely) a parameter type mismatch: the ConstantToParameterMap
ends up filled with a non nullable DateTime
key (in ExpressionParameterVisitor.VisitMethodCallExpression
) while the hql tree constant expression is still a nullable DateTime?
(not determined yet from where it comes). This causes it to be not parameterized in HqlGeneratorExpressionTreeVisitor.VisitConstantExpression
.
I wonder if we should strive for eliminating this mismatch, or if we should support it by making ConstantToParameterMap
considers such values (one nullable, the other not, but having the same value indeed) equals.
Frédéric Delaporte March 15, 2017 at 7:04 PM
Well, there is actually a parameter value caching bug, but its reproduction conditions are so closed to those of this bug (requires comparison to nullable property and usage of MappedAs) that it is very likely to have the same root cause.
So I have just added some additional test cases in this bug.
Frédéric Delaporte March 15, 2017 at 5:58 PM
Test cases available here.
I intend to try fix this, but not today. I think I have found another more critical bug while elaborating those test cases, something similar to but with datetime parameters. I will try to sort this out first (and then issue another Jira if I end up confirming this another issue).
In some circumstances, the Linq to NHibernate provider emits datetime parameters as string literals formatted to short date time string, using current locales.
This may result in an invalid date emitted in the SQL.
This trouble happens when comparing a nullable
DateTime?
property of an entity to aDateTime
value with its type overloaded throughMappedAs
to adate/datetime/timestamp
type.Does emit with French locales:
This fails if the SQL user language is English.
The same query on a non nullable property yields a quite different and more robust SQL: