Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
  • 3 commits
  • 3 files changed
  • 0 commit comments
  • 2 contributors
Commits on Mar 05, 2014
@arturosevilla arturosevilla Detects when a MemberExpression returns null and adjusts it as a Cons…
…tantExpression

Neo4j doesn't consider null as valid values for PropertyBags
(relationships and nodes).
Neo4jClient could have a MemberExpression in a Where() construct and it
could detect it if was in reality a ConstantExpression, however it just
sends the value as parameter regardless if it's a null value.

This commit fixes that by having the same behavior that occurs in
VisitConstant(ConstantExpression) if it detects a null value.
38868f3
Commits on Mar 06, 2014
@arturosevilla arturosevilla Added unit tests for CypherWhereExpressionVisitor.VisitConstantMember()
The unit tests from the last commit was moved from the
CypherFluentQueryWhereTests to CypherWhereExpressionBuilderTests and added
three more unit tests for all logic branches within this method.
1726e71
@tathamoddie tathamoddie Merge pull request #38 from arturosevilla/nullinmemberexpressionfix
Detects when a MemberExpression returns null and adjusts it as a ConstantExpression
e8f7c19
View
39 Neo4jClient/Cypher/CypherWhereExpressionVisitor.cs
@@ -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[]
View
5 Test/Cypher/CypherFluentQueryWhereTests.cs
@@ -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()
{
View
60 Test/Cypher/CypherWhereExpressionBuilderTests.cs
@@ -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>();

No commit comments for this range

Something went wrong with that request. Please try again.