Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
小 白蛋
Neo4jsource
Commits
c3e14d12
Commit
c3e14d12
authored
5 years ago
by
Satia Herfert
Browse files
Options
Download
Email Patches
Plain Diff
Adjust NaN behavior to new CLG rules.
parent
4e3ba6d9
No related merge requests found
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
community/codegen/src/main/scala/org/neo4j/codegen/api/IntermediateRepresentation.scala
+3
-1
...la/org/neo4j/codegen/api/IntermediateRepresentation.scala
community/community-it/kernel-it/src/test/java/org/neo4j/kernel/api/index/IndexProviderCompatibilityTestSuite.java
+1
-0
...kernel/api/index/IndexProviderCompatibilityTestSuite.java
community/community-it/kernel-it/src/test/java/org/neo4j/kernel/api/index/SimpleIndexAccessorCompatibility.java
+93
-11
...4j/kernel/api/index/SimpleIndexAccessorCompatibility.java
community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/TransactionBoundQueryContext.scala
+2
-2
...al/runtime/interpreted/TransactionBoundQueryContext.scala
community/cypher/interpreted-runtime/src/test/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/ComparablePredicateTest.scala
+0
-1
...untime/interpreted/commands/ComparablePredicateTest.scala
community/cypher/runtime-util/src/main/java/org/neo4j/cypher/operations/CypherBoolean.java
+16
-5
.../main/java/org/neo4j/cypher/operations/CypherBoolean.java
community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/IndexQuery.java
+12
-30
...c/main/java/org/neo4j/internal/kernel/api/IndexQuery.java
community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/NumberRangePredicate.java
+56
-0
...a/org/neo4j/internal/kernel/api/NumberRangePredicate.java
community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/NumberType.java
+1
-1
...n/java/org/neo4j/kernel/impl/index/schema/NumberType.java
community/values/src/main/java/org/neo4j/values/AnyValue.java
+21
-0
...unity/values/src/main/java/org/neo4j/values/AnyValue.java
community/values/src/main/java/org/neo4j/values/storable/Value.java
+4
-0
...values/src/main/java/org/neo4j/values/storable/Value.java
community/values/src/test/java/org/neo4j/values/storable/NumberValuesTest.java
+4
-4
...test/java/org/neo4j/values/storable/NumberValuesTest.java
community/values/src/test/java/org/neo4j/values/storable/ValuesTest.java
+34
-0
...s/src/test/java/org/neo4j/values/storable/ValuesTest.java
community/values/src/test/java/org/neo4j/values/utils/AnyValueTestUtil.java
+6
-6
...rc/test/java/org/neo4j/values/utils/AnyValueTestUtil.java
with
253 additions
and
61 deletions
+253
-61
community/codegen/src/main/scala/org/neo4j/codegen/api/IntermediateRepresentation.scala
+
3
-
1
View file @
c3e14d12
...
...
@@ -642,7 +642,9 @@ object IntermediateRepresentation {
def
trueValue
:
IntermediateRepresentation
=
getStatic
[
Values
,
BooleanValue
](
"TRUE"
)
def
falseValue
:
IntermediateRepresentation
=
getStatic
[
Values
,
BooleanValue
](
"FALSE"
)
def
falseValue
:
IntermediateRepresentation
=
getStatic
[
Values
,
BooleanValue
](
"FALSE"
)
def
isNaN
(
value
:
IntermediateRepresentation
)
:
IntermediateRepresentation
=
and
(
instanceOf
[
FloatingPointValue
](
value
),
invoke
(
cast
[
FloatingPointValue
](
value
),
method
[
FloatingPointValue
,
Boolean
](
"isNaN"
)))
def
constant
(
value
:
Any
)
:
IntermediateRepresentation
=
Constant
(
value
)
...
...
This diff is collapsed.
Click to expand it.
community/community-it/kernel-it/src/test/java/org/neo4j/kernel/api/index/IndexProviderCompatibilityTestSuite.java
+
1
-
0
View file @
c3e14d12
...
...
@@ -161,6 +161,7 @@ public abstract class IndexProviderCompatibilityTestSuite
Arrays
.
asList
(
Values
.
of
(
"string1"
),
Values
.
of
(
42
),
Values
.
of
(
Double
.
NaN
),
Values
.
of
(
true
),
Values
.
of
(
new
char
[]{
'a'
,
'z'
}
),
Values
.
of
(
new
String
[]{
"arrayString1"
,
"arraysString2"
}
),
...
...
This diff is collapsed.
Click to expand it.
community/community-it/kernel-it/src/test/java/org/neo4j/kernel/api/index/SimpleIndexAccessorCompatibility.java
+
93
-
11
View file @
c3e14d12
...
...
@@ -35,11 +35,13 @@ import java.time.ZoneOffset;
import
java.time.ZonedDateTime
;
import
java.time.temporal.ChronoUnit
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.function.Supplier
;
import
java.util.stream.Collectors
;
import
org.neo4j.internal.kernel.api.IndexQuery
;
import
org.neo4j.internal.schema.IndexOrder
;
...
...
@@ -815,26 +817,99 @@ public abstract class SimpleIndexAccessorCompatibility extends IndexAccessorComp
shouldRangeSeekInOrder
(
IndexOrder
.
DESCENDING
,
o0
,
o1
,
o2
,
o3
,
o4
,
o5
);
}
private
void
shouldRangeSeekInOrder
(
IndexOrder
order
,
Object
o0
,
Object
o1
,
Object
o2
,
Object
o3
,
Object
o4
,
Object
o5
)
throws
Exception
@Test
public
void
shouldRangeSeekAscendingWithoutFindingNanForOpenEnd
()
throws
Exception
{
Object
o0
=
0
;
Object
o1
=
1.0
;
Object
o2
=
2.5
;
Object
o3
=
3
;
Object
o4
=
4
;
Object
o5
=
5
;
Object
o6
=
Double
.
POSITIVE_INFINITY
;
Object
o7
=
Double
.
NaN
;
shouldRangeSeekInOrderWithExpectedSize
(
IndexOrder
.
ASCENDING
,
RangeSeekMode
.
OPEN_END
,
7
,
o0
,
o1
,
o2
,
o3
,
o4
,
o5
,
o6
,
o7
);
}
@Test
public
void
shouldRangeSeekDescendingWithoutFindingNanForOpenEnd
()
throws
Exception
{
Object
o0
=
0
;
Object
o1
=
1.0
;
Object
o2
=
2.5
;
Object
o3
=
3
;
Object
o4
=
4
;
Object
o5
=
5
;
Object
o6
=
Double
.
POSITIVE_INFINITY
;
Object
o7
=
Double
.
NaN
;
shouldRangeSeekInOrderWithExpectedSize
(
IndexOrder
.
DESCENDING
,
RangeSeekMode
.
OPEN_END
,
7
,
o0
,
o1
,
o2
,
o3
,
o4
,
o5
,
o6
,
o7
);
}
@Test
public
void
shouldRangeSeekAscendingWithoutFindingNanForOpenStart
()
throws
Exception
{
Object
o0
=
Double
.
NaN
;
Object
o1
=
1.0
;
Object
o2
=
2.5
;
Object
o3
=
3
;
Object
o4
=
4
;
Object
o5
=
5
;
Object
o6
=
Double
.
POSITIVE_INFINITY
;
shouldRangeSeekInOrderWithExpectedSize
(
IndexOrder
.
ASCENDING
,
RangeSeekMode
.
OPEN_START
,
6
,
o0
,
o1
,
o2
,
o3
,
o4
,
o5
,
o6
);
}
@Test
public
void
shouldRangeSeekDescendingWithoutFindingNanForOpenStart
()
throws
Exception
{
Object
o0
=
Double
.
NaN
;
Object
o1
=
1.0
;
Object
o2
=
2.5
;
Object
o3
=
3
;
Object
o4
=
4
;
Object
o5
=
5
;
Object
o6
=
Double
.
POSITIVE_INFINITY
;
shouldRangeSeekInOrderWithExpectedSize
(
IndexOrder
.
DESCENDING
,
RangeSeekMode
.
OPEN_START
,
6
,
o0
,
o1
,
o2
,
o3
,
o4
,
o5
,
o6
);
}
private
void
shouldRangeSeekInOrder
(
IndexOrder
order
,
Object
...
objects
)
throws
Exception
{
shouldRangeSeekInOrderWithExpectedSize
(
order
,
RangeSeekMode
.
CLOSED
,
objects
.
length
,
objects
);
}
private
void
shouldRangeSeekInOrderWithExpectedSize
(
IndexOrder
order
,
RangeSeekMode
rangeSeekMode
,
int
expectedSize
,
Object
...
objects
)
throws
Exception
{
IndexQuery
range
=
range
(
100
,
Values
.
of
(
o0
),
true
,
Values
.
of
(
o5
),
true
);
IndexQuery
range
;
switch
(
rangeSeekMode
)
{
case
CLOSED:
range
=
range
(
100
,
Values
.
of
(
objects
[
0
]
),
true
,
Values
.
of
(
objects
[
objects
.
length
-
1
]
),
true
);
break
;
case
OPEN_END:
range
=
range
(
100
,
Values
.
of
(
objects
[
0
]
),
true
,
null
,
false
);
break
;
case
OPEN_START:
range
=
range
(
100
,
null
,
false
,
Values
.
of
(
objects
[
objects
.
length
-
1
]
),
true
);
break
;
default
:
throw
new
IllegalStateException
();
}
IndexOrder
[]
indexOrders
=
orderCapability
(
range
);
Assume
.
assumeTrue
(
"Assume support for order "
+
order
,
ArrayUtils
.
contains
(
indexOrders
,
order
)
);
updateAndCommit
(
asList
(
add
(
1
,
descriptor
.
schema
(),
o0
),
add
(
1
,
descriptor
.
schema
(),
o5
),
add
(
1
,
descriptor
.
schema
(),
o1
),
add
(
1
,
descriptor
.
schema
(),
o4
),
add
(
1
,
descriptor
.
schema
(),
o2
),
add
(
1
,
descriptor
.
schema
(),
o3
)
)
);
List
<
IndexEntryUpdate
<?>>
additions
=
Arrays
.
stream
(
objects
).
map
(
o
->
add
(
1
,
descriptor
.
schema
(),
o
)
).
collect
(
Collectors
.
toList
()
);
Collections
.
shuffle
(
additions
,
random
.
random
()
);
updateAndCommit
(
additions
);
SimpleNodeValueClient
client
=
new
SimpleNodeValueClient
();
try
(
AutoCloseable
ignored
=
query
(
client
,
order
,
range
)
)
{
List
<
Long
>
seenIds
=
assertClientReturnValuesInOrder
(
client
,
order
);
assertThat
(
seenIds
.
size
(),
equalTo
(
6
)
);
assertThat
(
seenIds
.
size
(),
equalTo
(
expectedSize
)
);
}
}
...
...
@@ -1163,4 +1238,11 @@ public abstract class SimpleIndexAccessorCompatibility extends IndexAccessorComp
assertThat
(
query
(
IndexQuery
.
exists
(
1
)
),
equalTo
(
asList
(
1L
,
2L
,
3L
)
)
);
}
}
private
enum
RangeSeekMode
{
CLOSED
,
OPEN_END
,
OPEN_START
}
}
This diff is collapsed.
Click to expand it.
community/cypher/interpreted-runtime/src/main/scala/org/neo4j/cypher/internal/runtime/interpreted/TransactionBoundQueryContext.scala
+
2
-
2
View file @
c3e14d12
...
...
@@ -56,7 +56,7 @@ import org.neo4j.kernel.impl.core.TransactionalEntityFactory
import
org.neo4j.kernel.impl.util.ValueUtils.
{
fromNodeEntity
,
fromRelationshipEntity
}
import
org.neo4j.kernel.impl.util.
{
DefaultValueMapper
,
ValueUtils
}
import
org.neo4j.storageengine.api.RelationshipVisitor
import
org.neo4j.values.storable.
{
TextValue
,
Value
,
Values
}
import
org.neo4j.values.storable.
{
FloatingPointValue
,
TextValue
,
Value
,
Values
}
import
org.neo4j.values.virtual._
import
org.neo4j.values.
{
AnyValue
,
ValueMapper
}
...
...
@@ -217,7 +217,7 @@ sealed class TransactionBoundQueryContext(val transactionalContext: Transactiona
val
impossiblePredicate
=
predicates
.
exists
{
case
p
:
IndexQuery.ExactPredicate
=>
p
.
value
()
eq
Values
.
NO_VALUE
case
p
:
IndexQuery.ExactPredicate
=>
(
p
.
value
()
eq
Values
.
NO_VALUE
)
||
(
p
.
value
().
isInstanceOf
[
FloatingPointValue
]
&&
p
.
value
().
asInstanceOf
[
FloatingPointValue
].
isNaN
)
case
_:
IndexQuery.ExistsPredicate
if
predicates.length
>
1
=>
false
case
p
:
IndexQuery
=>
!
RANGE_SEEKABLE_VALUE_GROUPS
.
contains
(
p
.
valueGroup
())
...
...
This diff is collapsed.
Click to expand it.
community/cypher/interpreted-runtime/src/test/scala/org/neo4j/cypher/internal/runtime/interpreted/commands/ComparablePredicateTest.scala
+
0
-
1
View file @
c3e14d12
...
...
@@ -48,7 +48,6 @@ class ComparablePredicateTest extends CypherFunSuite {
Long
.
MaxValue
,
Double
.
MaxValue
,
Double
.
PositiveInfinity
,
Double
.
NaN
,
null
).
flatMap
{
case
null
=>
Seq
(
null
)
...
...
This diff is collapsed.
Click to expand it.
community/cypher/runtime-util/src/main/java/org/neo4j/cypher/operations/CypherBoolean.java
+
16
-
5
View file @
c3e14d12
...
...
@@ -139,6 +139,10 @@ public final class CypherBoolean
public
static
Value
lessThan
(
AnyValue
lhs
,
AnyValue
rhs
)
{
if
(
AnyValue
.
isNanAndNumber
(
lhs
,
rhs
)
)
{
return
FALSE
;
}
Comparison
comparison
=
AnyValues
.
TERNARY_COMPARATOR
.
ternaryCompare
(
lhs
,
rhs
);
switch
(
comparison
)
{
...
...
@@ -158,6 +162,10 @@ public final class CypherBoolean
public
static
Value
lessThanOrEqual
(
AnyValue
lhs
,
AnyValue
rhs
)
{
if
(
AnyValue
.
isNanAndNumber
(
lhs
,
rhs
)
)
{
return
FALSE
;
}
Comparison
comparison
=
AnyValues
.
TERNARY_COMPARATOR
.
ternaryCompare
(
lhs
,
rhs
);
switch
(
comparison
)
{
...
...
@@ -177,6 +185,10 @@ public final class CypherBoolean
public
static
Value
greaterThan
(
AnyValue
lhs
,
AnyValue
rhs
)
{
if
(
AnyValue
.
isNanAndNumber
(
lhs
,
rhs
)
)
{
return
FALSE
;
}
Comparison
comparison
=
AnyValues
.
TERNARY_COMPARATOR
.
ternaryCompare
(
lhs
,
rhs
);
switch
(
comparison
)
{
...
...
@@ -196,6 +208,10 @@ public final class CypherBoolean
public
static
Value
greaterThanOrEqual
(
AnyValue
lhs
,
AnyValue
rhs
)
{
if
(
AnyValue
.
isNanAndNumber
(
lhs
,
rhs
)
)
{
return
FALSE
;
}
Comparison
comparison
=
AnyValues
.
TERNARY_COMPARATOR
.
ternaryCompare
(
lhs
,
rhs
);
switch
(
comparison
)
{
...
...
@@ -243,11 +259,6 @@ public final class CypherBoolean
return
seenUndefined
?
NO_VALUE
:
Values
.
FALSE
;
}
private
static
boolean
isNan
(
AnyValue
value
)
{
return
value
instanceof
FloatingPointValue
&&
((
FloatingPointValue
)
value
).
isNaN
();
}
private
static
final
class
BooleanMapper
implements
ValueMapper
<
Value
>
{
@Override
...
...
This diff is collapsed.
Click to expand it.
community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/IndexQuery.java
+
12
-
30
View file @
c3e14d12
...
...
@@ -78,7 +78,7 @@ public abstract class IndexQuery
Number
from
,
boolean
fromInclusive
,
Number
to
,
boolean
toInclusive
)
{
return
new
NumberRangePredicate
(
propertyKeyId
,
return
NumberRangePredicate
.
create
(
propertyKeyId
,
from
==
null
?
null
:
Values
.
numberValue
(
from
),
fromInclusive
,
to
==
null
?
null
:
Values
.
numberValue
(
to
),
toInclusive
);
}
...
...
@@ -105,7 +105,7 @@ public abstract class IndexQuery
switch
(
valueGroup
)
{
case
NUMBER:
return
new
NumberRangePredicate
(
propertyKeyId
,
return
NumberRangePredicate
.
create
(
propertyKeyId
,
(
NumberValue
)
from
,
fromInclusive
,
(
NumberValue
)
to
,
toInclusive
);
...
...
@@ -263,7 +263,7 @@ public abstract class IndexQuery
public
static
final
class
ExistsPredicate
extends
IndexQuery
{
ExistsPredicate
(
int
propertyKeyId
)
private
ExistsPredicate
(
int
propertyKeyId
)
{
super
(
propertyKeyId
);
}
...
...
@@ -297,7 +297,7 @@ public abstract class IndexQuery
{
private
final
Value
exactValue
;
ExactPredicate
(
int
propertyKeyId
,
Object
value
)
private
ExactPredicate
(
int
propertyKeyId
,
Object
value
)
{
super
(
propertyKeyId
);
this
.
exactValue
=
value
instanceof
Value
?
(
Value
)
value
:
Values
.
of
(
value
);
...
...
@@ -419,7 +419,8 @@ public abstract class IndexQuery
{
private
final
CoordinateReferenceSystem
crs
;
GeometryRangePredicate
(
int
propertyKeyId
,
CoordinateReferenceSystem
crs
,
PointValue
from
,
boolean
fromInclusive
,
PointValue
to
,
boolean
toInclusive
)
private
GeometryRangePredicate
(
int
propertyKeyId
,
CoordinateReferenceSystem
crs
,
PointValue
from
,
boolean
fromInclusive
,
PointValue
to
,
boolean
toInclusive
)
{
super
(
propertyKeyId
,
ValueGroup
.
GEOMETRY
,
from
,
fromInclusive
,
to
,
toInclusive
);
this
.
crs
=
crs
;
...
...
@@ -470,28 +471,9 @@ public abstract class IndexQuery
}
}
public
static
final
class
NumberRangePredicate
extends
RangePredicate
<
NumberValue
>
{
NumberRangePredicate
(
int
propertyKeyId
,
NumberValue
from
,
boolean
fromInclusive
,
NumberValue
to
,
boolean
toInclusive
)
{
super
(
propertyKeyId
,
ValueGroup
.
NUMBER
,
from
,
fromInclusive
,
to
,
toInclusive
);
}
public
Number
from
()
{
return
from
==
null
?
null
:
from
.
asObject
();
}
public
Number
to
()
{
return
to
==
null
?
null
:
to
.
asObject
();
}
}
public
static
final
class
TextRangePredicate
extends
RangePredicate
<
TextValue
>
{
TextRangePredicate
(
int
propertyKeyId
,
TextValue
from
,
boolean
fromInclusive
,
TextValue
to
,
private
TextRangePredicate
(
int
propertyKeyId
,
TextValue
from
,
boolean
fromInclusive
,
TextValue
to
,
boolean
toInclusive
)
{
super
(
propertyKeyId
,
ValueGroup
.
TEXT
,
from
,
fromInclusive
,
to
,
toInclusive
);
...
...
@@ -510,7 +492,7 @@ public abstract class IndexQuery
public
abstract
static
class
StringPredicate
extends
IndexQuery
{
StringPredicate
(
int
propertyKeyId
)
private
StringPredicate
(
int
propertyKeyId
)
{
super
(
propertyKeyId
);
}
...
...
@@ -538,7 +520,7 @@ public abstract class IndexQuery
{
private
final
TextValue
prefix
;
StringPrefixPredicate
(
int
propertyKeyId
,
TextValue
prefix
)
private
StringPrefixPredicate
(
int
propertyKeyId
,
TextValue
prefix
)
{
super
(
propertyKeyId
);
//we know utf8 values are coming from the index so optimize for that
...
...
@@ -567,7 +549,7 @@ public abstract class IndexQuery
{
private
final
TextValue
contains
;
StringContainsPredicate
(
int
propertyKeyId
,
TextValue
contains
)
private
StringContainsPredicate
(
int
propertyKeyId
,
TextValue
contains
)
{
super
(
propertyKeyId
);
//we know utf8 values are coming from the index so optimize for that
...
...
@@ -596,7 +578,7 @@ public abstract class IndexQuery
{
private
final
TextValue
suffix
;
StringSuffixPredicate
(
int
propertyKeyId
,
TextValue
suffix
)
private
StringSuffixPredicate
(
int
propertyKeyId
,
TextValue
suffix
)
{
super
(
propertyKeyId
);
//we know utf8 values are coming from the index so optimize for that
...
...
@@ -625,7 +607,7 @@ public abstract class IndexQuery
{
private
final
String
query
;
FulltextSearchPredicate
(
String
query
)
private
FulltextSearchPredicate
(
String
query
)
{
super
(
TokenRead
.
NO_TOKEN
);
this
.
query
=
query
;
...
...
This diff is collapsed.
Click to expand it.
community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/NumberRangePredicate.java
0 → 100644
+
56
-
0
View file @
c3e14d12
/*
* Copyright (c) 2002-2019 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package
org.neo4j.internal.kernel.api
;
import
org.neo4j.values.storable.NumberValue
;
import
org.neo4j.values.storable.ValueGroup
;
import
org.neo4j.values.storable.Values
;
public
final
class
NumberRangePredicate
extends
IndexQuery
.
RangePredicate
<
NumberValue
>
{
private
NumberRangePredicate
(
int
propertyKeyId
,
NumberValue
from
,
boolean
fromInclusive
,
NumberValue
to
,
boolean
toInclusive
)
{
super
(
propertyKeyId
,
ValueGroup
.
NUMBER
,
from
,
fromInclusive
,
to
,
toInclusive
);
}
static
org
.
neo4j
.
internal
.
kernel
.
api
.
NumberRangePredicate
create
(
int
propertyKeyId
,
NumberValue
from
,
boolean
fromInclusive
,
NumberValue
to
,
boolean
toInclusive
)
{
// For range queries with numbers we need to redefine the upper bound from NaN to positive infinity.
// The reason is that we do not want to find NaNs for seeks, but for full scans we do.
if
(
to
==
null
)
{
to
=
Values
.
doubleValue
(
Double
.
POSITIVE_INFINITY
);
toInclusive
=
true
;
}
return
new
org
.
neo4j
.
internal
.
kernel
.
api
.
NumberRangePredicate
(
propertyKeyId
,
from
,
fromInclusive
,
to
,
toInclusive
);
}
public
Number
from
()
{
return
from
==
null
?
null
:
from
.
asObject
();
}
public
Number
to
()
{
return
to
==
null
?
null
:
to
.
asObject
();
}
}
This diff is collapsed.
Click to expand it.
community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/NumberType.java
+
1
-
1
View file @
c3e14d12
...
...
@@ -43,7 +43,7 @@ class NumberType extends Type
NumberType
(
byte
typeId
)
{
super
(
ValueGroup
.
NUMBER
,
typeId
,
Values
.
of
(
Double
.
NEGATIVE_INFINITY
),
Values
.
of
(
Double
.
POSITIVE_INFINITY
)
);
super
(
ValueGroup
.
NUMBER
,
typeId
,
Values
.
of
(
Double
.
NEGATIVE_INFINITY
),
Values
.
of
(
Double
.
NaN
)
);
}
@Override
...
...
This diff is collapsed.
Click to expand it.
community/values/src/main/java/org/neo4j/values/AnyValue.java
+
21
-
0
View file @
c3e14d12
...
...
@@ -19,6 +19,9 @@
*/
package
org.neo4j.values
;
import
org.neo4j.values.storable.FloatingPointValue
;
import
org.neo4j.values.storable.NumberValue
;
public
abstract
class
AnyValue
{
private
int
hash
;
...
...
@@ -94,4 +97,22 @@ public abstract class AnyValue
{
return
((
value
+
7
)
/
8
)
*
8
;
}
/**
* @return {@code true} if at least one operand is NaN and the other is a number
*/
public
static
boolean
isNanAndNumber
(
AnyValue
value1
,
AnyValue
value2
)
{
return
(
value1
instanceof
FloatingPointValue
&&
((
FloatingPointValue
)
value1
).
isNaN
()
&&
value2
instanceof
NumberValue
)
||
(
value2
instanceof
FloatingPointValue
&&
((
FloatingPointValue
)
value2
).
isNaN
()
&&
value1
instanceof
NumberValue
);
}
/**
* @return {@code true} if at least one operand is NaN
*/
public
static
boolean
hasNaNOperand
(
AnyValue
value1
,
AnyValue
value2
)
{
return
(
value1
instanceof
FloatingPointValue
&&
((
FloatingPointValue
)
value1
).
isNaN
())
||
(
value2
instanceof
FloatingPointValue
&&
((
FloatingPointValue
)
value2
).
isNaN
());
}
}
This diff is collapsed.
Click to expand it.
community/values/src/main/java/org/neo4j/values/storable/Value.java
+
4
-
0
View file @
c3e14d12
...
...
@@ -173,6 +173,10 @@ public abstract class Value extends AnyValue
{
return
((
SequenceValue
)
this
).
ternaryEquality
(
(
SequenceValue
)
other
);
}
if
(
hasNaNOperand
(
this
,
other
)
)
{
return
Equality
.
FALSE
;
}
if
(
other
instanceof
Value
&&
((
Value
)
other
).
valueGroup
()
==
valueGroup
()
)
{
Value
otherValue
=
(
Value
)
other
;
...
...
This diff is collapsed.
Click to expand it.
community/values/src/test/java/org/neo4j/values/storable/NumberValuesTest.java
+
4
-
4
View file @
c3e14d12
...
...
@@ -27,7 +27,7 @@ import java.util.concurrent.ThreadLocalRandom;
import
static
org
.
hamcrest
.
CoreMatchers
.
equalTo
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
neo4j
.
values
.
storable
.
NumberValues
.
hash
;
import
static
org
.
neo4j
.
values
.
utils
.
AnyValueTestUtil
.
assert
Incomparable
;
import
static
org
.
neo4j
.
values
.
utils
.
AnyValueTestUtil
.
assert
NotEqual
;
import
static
org
.
neo4j
.
values
.
virtual
.
VirtualValueTestUtil
.
toAnyValue
;
class
NumberValuesTest
...
...
@@ -49,9 +49,9 @@ class NumberValuesTest
@Test
void
shouldHandleNaNCorrectly
()
{
assert
Incomparable
(
toAnyValue
(
Double
.
NaN
),
toAnyValue
(
Double
.
NaN
)
);
assert
Incomparable
(
toAnyValue
(
1
),
toAnyValue
(
Double
.
NaN
)
);
assert
Incomparable
(
toAnyValue
(
Double
.
NaN
),
toAnyValue
(
1
)
);
assert
NotEqual
(
toAnyValue
(
Double
.
NaN
),
toAnyValue
(
Double
.
NaN
)
);
assert
NotEqual
(
toAnyValue
(
1
),
toAnyValue
(
Double
.
NaN
)
);
assert
NotEqual
(
toAnyValue
(
Double
.
NaN
),
toAnyValue
(
1
)
);
}
@Test
...
...
This diff is collapsed.
Click to expand it.
community/values/src/test/java/org/neo4j/values/storable/ValuesTest.java
+
34
-
0
View file @
c3e14d12
...
...
@@ -21,11 +21,18 @@ package org.neo4j.values.storable;
import
org.junit.jupiter.api.Test
;
import
java.util.Arrays
;
import
java.util.List
;
import
org.neo4j.string.UTF8
;
import
static
java
.
time
.
ZoneOffset
.
UTC
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertFalse
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertThrows
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertTrue
;
import
static
org
.
neo4j
.
values
.
storable
.
DurationValue
.
duration
;
import
static
org
.
neo4j
.
values
.
storable
.
LocalTimeValue
.
localTime
;
import
static
org
.
neo4j
.
values
.
storable
.
TimeValue
.
time
;
import
static
org
.
neo4j
.
values
.
storable
.
Values
.
booleanArray
;
import
static
org
.
neo4j
.
values
.
storable
.
Values
.
booleanValue
;
import
static
org
.
neo4j
.
values
.
storable
.
Values
.
byteArray
;
...
...
@@ -46,6 +53,7 @@ import static org.neo4j.values.storable.Values.stringArray;
import
static
org
.
neo4j
.
values
.
storable
.
Values
.
stringValue
;
import
static
org
.
neo4j
.
values
.
storable
.
Values
.
utf8Value
;
import
static
org
.
neo4j
.
values
.
utils
.
AnyValueTestUtil
.
assertEqual
;
import
static
org
.
neo4j
.
values
.
utils
.
AnyValueTestUtil
.
assertNotEqual
;
class
ValuesTest
{
...
...
@@ -116,4 +124,30 @@ class ValuesTest
assertFalse
(
areOfSameClasses
);
assertTrue
(
areOfSameValueType
);
}
@Test
void
differentTypesShouldNotBeEqual
()
{
// This includes NaN
List
<
Value
>
items
=
Arrays
.
asList
(
stringValue
(
"foo"
),
intValue
(
42
),
booleanValue
(
false
),
doubleValue
(
Double
.
NaN
),
time
(
14
,
0
,
0
,
0
,
UTC
),
localTime
(
14
,
0
,
0
,
0
),
duration
(
0
,
0
,
0
,
1_000_000_000
),
byteArray
(
new
byte
[]{}
),
charArray
(
new
char
[]{
'x'
}
)
);
for
(
int
i
=
0
;
i
<
items
.
size
();
i
++
)
{
for
(
int
j
=
0
;
j
<
items
.
size
();
j
++
)
{
if
(
i
!=
j
)
{
assertNotEqual
(
items
.
get
(
i
),
items
.
get
(
j
)
);
}
}
}
}
}
This diff is collapsed.
Click to expand it.
community/values/src/test/java/org/neo4j/values/utils/AnyValueTestUtil.java
+
6
-
6
View file @
c3e14d12
...
...
@@ -45,23 +45,23 @@ public class AnyValueTestUtil
{
assertEquals
(
a
,
b
,
a
+
" should be equivalent to "
+
b
);
assertEquals
(
b
,
a
,
a
+
" should be equivalent to "
+
b
);
assertEquals
(
a
.
ternaryEquals
(
b
),
Equality
.
TRUE
,
a
+
" should be equal to "
+
b
);
assertEquals
(
b
.
ternaryEquals
(
a
),
Equality
.
TRUE
,
a
+
" should be equal to "
+
b
);
assertEquals
(
Equality
.
TRUE
,
a
.
ternaryEquals
(
b
),
a
+
" should be equal to "
+
b
);
assertEquals
(
Equality
.
TRUE
,
b
.
ternaryEquals
(
a
),
a
+
" should be equal to "
+
b
);
}
public
static
void
assertNotEqual
(
AnyValue
a
,
AnyValue
b
)
{
assertNotEquals
(
a
,
b
,
a
+
" should not be equivalent to "
+
b
);
assertNotEquals
(
b
,
a
,
b
+
" should not be equivalent to "
+
a
);
assert
Not
Equals
(
a
.
ternaryEquals
(
b
),
Equality
.
TRUE
,
a
+
" should not equal "
+
b
);
assert
Not
Equals
(
b
.
ternaryEquals
(
a
),
Equality
.
TRUE
,
b
+
" should not equal "
+
a
);
assertEquals
(
Equality
.
FALSE
,
a
.
ternaryEquals
(
b
),
a
+
" should not equal "
+
b
);
assertEquals
(
Equality
.
FALSE
,
b
.
ternaryEquals
(
a
),
b
+
" should not equal "
+
a
);
}
public
static
void
assertIncomparable
(
AnyValue
a
,
AnyValue
b
)
{
assertNotEquals
(
a
,
b
,
a
+
" should not be equivalent to "
+
b
);
assertNotEquals
(
b
,
a
,
b
+
" should not be equivalent to "
+
a
);
assertEquals
(
a
.
ternaryEquals
(
b
)
,
Equality
.
UNDEFINED
,
a
+
" should be incomparable to "
+
b
);
assertEquals
(
b
.
ternaryEquals
(
a
)
,
Equality
.
UNDEFINED
,
b
+
" should be incomparable to "
+
a
);
assertEquals
(
Equality
.
UNDEFINED
,
a
.
ternaryEquals
(
b
),
a
+
" should be incomparable to "
+
b
);
assertEquals
(
Equality
.
UNDEFINED
,
b
.
ternaryEquals
(
a
),
b
+
" should be incomparable to "
+
a
);
}
}
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help