diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/pipes/TopPipe.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/pipes/TopPipe.scala index 9621f835bfc7c..340a5cc5832cc 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/pipes/TopPipe.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/pipes/TopPipe.scala @@ -179,7 +179,8 @@ case class Top1WithTiesPipe(source: Pipe, sortDescription: List[ColumnOrder]) val comparison = lessThan.compare(next, best) if (comparison < 0) { // Found a new best best = next - matchingRows = init(next) + matchingRows.clear() + matchingRows += next._2 } if (comparison == 0) { // Found a tie diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/pipes/Top1WithTiesPipeTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/pipes/Top1WithTiesPipeTest.scala index 2516d27202582..464ec6034cfb6 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/pipes/Top1WithTiesPipeTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/pipes/Top1WithTiesPipeTest.scala @@ -40,7 +40,7 @@ class Top1WithTiesPipeTest extends CypherFunSuite { sortPipe.createResults(QueryStateHelper.emptyWithValueSerialization).toList should beEquivalentTo(List(Map("x" -> "A"))) } - test("three ties for the first place are all returned") { + test("two ties for the first place are all returned") { val input = List( Map("x" -> 1, "y" -> 1), Map("x" -> 1, "y" -> 2), diff --git a/enterprise/cypher/cypher/src/test/java/org/neo4j/cypher/internal/codegen/DefaultTopTableTest.java b/enterprise/cypher/cypher/src/test/java/org/neo4j/cypher/internal/codegen/DefaultTopTableTest.java index 4ae27d431f6ae..fc8223dac31da 100644 --- a/enterprise/cypher/cypher/src/test/java/org/neo4j/cypher/internal/codegen/DefaultTopTableTest.java +++ b/enterprise/cypher/cypher/src/test/java/org/neo4j/cypher/internal/codegen/DefaultTopTableTest.java @@ -31,19 +31,15 @@ public class DefaultTopTableTest { - private static Long[] testValues = new Long[] { - 7L, 4L, 5L, 0L, 3L, 4L, 8L, 6L, 1L, 9L, 2L - }; + private static Long[] testValues = new Long[]{7L, 4L, 5L, 0L, 3L, 4L, 8L, 6L, 1L, 9L, 2L}; - private static long[] expectedValues = new long[] { - 0L, 1L, 2L, 3L, 4L, 4L, 5L, 6L, 7L, 8L, 9L - }; + private static long[] expectedValues = new long[]{0L, 1L, 2L, 3L, 4L, 4L, 5L, 6L, 7L, 8L, 9L}; @Rule public final ExpectedException exception = ExpectedException.none(); @Test - public void shouldHandleAddingMoreValuesThenCapacity() + public void shouldHandleAddingMoreValuesThanCapacity() { DefaultTopTable table = new DefaultTopTable( 7 ); for ( Long i : testValues ) diff --git a/enterprise/cypher/slotted-runtime/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/SortSlottedPipe.scala b/enterprise/cypher/slotted-runtime/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/SortSlottedPipe.scala index cb16a01abd47b..cd73618d5d567 100644 --- a/enterprise/cypher/slotted-runtime/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/SortSlottedPipe.scala +++ b/enterprise/cypher/slotted-runtime/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/SortSlottedPipe.scala @@ -31,7 +31,7 @@ case class SortSlottedPipe(source: Pipe, orderBy: Seq[ColumnOrder], pipelineInfo assert(orderBy.nonEmpty) private val comparator = orderBy - .map(ExecutionContextOrdering(_).comparator) + .map(ExecutionContextOrdering.comparator(_)) .reduceLeft[Comparator[ExecutionContext]]((a, b) => a.thenComparing(b)) override protected def internalCreateResults(input: Iterator[ExecutionContext], state: QueryState): Iterator[ExecutionContext] = { @@ -41,8 +41,8 @@ case class SortSlottedPipe(source: Pipe, orderBy: Seq[ColumnOrder], pipelineInfo } } -case class ExecutionContextOrdering(order: ColumnOrder) { - val comparator: scala.Ordering[ExecutionContext] = order.slot match { +object ExecutionContextOrdering { + def comparator(order: ColumnOrder): scala.Ordering[ExecutionContext] = order.slot match { case LongSlot(offset, _, _, _) => new scala.Ordering[ExecutionContext] { override def compare(a: ExecutionContext, b: ExecutionContext): Int = { diff --git a/enterprise/cypher/slotted-runtime/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/TopSlottedPipe.scala b/enterprise/cypher/slotted-runtime/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/TopSlottedPipe.scala index 71ab25cc1b1e6..7a6e777ab3bf3 100644 --- a/enterprise/cypher/slotted-runtime/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/TopSlottedPipe.scala +++ b/enterprise/cypher/slotted-runtime/src/main/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/TopSlottedPipe.scala @@ -38,12 +38,8 @@ abstract class TopSlottedPipe(source: Pipe, orderBy: Seq[ColumnOrder]) extends PipeWithSource(source) { protected val comparator = orderBy - .map(ExecutionContextOrdering(_).comparator) + .map(ExecutionContextOrdering.comparator(_)) .reduceLeft[Comparator[ExecutionContext]]((a, b) => a.thenComparing(b)) - - def binarySearch(array: Array[ExecutionContext], comparator: Comparator[ExecutionContext])(key: ExecutionContext) = { - java.util.Arrays.binarySearch(array.asInstanceOf[Array[ExecutionContext]], key, comparator) - } } case class TopNSlottedPipe(source: Pipe, orderBy: Seq[ColumnOrder], countExpression: Expression) @@ -128,7 +124,8 @@ case class Top1WithTiesSlottedPipe(source: Pipe, orderBy: List[ColumnOrder]) val comparison = comparator.compare(ctx, best) if (comparison < 0) { // Found a new best best = ctx - matchingRows = init(ctx) + matchingRows.clear() + matchingRows += ctx } if (comparison == 0) { // Found a tie diff --git a/enterprise/cypher/slotted-runtime/src/test/java/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/DefaultComparatorTopTableTest.java b/enterprise/cypher/slotted-runtime/src/test/java/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/DefaultComparatorTopTableTest.java index a30a2cd1e8e44..39238a0b9bb56 100644 --- a/enterprise/cypher/slotted-runtime/src/test/java/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/DefaultComparatorTopTableTest.java +++ b/enterprise/cypher/slotted-runtime/src/test/java/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/DefaultComparatorTopTableTest.java @@ -32,13 +32,9 @@ public class DefaultComparatorTopTableTest { - private static Long[] testValues = new Long[] { - 7L, 4L, 5L, 0L, 3L, 4L, 8L, 6L, 1L, 9L, 2L - }; + private static Long[] testValues = new Long[]{7L, 4L, 5L, 0L, 3L, 4L, 8L, 6L, 1L, 9L, 2L}; - private static long[] expectedValues = new long[] { - 0L, 1L, 2L, 3L, 4L, 4L, 5L, 6L, 7L, 8L, 9L - }; + private static long[] expectedValues = new long[]{0L, 1L, 2L, 3L, 4L, 4L, 5L, 6L, 7L, 8L, 9L}; private static Comparator comparator = new Comparator() { @@ -53,9 +49,9 @@ public int compare( Long x, Long y ) public final ExpectedException exception = ExpectedException.none(); @Test - public void shouldHandleAddingMoreValuesThenCapacity() + public void shouldHandleAddingMoreValuesThanCapacity() { - DefaultComparatorTopTable table = new DefaultComparatorTopTable( comparator,7 ); + DefaultComparatorTopTable table = new DefaultComparatorTopTable( comparator, 7 ); for ( Long i : testValues ) { table.add( i ); @@ -77,7 +73,7 @@ public void shouldHandleAddingMoreValuesThenCapacity() @Test public void shouldHandleWhenNotCompletelyFilledToCapacity() { - DefaultComparatorTopTable table = new DefaultComparatorTopTable( comparator,20 ); + DefaultComparatorTopTable table = new DefaultComparatorTopTable( comparator, 20 ); for ( Long i : testValues ) { table.add( i ); @@ -112,20 +108,20 @@ public void shouldHandleWhenEmpty() public void shouldThrowOnInitializeToZeroCapacity() { exception.expect( IllegalArgumentException.class ); - new DefaultComparatorTopTable( comparator,0 ); + new DefaultComparatorTopTable( comparator, 0 ); } @Test public void shouldThrowOnInitializeToNegativeCapacity() { exception.expect( IllegalArgumentException.class ); - new DefaultComparatorTopTable( comparator,-1 ); + new DefaultComparatorTopTable( comparator, -1 ); } @Test public void shouldThrowOnSortNotCalledBeforeIterator() { - DefaultComparatorTopTable table = new DefaultComparatorTopTable( comparator,5 ); + DefaultComparatorTopTable table = new DefaultComparatorTopTable( comparator, 5 ); for ( Long i : testValues ) { table.add( i ); diff --git a/enterprise/cypher/slotted-runtime/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/Top1WithTiesSlottedPipeTest.scala b/enterprise/cypher/slotted-runtime/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/Top1WithTiesSlottedPipeTest.scala index 0d355d0790b97..50b94c30619be 100644 --- a/enterprise/cypher/slotted-runtime/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/Top1WithTiesSlottedPipeTest.scala +++ b/enterprise/cypher/slotted-runtime/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/Top1WithTiesSlottedPipeTest.scala @@ -43,7 +43,7 @@ class Top1WithTiesSlottedPipeTest extends CypherFunSuite { sortPipe.createResults(QueryStateHelper.emptyWithValueSerialization).toList should beEquivalentTo(List(Map("x" -> "A"))) } - test("three ties for the first place are all returned") { + test("two ties for the first place are all returned") { val input = List( Map("x" -> 1, "y" -> 1), Map("x" -> 1, "y" -> 2), diff --git a/enterprise/cypher/slotted-runtime/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/TopSlottedPipeTest.scala b/enterprise/cypher/slotted-runtime/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/TopSlottedPipeTest.scala index bae123ea74d0f..6644b8c326497 100644 --- a/enterprise/cypher/slotted-runtime/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/TopSlottedPipeTest.scala +++ b/enterprise/cypher/slotted-runtime/src/test/scala/org/neo4j/cypher/internal/compatibility/v3_3/runtime/slotted/pipes/TopSlottedPipeTest.scala @@ -32,35 +32,35 @@ import scala.util.Random class TopSlottedPipeTest extends CypherFunSuite { - private sealed trait _ColumnOrder - private case object _Ascending extends _ColumnOrder - private case object _Descending extends _ColumnOrder + private sealed trait TestColumnOrder + private case object AscendingOrder extends TestColumnOrder + private case object DescendingOrder extends TestColumnOrder test("returning top 10 from 5 possible should return all") { val input = randomlyShuffledIntDataFromZeroUntil(5) val result = singleColumnTopWithInput( - input, orderBy = _Ascending, limit = 10 + input, orderBy = AscendingOrder, limit = 10 ) result should equal(list(0, 1, 2, 3, 4)) } test("returning top 10 descending from 3 possible should return all") { val result = singleColumnTopWithInput( - randomlyShuffledIntDataFromZeroUntil(3), orderBy = _Descending, limit = 10 + randomlyShuffledIntDataFromZeroUntil(3), orderBy = DescendingOrder, limit = 10 ) result should equal(list(2, 1, 0)) } test("returning top 5 from 20 possible should return 5 with lowest value") { val result = singleColumnTopWithInput( - randomlyShuffledIntDataFromZeroUntil(20), orderBy = _Ascending, limit = 5 + randomlyShuffledIntDataFromZeroUntil(20), orderBy = AscendingOrder, limit = 5 ) result should equal(list(0, 1, 2, 3, 4)) } test("returning top 3 descending from 10 possible values should return three highest values") { val result = singleColumnTopWithInput( - randomlyShuffledIntDataFromZeroUntil(10), orderBy = _Descending, limit = 3 + randomlyShuffledIntDataFromZeroUntil(10), orderBy = DescendingOrder, limit = 3 ) result should equal(list(9, 8, 7)) } @@ -68,7 +68,7 @@ class TopSlottedPipeTest extends CypherFunSuite { test("returning top 5 from a reversed pipe should work correctly") { val input = (0 until 100).reverse val result = singleColumnTopWithInput( - input, orderBy = _Ascending, limit = 5 + input, orderBy = AscendingOrder, limit = 5 ) result should equal(list(0, 1, 2, 3, 4)) } @@ -76,7 +76,7 @@ class TopSlottedPipeTest extends CypherFunSuite { test("duplicates should be sorted correctly") { val input = ((0 until 5) ++ (0 until 5)).reverse val result = singleColumnTopWithInput( - input, orderBy = _Descending, limit = 5 + input, orderBy = DescendingOrder, limit = 5 ) result should equal(list(4, 4, 3, 3, 2)) } @@ -84,7 +84,7 @@ class TopSlottedPipeTest extends CypherFunSuite { test("duplicates should be sorted correctly for small lists") { val input = List(0, 1, 1) val result = singleColumnTopWithInput( - input, orderBy = _Descending, limit = 2 + input, orderBy = DescendingOrder, limit = 2 ) result should equal(list(1,1)) } @@ -92,7 +92,7 @@ class TopSlottedPipeTest extends CypherFunSuite { test("should handle empty input") { val input = Seq.empty val result = singleColumnTopWithInput( - input, orderBy = _Ascending, limit = 5 + input, orderBy = AscendingOrder, limit = 5 ) result should equal(List.empty) } @@ -100,35 +100,35 @@ class TopSlottedPipeTest extends CypherFunSuite { test("should handle null input") { val input = Seq(10, null) val result = singleColumnTopWithInput( - input, orderBy = _Ascending, limit = 5 + input, orderBy = AscendingOrder, limit = 5 ) result should equal(list(10, null)) } test("returning top 1 from 5 possible should return lowest") { val result = singleColumnTopWithInput( - randomlyShuffledIntDataFromZeroUntil(5), orderBy = _Ascending, limit = 1 + randomlyShuffledIntDataFromZeroUntil(5), orderBy = AscendingOrder, limit = 1 ) result should equal(list(0)) } test("returning top 1 descending from 3 possible should return all") { val result = singleColumnTopWithInput( - randomlyShuffledIntDataFromZeroUntil(3), orderBy = _Descending, limit = 1 + randomlyShuffledIntDataFromZeroUntil(3), orderBy = DescendingOrder, limit = 1 ) result should equal(list(2)) } test("returning top 1 from 20 possible should return 5 with lowest value") { val result = singleColumnTopWithInput( - randomlyShuffledIntDataFromZeroUntil(20), orderBy = _Ascending, limit = 1 + randomlyShuffledIntDataFromZeroUntil(20), orderBy = AscendingOrder, limit = 1 ) result should equal(list(0)) } test("returning top 1 descending from 10 possible values should return three highest values") { val result = singleColumnTopWithInput( - randomlyShuffledIntDataFromZeroUntil(10), orderBy = _Descending, limit = 1 + randomlyShuffledIntDataFromZeroUntil(10), orderBy = DescendingOrder, limit = 1 ) result should equal(list(9)) } @@ -136,7 +136,7 @@ class TopSlottedPipeTest extends CypherFunSuite { test("returning top 1 from a reversed pipe should work correctly") { val input = (0 until 100).reverse val result = singleColumnTopWithInput( - input, orderBy = _Ascending, limit = 1 + input, orderBy = AscendingOrder, limit = 1 ) result should equal(list(0)) } @@ -144,7 +144,7 @@ class TopSlottedPipeTest extends CypherFunSuite { test("duplicates should be sorted correctly with top 1") { val input = ((0 until 5) ++ (0 until 5)).reverse val result = singleColumnTopWithInput( - input, orderBy = _Descending, limit = 1 + input, orderBy = DescendingOrder, limit = 1 ) result should equal(list(4)) } @@ -152,14 +152,14 @@ class TopSlottedPipeTest extends CypherFunSuite { test("duplicates should be sorted correctly for small lists with top 1") { val input = Seq(0, 1, 1) val result = singleColumnTopWithInput( - input, orderBy = _Descending, limit = 1 + input, orderBy = DescendingOrder, limit = 1 ) result should equal(list(1)) } test("top 1 should handle empty input with") { val result = singleColumnTopWithInput( - Seq.empty, orderBy = _Descending, limit = 1 + Seq.empty, orderBy = DescendingOrder, limit = 1 ) result should equal(List.empty) } @@ -167,7 +167,7 @@ class TopSlottedPipeTest extends CypherFunSuite { test("top 1 should handle null input") { val input = Seq(10, null) val result = singleColumnTopWithInput( - input, orderBy = _Ascending, limit = 1 + input, orderBy = AscendingOrder, limit = 1 ) result should equal(list(10)) } @@ -175,7 +175,7 @@ class TopSlottedPipeTest extends CypherFunSuite { test("top 5 from multi column values") { val input = List((2, 0), (1, 2), (0, 4), (1, 1), (0, 2), (1, 2), (0, 5), (2, 1)) val result = twoColumnTopWithInput( - input, orderBy = (_Ascending, _Descending), limit = 5 + input, orderBy = (AscendingOrder, DescendingOrder), limit = 5 ) result should equal(list((0, 5), (0, 4), (0, 2), (1, 2), (1, 2))) } @@ -183,7 +183,7 @@ class TopSlottedPipeTest extends CypherFunSuite { test("top 1 from multi column values") { val input = List((2, 0), (1, 2), (0, 4), (1, 1), (0, 2), (1, 2), (0, 5), (2, 1)) val result = twoColumnTopWithInput( - input, orderBy = (_Ascending, _Descending), limit = 1 + input, orderBy = (AscendingOrder, DescendingOrder), limit = 1 ) result should equal(list((0, 5))) } @@ -199,7 +199,7 @@ class TopSlottedPipeTest extends CypherFunSuite { data } - private def singleColumnTopWithInput(data: Traversable[Any], orderBy: _ColumnOrder, limit: Int) = { + private def singleColumnTopWithInput(data: Traversable[Any], orderBy: TestColumnOrder, limit: Int) = { val pipeline = PipelineInformation.empty .newReference("a", nullable = true, CTAny) @@ -208,8 +208,8 @@ class TopSlottedPipeTest extends CypherFunSuite { val source = FakeSlottedPipe(data.map(v => Map("a" -> v)).toIterator, pipeline) val topOrderBy = orderBy match { - case `_Ascending` => List(Ascending(slot)) - case `_Descending` => List(Descending(slot)) + case AscendingOrder => List(Ascending(slot)) + case DescendingOrder => List(Descending(slot)) } val topPipe = @@ -230,7 +230,7 @@ class TopSlottedPipeTest extends CypherFunSuite { }.toList } - private def twoColumnTopWithInput(data: Traversable[(Any, Any)], orderBy: (_ColumnOrder, _ColumnOrder), limit: Int) = { + private def twoColumnTopWithInput(data: Traversable[(Any, Any)], orderBy: (TestColumnOrder, TestColumnOrder), limit: Int) = { val pipeline = PipelineInformation.empty .newReference("a", nullable = true, CTAny) .newReference("b", nullable = true, CTAny) @@ -241,8 +241,8 @@ class TopSlottedPipeTest extends CypherFunSuite { val source = FakeSlottedPipe(data.map { case (v1, v2) => Map("a" -> v1, "b" -> v2) }.toIterator, pipeline) val topOrderBy = List((orderBy._1, slot1), (orderBy._2, slot2)).map { - case (`_Ascending`, slot) => Ascending(slot) - case (`_Descending`, slot) => Descending(slot) + case (AscendingOrder, slot) => Ascending(slot) + case (DescendingOrder, slot) => Descending(slot) } val topPipe =