Permalink
Browse files

Merge pull request #38 from arturosevilla/nullinmemberexpressionfix

Detects when a MemberExpression returns null and adjusts it as a ConstantExpression
  • Loading branch information...
2 parents 3c3ae3d + 1726e71 commit e8f7c192f4da80480b5d66cb076519011d01a40f @tathamoddie tathamoddie committed Mar 6, 2014
@@ -216,6 +216,45 @@ void VisitParameterMember(MemberExpression node)
void VisitConstantMember(MemberExpression node)
{
var value = GetConstantExpressionValue(node);
+
+ // if the value is null, sending a parameter would return something we don't want.
+ // A PropertyBag within the Neo4j server cannot have property with null value, that is, having a null
+ // property is the same as not having the property.
+ var text = TextOutput.ToString();
+ if (value == null && text.EndsWith(NotEqual))
+ {
+ TextOutput.Remove(TextOutput.ToString().LastIndexOf(NotEqual, StringComparison.Ordinal), NotEqual.Length);
+ if (capabilities.SupportsNullComparisonsWithIsOperator)
+ {
+ TextOutput.Append(" is not null");
+ }
+ else
+ {
+ TextOutput.Remove(TextOutput.ToString().LastIndexOf(lastWrittenMemberName, StringComparison.Ordinal), lastWrittenMemberName.Length);
+ TextOutput.Append(string.Format("has({0})", lastWrittenMemberName));
+ }
+
+ // no further processing is required
+ return;
+ }
+
+ if (value == null && text.EndsWith(Equal))
+ {
+ TextOutput.Remove(TextOutput.ToString().LastIndexOf(Equal, StringComparison.Ordinal), Equal.Length);
+ if (capabilities.SupportsNullComparisonsWithIsOperator)
+ {
+ TextOutput.Append(" is null");
+ }
+ else
+ {
+ TextOutput.Remove(TextOutput.ToString().LastIndexOf(lastWrittenMemberName, StringComparison.Ordinal), lastWrittenMemberName.Length);
+ TextOutput.Append(string.Format("not(has({0}))", lastWrittenMemberName));
+ }
+
+ // no further processing is required
+ return;
+ }
+
if (capabilities.SupportsPropertySuffixesForControllingNullComparisons && value != null)
{
SwapNullQualifierFromDefaultTrueToDefaultFalseIfTextEndsWithAny(new[]
@@ -16,6 +16,11 @@ class Foo
// ReSharper restore ClassNeverInstantiated.Local
// ReSharper restore UnusedAutoPropertyAccessor.Local
+ class MockWithNullField
+ {
+ public string NullField { get; set; }
+ }
+
[Test]
public void ComparePropertiesAcrossEntitiesEqual()
{
@@ -159,6 +159,66 @@ public void ForPre20VersionsEvaluateFalseWhenComparingMissingNullablePropertyLes
}
[Test]
+ public void ForPre20VersionsEvaluateTrueWhenComparingMissingNullablePropertyToNullProperty()
+ {
+ var parameters = new Dictionary<string, object>();
+ var fooWithNulls = new Foo
+ {
+ NullableBar = null
+ };
+ Expression<Func<Foo, bool>> expression = foo => foo.NullableBar == fooWithNulls.NullableBar;
+
+ var result = CypherWhereExpressionBuilder.BuildText(expression, v => CreateParameter(parameters, v), CypherCapabilities.Cypher19);
+
+ Assert.AreEqual("(foo.NullableBar? is null)", result);
+ }
+
+ [Test]
+ public void For20VersionsEvaluateTrueWhenComparingMissingNullablePropertyToNullProperty()
+ {
+ var parameters = new Dictionary<string, object>();
+ var fooWithNulls = new Foo
+ {
+ NullableBar = null
+ };
+ Expression<Func<Foo, bool>> expression = foo => foo.NullableBar == fooWithNulls.NullableBar;
+
+ var result = CypherWhereExpressionBuilder.BuildText(expression, v => CreateParameter(parameters, v), CypherCapabilities.Cypher20);
+
+ Assert.AreEqual("(not(has(foo.NullableBar)))", result);
+ }
+
+ [Test]
+ public void ForPre20VersionsEvaluateTrueWhenComparingNotMissingNullablePropertyToNullProperty()
+ {
+ var parameters = new Dictionary<string, object>();
+ var fooWithNulls = new Foo
+ {
+ NullableBar = null
+ };
+ Expression<Func<Foo, bool>> expression = foo => foo.NullableBar != fooWithNulls.NullableBar;
+
+ var result = CypherWhereExpressionBuilder.BuildText(expression, v => CreateParameter(parameters, v), CypherCapabilities.Cypher19);
+
+ Assert.AreEqual("(foo.NullableBar? is not null)", result);
+ }
+
+ [Test]
+ public void For20VersionsEvaluateTrueWhenComparingNotMissingNullablePropertyToNullProperty()
+ {
+ var parameters = new Dictionary<string, object>();
+ var fooWithNulls = new Foo
+ {
+ NullableBar = null
+ };
+ Expression<Func<Foo, bool>> expression = foo => foo.NullableBar != fooWithNulls.NullableBar;
+
+ var result = CypherWhereExpressionBuilder.BuildText(expression, v => CreateParameter(parameters, v), CypherCapabilities.Cypher20);
+
+ Assert.AreEqual("(has(foo.NullableBar))", result);
+ }
+
+ [Test]
public void ForPre20VersionsEvaluateTrueWhenComparingMissingNullablePropertyToNull()
{
var parameters = new Dictionary<string, object>();

0 comments on commit e8f7c19

Please sign in to comment.