From aea10f889a7f3672aba1515f4c638c03f31810a3 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Fri, 8 Mar 2024 14:20:38 -0500 Subject: [PATCH 01/21] fix: seek row for sorted columns --- .../clientsupport/gotorow/SeekRow.java | 207 ++++++------------ 1 file changed, 62 insertions(+), 145 deletions(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index 5f57ff99f85..549bf3b7c8c 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -14,10 +14,13 @@ import io.deephaven.engine.rowset.RowSetFactory; import io.deephaven.engine.table.ColumnSource; import io.deephaven.engine.table.Table; +import io.deephaven.engine.table.impl.SortedColumnsAttribute; +import io.deephaven.engine.table.impl.SortingOrder; import io.deephaven.internal.log.LoggerFactory; import io.deephaven.io.logger.Logger; import io.deephaven.time.DateTimeUtils; +import java.util.*; import java.util.Random; public class SeekRow implements Function { @@ -46,37 +49,38 @@ public SeekRow(long startingRow, String columnName, Object seekValue, boolean in } @Override - @ConcurrentMethod public Long apply(Table table) { - final int sortDirection = guessSorted(table); - final boolean isSorted = !contains && sortDirection != 0; - + final Optional order = SortedColumnsAttribute.getOrderForColumn(table, columnName); final RowSet index = table.getRowSet(); - long row; - if (isSorted) { - final Comparable value = - (Comparable) table.getColumnSource(columnName).get((int) index.get((int) startingRow)); - final int compareTo = - sortDirection * nullSafeCompare(value, (Comparable) seekValue) * (isBackward ? -1 : 1); - final int start = isBackward ? (int) startingRow + 1 : (int) startingRow; - if (compareTo == 0) { - return startingRow; - } else if (compareTo < 0) { - // value is less than seek value - log.info().append("Value is before: ").append(nullSafeToString(value)).append(" < ") - .append(nullSafeToString(seekValue)).endl(); - row = maybeBinarySearch(table, index, sortDirection, start, (int) index.size() - 1); + + if (!order.isEmpty()) { + if (isBackward) { + // check prev row + if (startingRow != 0) { + final Comparable prevValue = + (Comparable) table.getColumnSource(columnName).get((int) index.get((int) startingRow - 1)); + if (nullSafeCompare(prevValue, (Comparable) seekValue) == 0) { + return startingRow - 1; + } + } + // no values before, loop back around and find the last value + return findEdgeOccurence(table, index, startingRow, index.size() - 1, false, + order.get() == SortingOrder.Ascending); } else { - log.info().append("Value is after: ").append(nullSafeToString(value)).append(" > ") - .append(nullSafeToString(seekValue)).endl(); - row = maybeBinarySearch(table, index, sortDirection, 0, start); - } - if (row >= 0) { - return row; + // check next row + if (startingRow != index.size() - 1) { + final Comparable nextValue = + (Comparable) table.getColumnSource(columnName).get((int) index.get((int) startingRow + 1)); + if (nullSafeCompare(nextValue, (Comparable) seekValue) == 0) { + return startingRow + 1; + } + } + // no values after, loop back around and find the first value + return findEdgeOccurence(table, index, 0, startingRow, true, order.get() == SortingOrder.Ascending); } - // we aren't really sorted } + long row; if (isBackward) { row = findRow(table, index, 0, (int) startingRow); if (row >= 0) { @@ -136,64 +140,44 @@ public Long apply(Table table) { } } - private long maybeBinarySearch(Table table, RowSet index, int sortDirection, int start, int end) { - log.info().append("Doing binary search ").append(start).append(", ").append(end).endl(); - - final ColumnSource columnSource = table.getColumnSource(columnName); - - int minBound = start; - int maxBound = end; - - Comparable minValue = (Comparable) columnSource.get(index.get(minBound)); - Comparable maxValue = (Comparable) columnSource.get(index.get(maxBound)); - - final Comparable comparableSeek = (Comparable) this.seekValue; - - log.info().append("Seek Value ").append(nullSafeToString(comparableSeek)).endl(); - - if (nullSafeCompare(minValue, comparableSeek) * sortDirection >= 0) { - log.info().append("Less than min ").append(nullSafeToString(comparableSeek)).append(" < ") - .append(nullSafeToString(minValue)).endl(); - return minBound; - } else if (nullSafeCompare(maxValue, comparableSeek) * sortDirection <= 0) { - log.info().append("Greater than max: ").append(nullSafeToString(comparableSeek)).append(" < ") - .append(nullSafeToString(maxValue)).endl(); - return maxBound; - } - - - do { - log.info().append("Bounds (").append(minBound).append(", ").append(maxBound).append(")").endl(); - if (minBound == maxBound || minBound == maxBound - 1) { - return minBound; - } - - if (nullSafeCompare(minValue, maxValue) * sortDirection > 0) { - log.info().append("Not Sorted (").append(minValue.toString()).append(", ").append(maxValue.toString()) - .append(")").endl(); - // not really sorted - return -1; - } - - final int check = (minBound + maxBound) / 2; - final Comparable checkValue = (Comparable) columnSource.get(index.get(check)); - // Search up by default, reverse the result to search down - final int compareResult = - nullSafeCompare(checkValue, comparableSeek) * sortDirection * (isBackward ? -1 : 1); + /** + * Finds the first/last occurence of the target value by using binary search + * + * @param table the table to check for sorted-ness + * @param start the starting index to search + * @param end the ending index to search + * @param findFirst whether to find the first or last occurence (false for last) + * @param isAscending whether the table is sorted in ascending order (false for descending) + * @return the index of the first/last occurence of the target value, -1 if not found + */ + private long findEdgeOccurence(Table table, RowSet index, long start, long end, boolean findFirst, + boolean isAscending) { + long result = -1; - log.info().append("Check[").append(check).append("] ").append(checkValue.toString()).append(" -> ") - .append(compareResult).endl(); + while (start <= end) { + long mid = start + (end - start) / 2; + Comparable midValue = + (Comparable) table.getColumnSource(columnName).get((int) index.get((int) mid)); + int compareResult = nullSafeCompare(midValue, (Comparable) seekValue); if (compareResult == 0) { - return check; - } else if (compareResult < 0) { - minBound = check; - minValue = checkValue; + result = mid; + if (findFirst) { + end = mid - 1; + } else { + start = mid + 1; + } + } else if ((compareResult < 0 && isAscending) || (compareResult > 0 && !isAscending)) { + // mid less than target and list is ascending + // mid more than target and list is descending + // search right half + start = mid + 1; } else { - maxBound = check; - maxValue = checkValue; + // other way around, search left half + end = mid - 1; } - } while (true); + } + return result; } int nullSafeCompare(Comparable c1, Comparable c2) { @@ -286,71 +270,4 @@ private long findRow(Table table, RowSet index, int start, int end) { return -1L; } - - /** - * Take a guess as to whether the table is sorted, such that we should do a binary search instead - * - * @param table the table to check for sorted-ness - * @return 0 if the table is not sorted; 1 if might be ascending sorted, -1 if it might be descending sorted. - */ - int guessSorted(Table table) { - final ColumnSource columnSource = table.getColumnSource(columnName); - if (!Comparable.class.isAssignableFrom(columnSource.getType())) { - return 0; - } - - RowSet index = table.getRowSet(); - if (index.size() > 10000) { - Random random = new Random(); - TLongSet set = new TLongHashSet(); - long sampleSize = Math.min(index.size() / 4, 10000L); - while (sampleSize > 0) { - final long row = (long) (random.nextDouble() * index.size() - 1); - if (set.add(row)) { - sampleSize--; - } - } - RowSetBuilderRandom builder = RowSetFactory.builderRandom(); - set.forEach(row -> { - builder.addKey(table.getRowSet().get(row)); - return true; - }); - index = builder.build(); - } - - boolean isAscending = true; - boolean isDescending = true; - boolean first = true; - - Object previous = null; - for (RowSet.Iterator it = index.iterator(); it.hasNext();) { - long key = it.nextLong(); - Object current = columnSource.get(key); - if (current == previous) { - continue; - } - - int compareTo = first ? 0 : nullSafeCompare((Comparable) previous, (Comparable) current); - first = false; - - if (compareTo > 0) { - isAscending = false; - } else if (compareTo < 0) { - isDescending = false; - } - - if (!isAscending && !isDescending) { - break; - } - - previous = current; - } - - if (isAscending) - return 1; - else if (isDescending) - return -1; - else - return 0; - } } From 747b65c60692c8a2631c180b05f66c66058e2586 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 11 Mar 2024 09:21:54 -0400 Subject: [PATCH 02/21] Update SeekRow Co-authored-by: Ryan Caudy --- .../main/java/io/deephaven/clientsupport/gotorow/SeekRow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index 549bf3b7c8c..5efc4457d54 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -53,7 +53,7 @@ public Long apply(Table table) { final Optional order = SortedColumnsAttribute.getOrderForColumn(table, columnName); final RowSet index = table.getRowSet(); - if (!order.isEmpty()) { + if (order.isPresent()) { if (isBackward) { // check prev row if (startingRow != 0) { From 38e6cb79c79b4e8aca8e1be85de29bfba565aa06 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 11 Mar 2024 09:22:12 -0400 Subject: [PATCH 03/21] Fix typo Co-authored-by: Ryan Caudy --- .../main/java/io/deephaven/clientsupport/gotorow/SeekRow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index 5efc4457d54..7e9cc75a686 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -141,7 +141,7 @@ public Long apply(Table table) { } /** - * Finds the first/last occurence of the target value by using binary search + * Finds the first/last occurrence of the target value by using binary search * * @param table the table to check for sorted-ness * @param start the starting index to search From 9c36e6e81b09043a3ca74390050c89c129f70a72 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 11 Mar 2024 09:22:21 -0400 Subject: [PATCH 04/21] Fix typo Co-authored-by: Ryan Caudy --- .../main/java/io/deephaven/clientsupport/gotorow/SeekRow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index 7e9cc75a686..c60504b6133 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -150,7 +150,7 @@ public Long apply(Table table) { * @param isAscending whether the table is sorted in ascending order (false for descending) * @return the index of the first/last occurence of the target value, -1 if not found */ - private long findEdgeOccurence(Table table, RowSet index, long start, long end, boolean findFirst, + private long findEdgeOccurrence(Table table, RowSet index, long start, long end, boolean findFirst, boolean isAscending) { long result = -1; From 0a800cecdfddf57e304df6fadb843820ee23119e Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 11 Mar 2024 09:22:28 -0400 Subject: [PATCH 05/21] Fix typo Co-authored-by: Ryan Caudy --- .../main/java/io/deephaven/clientsupport/gotorow/SeekRow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index c60504b6133..51f224c35c0 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -146,7 +146,7 @@ public Long apply(Table table) { * @param table the table to check for sorted-ness * @param start the starting index to search * @param end the ending index to search - * @param findFirst whether to find the first or last occurence (false for last) + * @param findFirst whether to find the first or last occurrence (false for last) * @param isAscending whether the table is sorted in ascending order (false for descending) * @return the index of the first/last occurence of the target value, -1 if not found */ From 8e3e35afb1fa8e631bad065700a585bf0e7c4711 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 11 Mar 2024 09:26:41 -0400 Subject: [PATCH 06/21] Fix typo --- .../java/io/deephaven/clientsupport/gotorow/SeekRow.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index 51f224c35c0..8b07f61daa5 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -64,7 +64,7 @@ public Long apply(Table table) { } } // no values before, loop back around and find the last value - return findEdgeOccurence(table, index, startingRow, index.size() - 1, false, + return findEdgeOccurrence(table, index, startingRow, index.size() - 1, false, order.get() == SortingOrder.Ascending); } else { // check next row @@ -76,7 +76,7 @@ public Long apply(Table table) { } } // no values after, loop back around and find the first value - return findEdgeOccurence(table, index, 0, startingRow, true, order.get() == SortingOrder.Ascending); + return findEdgeOccurrence(table, index, 0, startingRow, true, order.get() == SortingOrder.Ascending); } } @@ -148,7 +148,7 @@ public Long apply(Table table) { * @param end the ending index to search * @param findFirst whether to find the first or last occurrence (false for last) * @param isAscending whether the table is sorted in ascending order (false for descending) - * @return the index of the first/last occurence of the target value, -1 if not found + * @return the index of the first/last occurrence of the target value, -1 if not found */ private long findEdgeOccurrence(Table table, RowSet index, long start, long end, boolean findFirst, boolean isAscending) { From 5a4e6156b0018c61914c07a97f11334c3b4dda5a Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 11 Mar 2024 14:28:39 -0400 Subject: [PATCH 07/21] fix: remove int cast --- .../main/java/io/deephaven/clientsupport/gotorow/SeekRow.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index 8b07f61daa5..8b66465036c 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -58,7 +58,7 @@ public Long apply(Table table) { // check prev row if (startingRow != 0) { final Comparable prevValue = - (Comparable) table.getColumnSource(columnName).get((int) index.get((int) startingRow - 1)); + (Comparable) table.getColumnSource(columnName).get(index.get(startingRow - 1)); if (nullSafeCompare(prevValue, (Comparable) seekValue) == 0) { return startingRow - 1; } @@ -70,7 +70,7 @@ public Long apply(Table table) { // check next row if (startingRow != index.size() - 1) { final Comparable nextValue = - (Comparable) table.getColumnSource(columnName).get((int) index.get((int) startingRow + 1)); + (Comparable) table.getColumnSource(columnName).get(index.get(startingRow + 1)); if (nullSafeCompare(nextValue, (Comparable) seekValue) == 0) { return startingRow + 1; } From 1f74cea0b470fdaa15bf4f6a0faa832703a86d76 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 11 Mar 2024 15:17:10 -0400 Subject: [PATCH 08/21] refactor: find algo, imports --- .../clientsupport/gotorow/SeekRow.java | 75 ++++++++++++------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index 8b66465036c..2399d9482d2 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -5,13 +5,8 @@ import java.time.Instant; import java.util.function.Function; -import gnu.trove.set.TLongSet; -import gnu.trove.set.hash.TLongHashSet; -import io.deephaven.api.util.ConcurrentMethod; import io.deephaven.base.verify.Require; import io.deephaven.engine.rowset.RowSet; -import io.deephaven.engine.rowset.RowSetBuilderRandom; -import io.deephaven.engine.rowset.RowSetFactory; import io.deephaven.engine.table.ColumnSource; import io.deephaven.engine.table.Table; import io.deephaven.engine.table.impl.SortedColumnsAttribute; @@ -21,7 +16,6 @@ import io.deephaven.time.DateTimeUtils; import java.util.*; -import java.util.Random; public class SeekRow implements Function { private final long startingRow; @@ -51,51 +45,78 @@ public SeekRow(long startingRow, String columnName, Object seekValue, boolean in @Override public Long apply(Table table) { final Optional order = SortedColumnsAttribute.getOrderForColumn(table, columnName); - final RowSet index = table.getRowSet(); + final RowSet rowSet = table.getRowSet(); + log.info().append("starting row: ").append(startingRow).endl(); if (order.isPresent()) { + final Comparable currValue = + (Comparable) table.getColumnSource(columnName).get(rowSet.get(startingRow)); + int compareResult = nullSafeCompare(currValue, (Comparable) seekValue); + if (isBackward) { - // check prev row - if (startingRow != 0) { + // current row is seek value, check prev row + if (compareResult == 0 && startingRow > 0) { final Comparable prevValue = - (Comparable) table.getColumnSource(columnName).get(index.get(startingRow - 1)); + (Comparable) table.getColumnSource(columnName).get(rowSet.get(startingRow - 1)); if (nullSafeCompare(prevValue, (Comparable) seekValue) == 0) { return startingRow - 1; } + // prev row is not the seek value, loop to back and find the last value + // algorithm is the same as if seek value is below the current row + } else if ((compareResult > 0 && order.get() == SortingOrder.Ascending) + || (compareResult < 0 && order.get() == SortingOrder.Descending)) { + // current row is greater than seek value and ascending + // current row is less than seek value and descending + // which means seek value is above the current row, find the last occurrence + return findEdgeOccurrence(table, rowSet, 0, startingRow - 1, false, + order.get() == SortingOrder.Ascending); } - // no values before, loop back around and find the last value - return findEdgeOccurrence(table, index, startingRow, index.size() - 1, false, + // seek value is below the current row + // loop to back and find the last value + return findEdgeOccurrence(table, rowSet, startingRow, rowSet.size() - 1, false, order.get() == SortingOrder.Ascending); + } else { - // check next row - if (startingRow != index.size() - 1) { + // current row is seek value, check next row + if (compareResult == 0 && startingRow < rowSet.size() - 1) { final Comparable nextValue = - (Comparable) table.getColumnSource(columnName).get(index.get(startingRow + 1)); + (Comparable) table.getColumnSource(columnName).get(rowSet.get(startingRow + 1)); if (nullSafeCompare(nextValue, (Comparable) seekValue) == 0) { return startingRow + 1; } + // next row is not the seek value, loop to start and find the first value + // algorithm is the same as if seek value is above the current row + } else if ((compareResult < 0 && order.get() == SortingOrder.Ascending) + || (compareResult > 0 && order.get() == SortingOrder.Descending)) { + // current row is less than seek value and ascending + // current row is greater than seek value and descending + // which means seek value is below the current row, find the first occurrence + return findEdgeOccurrence(table, rowSet, startingRow + 1, rowSet.size() - 1, true, + order.get() == SortingOrder.Ascending); } - // no values after, loop back around and find the first value - return findEdgeOccurrence(table, index, 0, startingRow, true, order.get() == SortingOrder.Ascending); + // seek value is above the current row + // loop to start and find the first value + return findEdgeOccurrence(table, rowSet, 0, startingRow - 1, true, + order.get() == SortingOrder.Ascending); } } long row; if (isBackward) { - row = findRow(table, index, 0, (int) startingRow); + row = findRow(table, rowSet, 0, (int) startingRow); if (row >= 0) { return row; } - row = findRow(table, index, (int) startingRow, (int) index.size()); + row = findRow(table, rowSet, (int) startingRow, (int) rowSet.size()); if (row >= 0) { return row; } } else { - row = findRow(table, index, (int) startingRow + 1, (int) index.size()); + row = findRow(table, rowSet, (int) startingRow + 1, (int) rowSet.size()); if (row >= 0) { return row; } - row = findRow(table, index, 0, (int) startingRow + 1); + row = findRow(table, rowSet, 0, (int) startingRow + 1); if (row >= 0) { return row; } @@ -105,9 +126,9 @@ public Long apply(Table table) { if (closestLowerValueYet == null && closestUpperValueYet == null) { return -1L; } else if (closestLowerValueYet == null) { - return index.find(closestUpperRowYet); + return rowSet.find(closestUpperRowYet); } else if (closestUpperValueYet == null) { - return index.find(closestLowerRowYet); + return rowSet.find(closestLowerRowYet); } else { // we need to decide between the two Class columnType = table.getColumnSource(columnName).getType(); @@ -119,7 +140,7 @@ public Long apply(Table table) { double dl = Math.abs(nl - ns); log.info().append("Using numerical distance (").appendDouble(dl).append(", ").appendDouble(du) .append(")").endl(); - return index.find(du < dl ? closestUpperRowYet : closestLowerRowYet); + return rowSet.find(du < dl ? closestUpperRowYet : closestLowerRowYet); } else if (Instant.class.isAssignableFrom(columnType)) { long nu = DateTimeUtils.epochNanos(((Instant) closestUpperValueYet)); long nl = DateTimeUtils.epochNanos(((Instant) closestLowerValueYet)); @@ -127,10 +148,10 @@ public Long apply(Table table) { long du = Math.abs(nu - ns); long dl = Math.abs(nl - ns); log.info().append("Using nano distance (").append(dl).append(", ").append(du).append(")").endl(); - return index.find(du < dl ? closestUpperRowYet : closestLowerRowYet); + return rowSet.find(du < dl ? closestUpperRowYet : closestLowerRowYet); } else { - long nu = index.find(closestUpperRowYet); - long nl = index.find(closestLowerRowYet); + long nu = rowSet.find(closestUpperRowYet); + long nl = rowSet.find(closestLowerRowYet); long ns = startingRow; long du = Math.abs(nu - ns); long dl = Math.abs(nl - ns); From 9e5e9019f096e51f75a2b860cab390bfbcf3dff2 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Fri, 15 Mar 2024 14:01:32 -0400 Subject: [PATCH 09/21] tests and refactor --- ClientSupport/ClientSupport.gradle | 10 + .../clientsupport/gotorow/SeekRow.java | 272 ++++++++++-------- .../clientsupport/gotorow/SeekRowTest.java | 114 ++++++++ .../table/ops/TableServiceGrpcImpl.java | 4 +- 4 files changed, 276 insertions(+), 124 deletions(-) create mode 100644 ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java diff --git a/ClientSupport/ClientSupport.gradle b/ClientSupport/ClientSupport.gradle index ec3c002ee0e..b4b426ef3c2 100644 --- a/ClientSupport/ClientSupport.gradle +++ b/ClientSupport/ClientSupport.gradle @@ -12,4 +12,14 @@ dependencies { implementation project(':log-factory') implementation project(':Configuration') implementation depCommonsLang3 + + testImplementation project(':engine-test-utils') + Classpaths.inheritJUnitClassic(project, 'testImplementation') + Classpaths.inheritJUnitPlatform(project) + Classpaths.inheritAssertJ(project) + + testRuntimeOnly project(':log-to-slf4j'), + project(path: ':configs'), + project(path: ':test-configs') + Classpaths.inheritSlf4j(project, 'slf4j-simple', 'testRuntimeOnly') } diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index 2399d9482d2..08713170f42 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -4,20 +4,23 @@ package io.deephaven.clientsupport.gotorow; import java.time.Instant; -import java.util.function.Function; import io.deephaven.base.verify.Require; import io.deephaven.engine.rowset.RowSet; import io.deephaven.engine.table.ColumnSource; import io.deephaven.engine.table.Table; +import io.deephaven.engine.table.impl.NotificationStepSource; import io.deephaven.engine.table.impl.SortedColumnsAttribute; import io.deephaven.engine.table.impl.SortingOrder; +import io.deephaven.engine.table.impl.remote.ConstructSnapshot; import io.deephaven.internal.log.LoggerFactory; import io.deephaven.io.logger.Logger; import io.deephaven.time.DateTimeUtils; +import org.apache.commons.lang3.mutable.Mutable; +import org.apache.commons.lang3.mutable.MutableObject; import java.util.*; -public class SeekRow implements Function { +public class SeekRow { private final long startingRow; private final String columnName; private final Object seekValue; @@ -27,8 +30,10 @@ public class SeekRow implements Function { private Comparable closestUpperValueYet; private Comparable closestLowerValueYet; + private ColumnSource columnSource; private long closestUpperRowYet = -1; private long closestLowerRowYet = -1; + private boolean usePrev; private static final Logger log = LoggerFactory.getLogger(SeekRow.class); @@ -42,143 +47,166 @@ public SeekRow(long startingRow, String columnName, Object seekValue, boolean in this.isBackward = isBackward; } - @Override - public Long apply(Table table) { - final Optional order = SortedColumnsAttribute.getOrderForColumn(table, columnName); - final RowSet rowSet = table.getRowSet(); - log.info().append("starting row: ").append(startingRow).endl(); + public long seek(Table table) { + final Mutable result = new MutableObject<>(-1L); - if (order.isPresent()) { - final Comparable currValue = - (Comparable) table.getColumnSource(columnName).get(rowSet.get(startingRow)); - int compareResult = nullSafeCompare(currValue, (Comparable) seekValue); + ConstructSnapshot.callDataSnapshotFunction("SeekRow", + ConstructSnapshot.makeSnapshotControl(false, table.isRefreshing(), (NotificationStepSource) table), + ((nestedUsePrev, beforeClockValue) -> { + final Optional order = SortedColumnsAttribute.getOrderForColumn(table, columnName); + final RowSet rowSet = table.getRowSet(); + columnSource = table.getColumnSource(columnName); + usePrev = nestedUsePrev; - if (isBackward) { - // current row is seek value, check prev row - if (compareResult == 0 && startingRow > 0) { - final Comparable prevValue = - (Comparable) table.getColumnSource(columnName).get(rowSet.get(startingRow - 1)); - if (nullSafeCompare(prevValue, (Comparable) seekValue) == 0) { - return startingRow - 1; + if (order.isPresent()) { + final Comparable currValue = (Comparable) columnSourceGet(rowSet.get(startingRow)); + int compareResult = nullSafeCompare(currValue, (Comparable) seekValue); + + if (isBackward) { + // current row is seek value, check prev row + if (compareResult == 0 && startingRow > 0) { + final Comparable prevValue = (Comparable) columnSourceGet(rowSet.get(startingRow - 1)); + if (nullSafeCompare(prevValue, (Comparable) seekValue) == 0) { + result.setValue(startingRow - 1); + return true; + } + // prev row is not the seek value, loop to back and find the last value + // algorithm is the same as if seek value is below the current row + } else if ((compareResult > 0 && order.get() == SortingOrder.Ascending) + || (compareResult < 0 && order.get() == SortingOrder.Descending)) { + // current row is greater than seek value and ascending + // current row is less than seek value and descending + // which means seek value is above the current row, find the last occurrence + result.setValue(findEdgeOccurrence(rowSet, 0, startingRow, false, + order.get() == SortingOrder.Ascending)); + return true; + } + // seek value is below the current row + // loop to back and find the last value + result.setValue(findEdgeOccurrence(rowSet, startingRow, rowSet.size() - 1, false, + order.get() == SortingOrder.Ascending)); + return true; + + } else { + // current row is seek value, check next row + if (compareResult == 0 && startingRow < rowSet.size() - 1) { + final Comparable nextValue = (Comparable) columnSourceGet(rowSet.get(startingRow + 1)); + if (nullSafeCompare(nextValue, (Comparable) seekValue) == 0) { + result.setValue(startingRow + 1); + return true; + } + // next row is not the seek value, loop to start and find the first value + // algorithm is the same as if seek value is above the current row + } else if ((compareResult < 0 && order.get() == SortingOrder.Ascending) + || (compareResult > 0 && order.get() == SortingOrder.Descending)) { + // current row is less than seek value and ascending + // current row is greater than seek value and descending + // which means seek value is below the current row, find the first occurrence + result.setValue( + findEdgeOccurrence(rowSet, startingRow, rowSet.size() - 1, true, + order.get() == SortingOrder.Ascending)); + return true; + } + // seek value is above the current row + // loop to start and find the first value + result.setValue(findEdgeOccurrence(rowSet, 0, startingRow, true, + order.get() == SortingOrder.Ascending)); + return true; + } } - // prev row is not the seek value, loop to back and find the last value - // algorithm is the same as if seek value is below the current row - } else if ((compareResult > 0 && order.get() == SortingOrder.Ascending) - || (compareResult < 0 && order.get() == SortingOrder.Descending)) { - // current row is greater than seek value and ascending - // current row is less than seek value and descending - // which means seek value is above the current row, find the last occurrence - return findEdgeOccurrence(table, rowSet, 0, startingRow - 1, false, - order.get() == SortingOrder.Ascending); - } - // seek value is below the current row - // loop to back and find the last value - return findEdgeOccurrence(table, rowSet, startingRow, rowSet.size() - 1, false, - order.get() == SortingOrder.Ascending); - } else { - // current row is seek value, check next row - if (compareResult == 0 && startingRow < rowSet.size() - 1) { - final Comparable nextValue = - (Comparable) table.getColumnSource(columnName).get(rowSet.get(startingRow + 1)); - if (nullSafeCompare(nextValue, (Comparable) seekValue) == 0) { - return startingRow + 1; + long row; + if (isBackward) { + row = findRow(rowSet, 0, (int) startingRow); + if (row >= 0) { + result.setValue(row); + return true; + } + row = findRow(rowSet, (int) startingRow, (int) rowSet.size()); + if (row >= 0) { + result.setValue(row); + return true; + } + } else { + row = findRow(rowSet, (int) startingRow + 1, (int) rowSet.size()); + if (row >= 0) { + result.setValue(row); + return true; + } + row = findRow(rowSet, 0, (int) startingRow + 1); + if (row >= 0) { + result.setValue(row); + return true; + } } - // next row is not the seek value, loop to start and find the first value - // algorithm is the same as if seek value is above the current row - } else if ((compareResult < 0 && order.get() == SortingOrder.Ascending) - || (compareResult > 0 && order.get() == SortingOrder.Descending)) { - // current row is less than seek value and ascending - // current row is greater than seek value and descending - // which means seek value is below the current row, find the first occurrence - return findEdgeOccurrence(table, rowSet, startingRow + 1, rowSet.size() - 1, true, - order.get() == SortingOrder.Ascending); - } - // seek value is above the current row - // loop to start and find the first value - return findEdgeOccurrence(table, rowSet, 0, startingRow - 1, true, - order.get() == SortingOrder.Ascending); - } - } - long row; - if (isBackward) { - row = findRow(table, rowSet, 0, (int) startingRow); - if (row >= 0) { - return row; - } - row = findRow(table, rowSet, (int) startingRow, (int) rowSet.size()); - if (row >= 0) { - return row; - } - } else { - row = findRow(table, rowSet, (int) startingRow + 1, (int) rowSet.size()); - if (row >= 0) { - return row; - } - row = findRow(table, rowSet, 0, (int) startingRow + 1); - if (row >= 0) { - return row; - } - } + // just go to the closest value + if (closestLowerValueYet == null && closestUpperValueYet == null) { + result.setValue(-1L); + return true; + } else if (closestLowerValueYet == null) { + result.setValue(rowSet.find(closestUpperRowYet)); + return true; + } else if (closestUpperValueYet == null) { + result.setValue(rowSet.find(closestUpperRowYet)); + return true; + } else { + // we need to decide between the two + Class columnType = columnSource.getType(); + if (Number.class.isAssignableFrom(columnType)) { + double nu = ((Number) closestUpperValueYet).doubleValue(); + double nl = ((Number) closestLowerRowYet).doubleValue(); + double ns = ((Number) seekValue).doubleValue(); + double du = Math.abs(nu - ns); + double dl = Math.abs(nl - ns); + log.info().append("Using numerical distance (").appendDouble(dl).append(", ") + .appendDouble(du) + .append(")").endl(); + result.setValue(rowSet.find(du < dl ? closestUpperRowYet : closestLowerRowYet)); + return true; + } else if (Instant.class.isAssignableFrom(columnType)) { + long nu = DateTimeUtils.epochNanos(((Instant) closestUpperValueYet)); + long nl = DateTimeUtils.epochNanos(((Instant) closestLowerValueYet)); + long ns = DateTimeUtils.epochNanos(((Instant) seekValue)); + long du = Math.abs(nu - ns); + long dl = Math.abs(nl - ns); + log.info().append("Using nano distance (").append(dl).append(", ").append(du).append(")") + .endl(); + result.setValue(rowSet.find(du < dl ? closestUpperRowYet : closestLowerRowYet)); + return true; + } else { + long nu = rowSet.find(closestUpperRowYet); + long nl = rowSet.find(closestLowerRowYet); + long ns = startingRow; + long du = Math.abs(nu - ns); + long dl = Math.abs(nl - ns); + log.info().append("Using index distance (").append(dl).append(", ").append(du).append(")") + .endl(); + result.setValue(du < dl ? nu : nl); + return true; + } + } + })); - // just go to the closest value - if (closestLowerValueYet == null && closestUpperValueYet == null) { - return -1L; - } else if (closestLowerValueYet == null) { - return rowSet.find(closestUpperRowYet); - } else if (closestUpperValueYet == null) { - return rowSet.find(closestLowerRowYet); - } else { - // we need to decide between the two - Class columnType = table.getColumnSource(columnName).getType(); - if (Number.class.isAssignableFrom(columnType)) { - double nu = ((Number) closestUpperValueYet).doubleValue(); - double nl = ((Number) closestLowerRowYet).doubleValue(); - double ns = ((Number) seekValue).doubleValue(); - double du = Math.abs(nu - ns); - double dl = Math.abs(nl - ns); - log.info().append("Using numerical distance (").appendDouble(dl).append(", ").appendDouble(du) - .append(")").endl(); - return rowSet.find(du < dl ? closestUpperRowYet : closestLowerRowYet); - } else if (Instant.class.isAssignableFrom(columnType)) { - long nu = DateTimeUtils.epochNanos(((Instant) closestUpperValueYet)); - long nl = DateTimeUtils.epochNanos(((Instant) closestLowerValueYet)); - long ns = DateTimeUtils.epochNanos(((Instant) seekValue)); - long du = Math.abs(nu - ns); - long dl = Math.abs(nl - ns); - log.info().append("Using nano distance (").append(dl).append(", ").append(du).append(")").endl(); - return rowSet.find(du < dl ? closestUpperRowYet : closestLowerRowYet); - } else { - long nu = rowSet.find(closestUpperRowYet); - long nl = rowSet.find(closestLowerRowYet); - long ns = startingRow; - long du = Math.abs(nu - ns); - long dl = Math.abs(nl - ns); - log.info().append("Using index distance (").append(dl).append(", ").append(du).append(")").endl(); - return du < dl ? nu : nl; - } - } + return result.getValue(); } /** * Finds the first/last occurrence of the target value by using binary search * - * @param table the table to check for sorted-ness * @param start the starting index to search * @param end the ending index to search * @param findFirst whether to find the first or last occurrence (false for last) * @param isAscending whether the table is sorted in ascending order (false for descending) * @return the index of the first/last occurrence of the target value, -1 if not found */ - private long findEdgeOccurrence(Table table, RowSet index, long start, long end, boolean findFirst, + private long findEdgeOccurrence(RowSet index, long start, long end, boolean findFirst, boolean isAscending) { long result = -1; while (start <= end) { long mid = start + (end - start) / 2; - Comparable midValue = - (Comparable) table.getColumnSource(columnName).get((int) index.get((int) mid)); + Comparable midValue = (Comparable) columnSourceGet((int) index.get((int) mid)); int compareResult = nullSafeCompare(midValue, (Comparable) seekValue); if (compareResult == 0) { @@ -198,6 +226,8 @@ private long findEdgeOccurrence(Table table, RowSet index, long start, long end, end = mid - 1; } } + log.info().append("searching from ").append(start).append(" to ").append(end).append(": ").append(result) + .endl(); return result; } @@ -218,11 +248,11 @@ int nullSafeCompare(Comparable c1, Comparable c2) { return c1.compareTo(c2); } - String nullSafeToString(Object o) { - return o == null ? "(null)" : o.toString(); + private Object columnSourceGet(long rowKey) { + return usePrev ? columnSource.getPrev(rowKey) : columnSource.get(rowKey); } - private long findRow(Table table, RowSet index, int start, int end) { + private long findRow(RowSet index, int start, int end) { final RowSet subIndex = index.subSetByPositionRange(start, end); final RowSet.Iterator it; @@ -232,8 +262,6 @@ private long findRow(Table table, RowSet index, int start, int end) { it = subIndex.iterator(); } - final ColumnSource columnSource = table.getColumnSource(columnName); - final boolean isComparable = !contains && (Comparable.class.isAssignableFrom(columnSource.getType()) || columnSource.getType().isPrimitive()); @@ -242,7 +270,7 @@ private long findRow(Table table, RowSet index, int start, int end) { for (; it.hasNext();) { long key = it.nextLong(); - Object value = columnSource.get(key); + Object value = columnSourceGet(key); if (useSeek instanceof String) { value = value == null ? null : value.toString(); if (insensitive) { diff --git a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java new file mode 100644 index 00000000000..9c6a8b44cdf --- /dev/null +++ b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java @@ -0,0 +1,114 @@ +// +// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending +// +package io.deephaven.clientsupport.gotorow; + +import io.deephaven.engine.table.Table; +import io.deephaven.engine.testutil.junit4.EngineCleanup; +import io.deephaven.engine.util.TableTools; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; + +import static io.deephaven.engine.util.TableTools.intCol; + + +public class SeekRowTest { + + @Rule + public final EngineCleanup framework = new EngineCleanup(); + + @Test + public void singleRow() { + Table t = TableTools.newTable(intCol("num", 1)).sort("num"); + Assert.assertEquals(0, (long) new SeekRow( + 0, "num", 1, false, false, true).seek(t)); + Assert.assertEquals(0, (long) new SeekRow( + 0, "num", 1, false, false, false).seek(t)); + } + + @Test + public void ascendingForward() { + Table t = createSortedTable(true); + Assert.assertEquals(3, (long) new SeekRow( + 0, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 1, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 2, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(4, (long) new SeekRow( + 3, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 4, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 5, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 6, "num", 3, false, false, false).seek(t)); + } + + @Test + public void ascendingBackward() { + Table t = createSortedTable(true); + Assert.assertEquals(4, (long) new SeekRow( + 0, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(4, (long) new SeekRow( + 1, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(4, (long) new SeekRow( + 2, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(4, (long) new SeekRow( + 3, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 4, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(4, (long) new SeekRow( + 5, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(4, (long) new SeekRow( + 6, "num", 3, false, false, true).seek(t)); + } + + @Test + public void descendingForward() { + Table t = createSortedTable(false); + Assert.assertEquals(2, (long) new SeekRow( + 0, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(2, (long) new SeekRow( + 1, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 2, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(2, (long) new SeekRow( + 3, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(2, (long) new SeekRow( + 4, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(2, (long) new SeekRow( + 5, "num", 3, false, false, false).seek(t)); + Assert.assertEquals(2, (long) new SeekRow( + 6, "num", 3, false, false, false).seek(t)); + } + + @Test + public void descendingBackward() { + Table t = createSortedTable(false); + Assert.assertEquals(3, (long) new SeekRow( + 0, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 1, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 2, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(2, (long) new SeekRow( + 3, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 4, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 5, "num", 3, false, false, true).seek(t)); + Assert.assertEquals(3, (long) new SeekRow( + 6, "num", 3, false, false, true).seek(t)); + } + + private Table createSortedTable(boolean ascending) { + Table t = TableTools.newTable(intCol("num", 1, 1, 2, 3, 3, 4, 4)).sort("num"); + if (ascending) { + return t.sort("num"); + } else { + return t.sortDescending("n"); + } + } +} diff --git a/server/src/main/java/io/deephaven/server/table/ops/TableServiceGrpcImpl.java b/server/src/main/java/io/deephaven/server/table/ops/TableServiceGrpcImpl.java index e67eba02bf8..0d92ce5bedc 100644 --- a/server/src/main/java/io/deephaven/server/table/ops/TableServiceGrpcImpl.java +++ b/server/src/main/java/io/deephaven/server/table/ops/TableServiceGrpcImpl.java @@ -459,13 +459,13 @@ public void seekRow( final String columnName = request.getColumnName(); final Class dataType = table.getDefinition().getColumn(columnName).getDataType(); final Object seekValue = getSeekValue(request.getSeekValue(), dataType); - final Long result = table.apply(new SeekRow( + final Long result = new SeekRow( request.getStartingRow(), columnName, seekValue, request.getInsensitive(), request.getContains(), - request.getIsBackward())); + request.getIsBackward()).seek(table); SeekRowResponse.Builder rowResponse = SeekRowResponse.newBuilder(); safelyComplete(responseObserver, rowResponse.setResultRow(result).build()); }); From f82e1861f06487076809b19e84c79af2f86c13bd Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Fri, 15 Mar 2024 14:32:14 -0400 Subject: [PATCH 10/21] fix test and typing --- .../java/io/deephaven/clientsupport/gotorow/SeekRowTest.java | 2 +- .../io/deephaven/server/table/ops/TableServiceGrpcImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java index 9c6a8b44cdf..784bf6c7b09 100644 --- a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java +++ b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java @@ -108,7 +108,7 @@ private Table createSortedTable(boolean ascending) { if (ascending) { return t.sort("num"); } else { - return t.sortDescending("n"); + return t.sortDescending("num"); } } } diff --git a/server/src/main/java/io/deephaven/server/table/ops/TableServiceGrpcImpl.java b/server/src/main/java/io/deephaven/server/table/ops/TableServiceGrpcImpl.java index 0d92ce5bedc..8d5de5f9df4 100644 --- a/server/src/main/java/io/deephaven/server/table/ops/TableServiceGrpcImpl.java +++ b/server/src/main/java/io/deephaven/server/table/ops/TableServiceGrpcImpl.java @@ -459,7 +459,7 @@ public void seekRow( final String columnName = request.getColumnName(); final Class dataType = table.getDefinition().getColumn(columnName).getDataType(); final Object seekValue = getSeekValue(request.getSeekValue(), dataType); - final Long result = new SeekRow( + final long result = new SeekRow( request.getStartingRow(), columnName, seekValue, From 9421fb27c3e17be558932a7f7a5c87d5fb83768f Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Wed, 20 Mar 2024 13:33:31 -0400 Subject: [PATCH 11/21] test: add seek row tests --- .../clientsupport/gotorow/SeekRowTest.java | 375 +++++++++++++----- 1 file changed, 284 insertions(+), 91 deletions(-) diff --git a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java index 784bf6c7b09..96bfb20e943 100644 --- a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java +++ b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java @@ -6,11 +6,13 @@ import io.deephaven.engine.table.Table; import io.deephaven.engine.testutil.junit4.EngineCleanup; import io.deephaven.engine.util.TableTools; -import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import static io.deephaven.engine.util.TableTools.intCol; +import static io.deephaven.engine.util.TableTools.newTable; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class SeekRowTest { @@ -18,97 +20,288 @@ public class SeekRowTest { @Rule public final EngineCleanup framework = new EngineCleanup(); - @Test - public void singleRow() { - Table t = TableTools.newTable(intCol("num", 1)).sort("num"); - Assert.assertEquals(0, (long) new SeekRow( - 0, "num", 1, false, false, true).seek(t)); - Assert.assertEquals(0, (long) new SeekRow( - 0, "num", 1, false, false, false).seek(t)); - } - - @Test - public void ascendingForward() { - Table t = createSortedTable(true); - Assert.assertEquals(3, (long) new SeekRow( - 0, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 1, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 2, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(4, (long) new SeekRow( - 3, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 4, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 5, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 6, "num", 3, false, false, false).seek(t)); - } - - @Test - public void ascendingBackward() { - Table t = createSortedTable(true); - Assert.assertEquals(4, (long) new SeekRow( - 0, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(4, (long) new SeekRow( - 1, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(4, (long) new SeekRow( - 2, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(4, (long) new SeekRow( - 3, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 4, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(4, (long) new SeekRow( - 5, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(4, (long) new SeekRow( - 6, "num", 3, false, false, true).seek(t)); - } - - @Test - public void descendingForward() { - Table t = createSortedTable(false); - Assert.assertEquals(2, (long) new SeekRow( - 0, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(2, (long) new SeekRow( - 1, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 2, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(2, (long) new SeekRow( - 3, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(2, (long) new SeekRow( - 4, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(2, (long) new SeekRow( - 5, "num", 3, false, false, false).seek(t)); - Assert.assertEquals(2, (long) new SeekRow( - 6, "num", 3, false, false, false).seek(t)); - } - - @Test - public void descendingBackward() { - Table t = createSortedTable(false); - Assert.assertEquals(3, (long) new SeekRow( - 0, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 1, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 2, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(2, (long) new SeekRow( - 3, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 4, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 5, "num", 3, false, false, true).seek(t)); - Assert.assertEquals(3, (long) new SeekRow( - 6, "num", 3, false, false, true).seek(t)); - } - - private Table createSortedTable(boolean ascending) { - Table t = TableTools.newTable(intCol("num", 1, 1, 2, 3, 3, 4, 4)).sort("num"); - if (ascending) { - return t.sort("num"); + /** + * Helper to verify that a given value can not be found no matter which row is started from + * + * @param t the table to search + * @param impossibleValue a value that isn't present in the table + */ + public static void assertNotFound(int impossibleValue, Table t) { + // ensure we can't find values that don't exist + for (int i = 0; i < t.size(); i++) { + assertSeekPosition(t, impossibleValue, true, i, -1); + assertSeekPosition(t, impossibleValue, false, i, -1); + } + } + + /** + * Helper to run SeekRow and validate that the discovered row is what was expected. Validates the + * {@code expectedPosition} before running, to ensure test data makes sense. + * + * @param t the table to search + * @param seekValue the value to search for + * @param seekForward true to seek forward, false to seek backward + * @param currentPosition the position to start searching + * @param expectedPosition the next expected position of the seek value + */ + private static void assertSeekPosition(Table t, int seekValue, boolean seekForward, int currentPosition, + int expectedPosition) { + if (expectedPosition != -1) { + // Confirm that the expected position matches + assertEquals(seekValue, t.flatten().getColumnSource("num").getInt(expectedPosition)); } else { - return t.sortDescending("num"); + // Confirm that the value actually doesn't exist + assertTrue(t.where("num" + "=" + seekValue).isEmpty()); } + // Actually perform the requested assertion + SeekRow seek = new SeekRow(currentPosition, "num", seekValue, false, false, !seekForward); + assertEquals(expectedPosition, seek.seek(t)); + } + + /** + * Helper to seek from every row in a table, and assert that a valid value can be found in a valid position from + * each. + * + * @param t the table to search + * @param seekValue the value to search for + * @param forwardPositions expected positions when searching forward, indexed on starting row + * @param backwardPositions expected positions when searching backwards, indexed on starting row + */ + private static void assertSeekPositionAllRows(Table t, int seekValue, int[] forwardPositions, + int[] backwardPositions) { + assertEquals(t.size(), forwardPositions.length); + assertEquals(t.size(), backwardPositions.length); + for (int i = 0; i < t.size(); i++) { + // seek from the current position, confirm we get the expected position + assertSeekPosition(t, seekValue, true, i, forwardPositions[i]); + assertSeekPosition(t, seekValue, false, i, backwardPositions[i]); + } + } + + /** + * Helper to run asserts for int rows that are already sorted at initialization + * + * @param data the data, must be sorted in ascending order already + * @param seekValue the value to search for + * @param ascForwardPositions expected positions when searching forwards for ascending data + * @param ascBackwardPositions expected positions when searching backwards for ascending data + * @param descForwardPositions expected positions when searching forwards for descending data + * @param descBackwardPositions expected positions when searching backwards for descending data + */ + private static void assertNaturallySorted(int[] data, int seekValue, + int[] ascForwardPositions, int[] ascBackwardPositions, + int[] descForwardPositions, int[] descBackwardPositions) { + // ascending tables + Table ascUnsorted = TableTools.newTable(intCol("num", data)); + Table ascSorted = ascUnsorted.sort("num"); + // reverse data to be in descending + for (int i = 0; i < data.length / 2; i++) { + int tmp = data[i]; + data[i] = data[data.length - i - 1]; + data[data.length - i - 1] = tmp; + } + // descending tables + Table descUnsorted = TableTools.newTable(intCol("num", data)); + Table descSorted = descUnsorted.sort("num"); + + assertSeekPositionAllRows(ascUnsorted, seekValue, ascForwardPositions, ascBackwardPositions); + assertSeekPositionAllRows(ascSorted, seekValue, ascForwardPositions, ascBackwardPositions); + assertSeekPositionAllRows(descUnsorted, seekValue, descForwardPositions, descBackwardPositions); + assertSeekPositionAllRows(descSorted, seekValue, descForwardPositions, descBackwardPositions); + } + + @Test + public void emptyTable() { + Table t = TableTools.newTable(intCol("num")); + + assertSeekPosition(t, 1, true, 0, -1); + assertSeekPosition(t, 1, false, 0, -1); + + // repeat with sorted + t = t.sort("num"); + assertSeekPosition(t, 1, true, 0, -1); + assertSeekPosition(t, 1, false, 0, -1); + } + + @Test + public void singleRow() { + Table t = TableTools.newTable(intCol("num", 1)); + assertSeekPosition(t, 1, true, 0, 0); + assertSeekPosition(t, 1, false, 0, 0); + + assertSeekPosition(t, 100, false, 0, -1); + assertSeekPosition(t, 100, true, 0, -1); + + // repeat with sorted + t = t.sort("num"); + assertSeekPosition(t, 1, true, 0, 0); + assertSeekPosition(t, 1, false, 0, 0); + + assertSeekPosition(t, 100, false, 0, -1); + assertSeekPosition(t, 100, true, 0, -1); + + // repeat with sorted descending + t = t.sortDescending("num"); + assertSeekPosition(t, 1, true, 0, 0); + assertSeekPosition(t, 1, false, 0, 0); + + assertSeekPosition(t, 100, false, 0, -1); + assertSeekPosition(t, 100, true, 0, -1); + } + + @Test + public void mono1() { + assertNaturallySorted( + new int[] {1}, 1, + new int[] {0}, + new int[] {0}, + new int[] {0}, + new int[] {0}); + } + + @Test + public void mono2() { + assertNaturallySorted( + new int[] {1, 1}, 1, + new int[] {1, 0}, + new int[] {1, 0}, + new int[] {1, 0}, + new int[] {1, 0}); + } + + @Test + public void mono3() { + assertNaturallySorted( + new int[] {1, 1, 1}, 1, + new int[] {1, 2, 0}, + new int[] {2, 0, 1}, + new int[] {1, 2, 0}, + new int[] {2, 0, 1}); + } + + @Test + public void start1() { + assertNaturallySorted( + new int[] {1, 2}, 1, + new int[] {0, 0}, + new int[] {0, 0}, + new int[] {1, 1}, + new int[] {1, 1}); + } + + @Test + public void start2() { + assertNaturallySorted( + new int[] {1, 1, 2}, 1, + new int[] {1, 0, 0}, + new int[] {1, 0, 1}, + new int[] {1, 2, 1}, + new int[] {2, 2, 1}); + } + + @Test + public void start3() { + assertNaturallySorted( + new int[] {1, 1, 1, 2}, 1, + new int[] {1, 2, 0, 0}, + new int[] {2, 0, 1, 2}, + new int[] {1, 2, 3, 1}, + new int[] {3, 3, 1, 2}); + } + + @Test + public void middle1() { + assertNaturallySorted( + new int[] {1, 2, 3}, 2, + new int[] {1, 1, 1}, + new int[] {1, 1, 1}, + new int[] {1, 1, 1}, + new int[] {1, 1, 1}); + } + + @Test + public void middle2() { + assertNaturallySorted( + new int[] {1, 2, 2, 3}, 2, + new int[] {1, 2, 1, 1}, + new int[] {2, 2, 1, 2}, + new int[] {1, 2, 1, 1}, + new int[] {2, 2, 1, 2}); + } + + @Test + public void middle3() { + assertNaturallySorted( + new int[] {1, 2, 2, 2, 3}, 2, + new int[] {1, 2, 3, 1, 1}, + new int[] {3, 3, 1, 2, 3}, + new int[] {1, 2, 3, 1, 1}, + new int[] {3, 3, 1, 2, 3}); + } + + @Test + public void end1() { + assertNaturallySorted( + new int[] {1, 2}, 2, + new int[] {1, 1}, + new int[] {1, 1}, + new int[] {0, 0}, + new int[] {0, 0}); + } + + @Test + public void end2() { + assertNaturallySorted( + new int[] {1, 2, 2}, 2, + new int[] {1, 2, 1}, + new int[] {2, 2, 1}, + new int[] {1, 0, 0}, + new int[] {1, 0, 1}); + } + + @Test + public void end3() { + assertNaturallySorted( + new int[] {1, 2, 2, 2}, 2, + new int[] {1, 2, 3, 1}, + new int[] {3, 3, 1, 2}, + new int[] {1, 2, 0, 0}, + new int[] {2, 0, 1, 2}); + } + + @Test + public void notFound() { + assertNaturallySorted( + new int[] {2, 4, 6}, 1, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}); + assertNaturallySorted( + new int[] {2, 4, 6}, 3, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}); + assertNaturallySorted( + new int[] {2, 4, 6}, 5, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}); + assertNaturallySorted( + new int[] {2, 4, 6}, 7, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}); + } + + @Test + public void unsorted() { + final Table t = newTable(intCol("num", 3, 1, 2, 1, 3, 2)); + assertSeekPositionAllRows(t, 2, + new int[] {2, 2, 5, 5, 5, 2}, + new int[] {5, 5, 5, 2, 2, 2}); } } From b1cf244d02abfd0a870872de0de8fdde4a16fcf3 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Wed, 20 Mar 2024 13:34:16 -0400 Subject: [PATCH 12/21] refactor return, concurrent method --- .../io/deephaven/clientsupport/gotorow/SeekRow.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index 08713170f42..e22600c5d07 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -4,6 +4,8 @@ package io.deephaven.clientsupport.gotorow; import java.time.Instant; + +import io.deephaven.api.util.ConcurrentMethod; import io.deephaven.base.verify.Require; import io.deephaven.engine.rowset.RowSet; import io.deephaven.engine.table.ColumnSource; @@ -47,6 +49,7 @@ public SeekRow(long startingRow, String columnName, Object seekValue, boolean in this.isBackward = isBackward; } + @ConcurrentMethod public long seek(Table table) { final Mutable result = new MutableObject<>(-1L); @@ -143,13 +146,10 @@ public long seek(Table table) { // just go to the closest value if (closestLowerValueYet == null && closestUpperValueYet == null) { result.setValue(-1L); - return true; } else if (closestLowerValueYet == null) { result.setValue(rowSet.find(closestUpperRowYet)); - return true; } else if (closestUpperValueYet == null) { result.setValue(rowSet.find(closestUpperRowYet)); - return true; } else { // we need to decide between the two Class columnType = columnSource.getType(); @@ -163,7 +163,6 @@ public long seek(Table table) { .appendDouble(du) .append(")").endl(); result.setValue(rowSet.find(du < dl ? closestUpperRowYet : closestLowerRowYet)); - return true; } else if (Instant.class.isAssignableFrom(columnType)) { long nu = DateTimeUtils.epochNanos(((Instant) closestUpperValueYet)); long nl = DateTimeUtils.epochNanos(((Instant) closestLowerValueYet)); @@ -173,7 +172,6 @@ public long seek(Table table) { log.info().append("Using nano distance (").append(dl).append(", ").append(du).append(")") .endl(); result.setValue(rowSet.find(du < dl ? closestUpperRowYet : closestLowerRowYet)); - return true; } else { long nu = rowSet.find(closestUpperRowYet); long nl = rowSet.find(closestLowerRowYet); @@ -183,9 +181,10 @@ public long seek(Table table) { log.info().append("Using index distance (").append(dl).append(", ").append(du).append(")") .endl(); result.setValue(du < dl ? nu : nl); - return true; } } + + return true; })); return result.getValue(); From 4cdcc2ea6fb23f594812f1048ae070b639a33ea0 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Wed, 20 Mar 2024 15:24:24 -0400 Subject: [PATCH 13/21] fix test --- .../java/io/deephaven/clientsupport/gotorow/SeekRowTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java index 96bfb20e943..6aa6bce154c 100644 --- a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java +++ b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java @@ -102,7 +102,7 @@ private static void assertNaturallySorted(int[] data, int seekValue, } // descending tables Table descUnsorted = TableTools.newTable(intCol("num", data)); - Table descSorted = descUnsorted.sort("num"); + Table descSorted = descUnsorted.sortDescending("num"); assertSeekPositionAllRows(ascUnsorted, seekValue, ascForwardPositions, ascBackwardPositions); assertSeekPositionAllRows(ascSorted, seekValue, ascForwardPositions, ascBackwardPositions); From aac6924e01e9ee34e0793a10098fb6211ce9568b Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Wed, 20 Mar 2024 15:24:51 -0400 Subject: [PATCH 14/21] add null default --- .../main/java/io/deephaven/clientsupport/gotorow/SeekRow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index e22600c5d07..2c605f1d622 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -51,7 +51,7 @@ public SeekRow(long startingRow, String columnName, Object seekValue, boolean in @ConcurrentMethod public long seek(Table table) { - final Mutable result = new MutableObject<>(-1L); + final Mutable result = new MutableObject<>(null); ConstructSnapshot.callDataSnapshotFunction("SeekRow", ConstructSnapshot.makeSnapshotControl(false, table.isRefreshing(), (NotificationStepSource) table), From fb14b634e2eabd69c9cd7c6ea200710ad94323b1 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Thu, 21 Mar 2024 14:00:03 -0400 Subject: [PATCH 15/21] remove closest value seek --- .../clientsupport/gotorow/SeekRow.java | 95 ++----------------- 1 file changed, 8 insertions(+), 87 deletions(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index 2c605f1d622..c98f8c5d837 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -3,8 +3,6 @@ // package io.deephaven.clientsupport.gotorow; -import java.time.Instant; - import io.deephaven.api.util.ConcurrentMethod; import io.deephaven.base.verify.Require; import io.deephaven.engine.rowset.RowSet; @@ -16,7 +14,6 @@ import io.deephaven.engine.table.impl.remote.ConstructSnapshot; import io.deephaven.internal.log.LoggerFactory; import io.deephaven.io.logger.Logger; -import io.deephaven.time.DateTimeUtils; import org.apache.commons.lang3.mutable.Mutable; import org.apache.commons.lang3.mutable.MutableObject; @@ -30,11 +27,7 @@ public class SeekRow { private final boolean contains; private final boolean isBackward; - private Comparable closestUpperValueYet; - private Comparable closestLowerValueYet; private ColumnSource columnSource; - private long closestUpperRowYet = -1; - private long closestLowerRowYet = -1; private boolean usePrev; private static final Logger log = LoggerFactory.getLogger(SeekRow.class); @@ -123,70 +116,34 @@ public long seek(Table table) { row = findRow(rowSet, 0, (int) startingRow); if (row >= 0) { result.setValue(row); + log.info().append("found 1").endl(); return true; } row = findRow(rowSet, (int) startingRow, (int) rowSet.size()); if (row >= 0) { result.setValue(row); + log.info().append("found 2").endl(); return true; } } else { row = findRow(rowSet, (int) startingRow + 1, (int) rowSet.size()); if (row >= 0) { result.setValue(row); + log.info().append("found 3").endl(); return true; } row = findRow(rowSet, 0, (int) startingRow + 1); if (row >= 0) { result.setValue(row); + log.info().append("found 4").endl(); return true; } } - - // just go to the closest value - if (closestLowerValueYet == null && closestUpperValueYet == null) { - result.setValue(-1L); - } else if (closestLowerValueYet == null) { - result.setValue(rowSet.find(closestUpperRowYet)); - } else if (closestUpperValueYet == null) { - result.setValue(rowSet.find(closestUpperRowYet)); - } else { - // we need to decide between the two - Class columnType = columnSource.getType(); - if (Number.class.isAssignableFrom(columnType)) { - double nu = ((Number) closestUpperValueYet).doubleValue(); - double nl = ((Number) closestLowerRowYet).doubleValue(); - double ns = ((Number) seekValue).doubleValue(); - double du = Math.abs(nu - ns); - double dl = Math.abs(nl - ns); - log.info().append("Using numerical distance (").appendDouble(dl).append(", ") - .appendDouble(du) - .append(")").endl(); - result.setValue(rowSet.find(du < dl ? closestUpperRowYet : closestLowerRowYet)); - } else if (Instant.class.isAssignableFrom(columnType)) { - long nu = DateTimeUtils.epochNanos(((Instant) closestUpperValueYet)); - long nl = DateTimeUtils.epochNanos(((Instant) closestLowerValueYet)); - long ns = DateTimeUtils.epochNanos(((Instant) seekValue)); - long du = Math.abs(nu - ns); - long dl = Math.abs(nl - ns); - log.info().append("Using nano distance (").append(dl).append(", ").append(du).append(")") - .endl(); - result.setValue(rowSet.find(du < dl ? closestUpperRowYet : closestLowerRowYet)); - } else { - long nu = rowSet.find(closestUpperRowYet); - long nl = rowSet.find(closestLowerRowYet); - long ns = startingRow; - long du = Math.abs(nu - ns); - long dl = Math.abs(nl - ns); - log.info().append("Using index distance (").append(dl).append(", ").append(du).append(")") - .endl(); - result.setValue(du < dl ? nu : nl); - } - } - + result.setValue(-1L); return true; })); + log.info().append(result.getValue()).endl(); return result.getValue(); } @@ -225,8 +182,6 @@ private long findEdgeOccurrence(RowSet index, long start, long end, boolean find end = mid - 1; } } - log.info().append("searching from ").append(start).append(" to ").append(end).append(": ").append(result) - .endl(); return result; } @@ -261,9 +216,6 @@ private long findRow(RowSet index, int start, int end) { it = subIndex.iterator(); } - final boolean isComparable = !contains - && (Comparable.class.isAssignableFrom(columnSource.getType()) || columnSource.getType().isPrimitive()); - final Object useSeek = (seekValue instanceof String && insensitive) ? ((String) seekValue).toLowerCase() : seekValue; @@ -278,41 +230,10 @@ private long findRow(RowSet index, int start, int end) { } // noinspection ConstantConditions if (contains && value != null && ((String) value).contains((String) useSeek)) { - return (long) Require.geqZero(index.find(key), "index.find(key)"); + return Require.geqZero(index.find(key), "index.find(key)"); } if (value == useSeek || (useSeek != null && useSeek.equals(value))) { - return (long) Require.geqZero(index.find(key), "index.find(key)"); - } - - if (isComparable && useSeek != null && value != null) { - // noinspection unchecked - long compareResult = ((Comparable) useSeek).compareTo(value); - if (compareResult < 0) { - // seekValue is less than value - if (closestUpperRowYet == -1) { - closestUpperRowYet = key; - closestUpperValueYet = (Comparable) value; - } else { - // noinspection unchecked - if (closestUpperValueYet.compareTo(value) > 0) { - closestUpperValueYet = (Comparable) value; - closestUpperRowYet = key; - } - } - } else { - // seekValue is greater than value - // seekValue is less than value - if (closestLowerRowYet == -1) { - closestLowerRowYet = key; - closestLowerValueYet = (Comparable) value; - } else { - // noinspection unchecked - if (closestLowerValueYet.compareTo(value) < 0) { - closestLowerValueYet = (Comparable) value; - closestLowerRowYet = key; - } - } - } + return Require.geqZero(index.find(key), "index.find(key)"); } } From 95cf58acd04273530065d56c9e5113cf9e6e54f2 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 25 Mar 2024 14:43:37 -0400 Subject: [PATCH 16/21] assert non null Co-authored-by: Colin Alworth --- .../main/java/io/deephaven/clientsupport/gotorow/SeekRow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index c98f8c5d837..f5ee1660122 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -143,7 +143,7 @@ public long seek(Table table) { return true; })); - log.info().append(result.getValue()).endl(); + Assert.neqNull(result.getValue(), "result.getValue()"); return result.getValue(); } From c313b2df02ea51807654cb464d9d2688a938493f Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 25 Mar 2024 14:53:41 -0400 Subject: [PATCH 17/21] clean --- .../java/io/deephaven/clientsupport/gotorow/SeekRow.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java index f5ee1660122..73c2a855f0c 100644 --- a/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java +++ b/ClientSupport/src/main/java/io/deephaven/clientsupport/gotorow/SeekRow.java @@ -4,6 +4,7 @@ package io.deephaven.clientsupport.gotorow; import io.deephaven.api.util.ConcurrentMethod; +import io.deephaven.base.verify.Assert; import io.deephaven.base.verify.Require; import io.deephaven.engine.rowset.RowSet; import io.deephaven.engine.table.ColumnSource; @@ -116,26 +117,22 @@ public long seek(Table table) { row = findRow(rowSet, 0, (int) startingRow); if (row >= 0) { result.setValue(row); - log.info().append("found 1").endl(); return true; } row = findRow(rowSet, (int) startingRow, (int) rowSet.size()); if (row >= 0) { result.setValue(row); - log.info().append("found 2").endl(); return true; } } else { row = findRow(rowSet, (int) startingRow + 1, (int) rowSet.size()); if (row >= 0) { result.setValue(row); - log.info().append("found 3").endl(); return true; } row = findRow(rowSet, 0, (int) startingRow + 1); if (row >= 0) { result.setValue(row); - log.info().append("found 4").endl(); return true; } } From df5b61801c3887c461f20caa7123ec90042d77c3 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 25 Mar 2024 16:09:20 -0400 Subject: [PATCH 18/21] update unsorted test --- .../clientsupport/gotorow/SeekRowTest.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java index 6aa6bce154c..9137774df90 100644 --- a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java +++ b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java @@ -299,9 +299,14 @@ public void notFound() { @Test public void unsorted() { - final Table t = newTable(intCol("num", 3, 1, 2, 1, 3, 2)); + final Table t = newTable(intCol("num", 3, 1, 1, 2, 3, 1, 1, 2)); + assertSeekPositionAllRows(t, 1, + new int[] {1, 2, 5, 5, 5, 6, 1, 1}, + new int[] {6, 6, 1, 2, 2, 2, 5, 6}); assertSeekPositionAllRows(t, 2, - new int[] {2, 2, 5, 5, 5, 2}, - new int[] {5, 5, 5, 2, 2, 2}); - } + new int[] {3, 3, 3, 7, 7, 7, 7, 3}, + new int[] {6, 6, 1, 2, 2, 2, 5, 6}); + assertSeekPositionAllRows(t, 3, + new int[] {4, 4, 4, 4, 0, 0, 0, 0}, + new int[] {6, 6, 1, 2, 2, 2, 5, 6}); } From 912e6e2be51c61375575aec14b2d669ce282b52a Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 25 Mar 2024 16:27:19 -0400 Subject: [PATCH 19/21] clean --- .../clientsupport/gotorow/SeekRowTest.java | 211 +++++++++--------- 1 file changed, 106 insertions(+), 105 deletions(-) diff --git a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java index 9137774df90..fe9e15a2cab 100644 --- a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java +++ b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java @@ -23,7 +23,7 @@ public class SeekRowTest { /** * Helper to verify that a given value can not be found no matter which row is started from * - * @param t the table to search + * @param t the table to search * @param impossibleValue a value that isn't present in the table */ public static void assertNotFound(int impossibleValue, Table t) { @@ -38,14 +38,14 @@ public static void assertNotFound(int impossibleValue, Table t) { * Helper to run SeekRow and validate that the discovered row is what was expected. Validates the * {@code expectedPosition} before running, to ensure test data makes sense. * - * @param t the table to search - * @param seekValue the value to search for - * @param seekForward true to seek forward, false to seek backward - * @param currentPosition the position to start searching + * @param t the table to search + * @param seekValue the value to search for + * @param seekForward true to seek forward, false to seek backward + * @param currentPosition the position to start searching * @param expectedPosition the next expected position of the seek value */ private static void assertSeekPosition(Table t, int seekValue, boolean seekForward, int currentPosition, - int expectedPosition) { + int expectedPosition) { if (expectedPosition != -1) { // Confirm that the expected position matches assertEquals(seekValue, t.flatten().getColumnSource("num").getInt(expectedPosition)); @@ -62,13 +62,13 @@ private static void assertSeekPosition(Table t, int seekValue, boolean seekForwa * Helper to seek from every row in a table, and assert that a valid value can be found in a valid position from * each. * - * @param t the table to search - * @param seekValue the value to search for - * @param forwardPositions expected positions when searching forward, indexed on starting row + * @param t the table to search + * @param seekValue the value to search for + * @param forwardPositions expected positions when searching forward, indexed on starting row * @param backwardPositions expected positions when searching backwards, indexed on starting row */ private static void assertSeekPositionAllRows(Table t, int seekValue, int[] forwardPositions, - int[] backwardPositions) { + int[] backwardPositions) { assertEquals(t.size(), forwardPositions.length); assertEquals(t.size(), backwardPositions.length); for (int i = 0; i < t.size(); i++) { @@ -80,17 +80,17 @@ private static void assertSeekPositionAllRows(Table t, int seekValue, int[] forw /** * Helper to run asserts for int rows that are already sorted at initialization - * - * @param data the data, must be sorted in ascending order already - * @param seekValue the value to search for - * @param ascForwardPositions expected positions when searching forwards for ascending data - * @param ascBackwardPositions expected positions when searching backwards for ascending data - * @param descForwardPositions expected positions when searching forwards for descending data + * + * @param data the data, must be sorted in ascending order already + * @param seekValue the value to search for + * @param ascForwardPositions expected positions when searching forwards for ascending data + * @param ascBackwardPositions expected positions when searching backwards for ascending data + * @param descForwardPositions expected positions when searching forwards for descending data * @param descBackwardPositions expected positions when searching backwards for descending data */ private static void assertNaturallySorted(int[] data, int seekValue, - int[] ascForwardPositions, int[] ascBackwardPositions, - int[] descForwardPositions, int[] descBackwardPositions) { + int[] ascForwardPositions, int[] ascBackwardPositions, + int[] descForwardPositions, int[] descBackwardPositions) { // ascending tables Table ascUnsorted = TableTools.newTable(intCol("num", data)); Table ascSorted = ascUnsorted.sort("num"); @@ -152,161 +152,162 @@ public void singleRow() { @Test public void mono1() { assertNaturallySorted( - new int[] {1}, 1, - new int[] {0}, - new int[] {0}, - new int[] {0}, - new int[] {0}); + new int[]{1}, 1, + new int[]{0}, + new int[]{0}, + new int[]{0}, + new int[]{0}); } @Test public void mono2() { assertNaturallySorted( - new int[] {1, 1}, 1, - new int[] {1, 0}, - new int[] {1, 0}, - new int[] {1, 0}, - new int[] {1, 0}); + new int[]{1, 1}, 1, + new int[]{1, 0}, + new int[]{1, 0}, + new int[]{1, 0}, + new int[]{1, 0}); } @Test public void mono3() { assertNaturallySorted( - new int[] {1, 1, 1}, 1, - new int[] {1, 2, 0}, - new int[] {2, 0, 1}, - new int[] {1, 2, 0}, - new int[] {2, 0, 1}); + new int[]{1, 1, 1}, 1, + new int[]{1, 2, 0}, + new int[]{2, 0, 1}, + new int[]{1, 2, 0}, + new int[]{2, 0, 1}); } @Test public void start1() { assertNaturallySorted( - new int[] {1, 2}, 1, - new int[] {0, 0}, - new int[] {0, 0}, - new int[] {1, 1}, - new int[] {1, 1}); + new int[]{1, 2}, 1, + new int[]{0, 0}, + new int[]{0, 0}, + new int[]{1, 1}, + new int[]{1, 1}); } @Test public void start2() { assertNaturallySorted( - new int[] {1, 1, 2}, 1, - new int[] {1, 0, 0}, - new int[] {1, 0, 1}, - new int[] {1, 2, 1}, - new int[] {2, 2, 1}); + new int[]{1, 1, 2}, 1, + new int[]{1, 0, 0}, + new int[]{1, 0, 1}, + new int[]{1, 2, 1}, + new int[]{2, 2, 1}); } @Test public void start3() { assertNaturallySorted( - new int[] {1, 1, 1, 2}, 1, - new int[] {1, 2, 0, 0}, - new int[] {2, 0, 1, 2}, - new int[] {1, 2, 3, 1}, - new int[] {3, 3, 1, 2}); + new int[]{1, 1, 1, 2}, 1, + new int[]{1, 2, 0, 0}, + new int[]{2, 0, 1, 2}, + new int[]{1, 2, 3, 1}, + new int[]{3, 3, 1, 2}); } @Test public void middle1() { assertNaturallySorted( - new int[] {1, 2, 3}, 2, - new int[] {1, 1, 1}, - new int[] {1, 1, 1}, - new int[] {1, 1, 1}, - new int[] {1, 1, 1}); + new int[]{1, 2, 3}, 2, + new int[]{1, 1, 1}, + new int[]{1, 1, 1}, + new int[]{1, 1, 1}, + new int[]{1, 1, 1}); } @Test public void middle2() { assertNaturallySorted( - new int[] {1, 2, 2, 3}, 2, - new int[] {1, 2, 1, 1}, - new int[] {2, 2, 1, 2}, - new int[] {1, 2, 1, 1}, - new int[] {2, 2, 1, 2}); + new int[]{1, 2, 2, 3}, 2, + new int[]{1, 2, 1, 1}, + new int[]{2, 2, 1, 2}, + new int[]{1, 2, 1, 1}, + new int[]{2, 2, 1, 2}); } @Test public void middle3() { assertNaturallySorted( - new int[] {1, 2, 2, 2, 3}, 2, - new int[] {1, 2, 3, 1, 1}, - new int[] {3, 3, 1, 2, 3}, - new int[] {1, 2, 3, 1, 1}, - new int[] {3, 3, 1, 2, 3}); + new int[]{1, 2, 2, 2, 3}, 2, + new int[]{1, 2, 3, 1, 1}, + new int[]{3, 3, 1, 2, 3}, + new int[]{1, 2, 3, 1, 1}, + new int[]{3, 3, 1, 2, 3}); } @Test public void end1() { assertNaturallySorted( - new int[] {1, 2}, 2, - new int[] {1, 1}, - new int[] {1, 1}, - new int[] {0, 0}, - new int[] {0, 0}); + new int[]{1, 2}, 2, + new int[]{1, 1}, + new int[]{1, 1}, + new int[]{0, 0}, + new int[]{0, 0}); } @Test public void end2() { assertNaturallySorted( - new int[] {1, 2, 2}, 2, - new int[] {1, 2, 1}, - new int[] {2, 2, 1}, - new int[] {1, 0, 0}, - new int[] {1, 0, 1}); + new int[]{1, 2, 2}, 2, + new int[]{1, 2, 1}, + new int[]{2, 2, 1}, + new int[]{1, 0, 0}, + new int[]{1, 0, 1}); } @Test public void end3() { assertNaturallySorted( - new int[] {1, 2, 2, 2}, 2, - new int[] {1, 2, 3, 1}, - new int[] {3, 3, 1, 2}, - new int[] {1, 2, 0, 0}, - new int[] {2, 0, 1, 2}); + new int[]{1, 2, 2, 2}, 2, + new int[]{1, 2, 3, 1}, + new int[]{3, 3, 1, 2}, + new int[]{1, 2, 0, 0}, + new int[]{2, 0, 1, 2}); } @Test public void notFound() { assertNaturallySorted( - new int[] {2, 4, 6}, 1, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}); + new int[]{2, 4, 6}, 1, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}); assertNaturallySorted( - new int[] {2, 4, 6}, 3, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}); + new int[]{2, 4, 6}, 3, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}); assertNaturallySorted( - new int[] {2, 4, 6}, 5, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}); + new int[]{2, 4, 6}, 5, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}); assertNaturallySorted( - new int[] {2, 4, 6}, 7, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}, - new int[] {-1, -1, -1}); + new int[]{2, 4, 6}, 7, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}, + new int[]{-1, -1, -1}); } @Test public void unsorted() { final Table t = newTable(intCol("num", 3, 1, 1, 2, 3, 1, 1, 2)); assertSeekPositionAllRows(t, 1, - new int[] {1, 2, 5, 5, 5, 6, 1, 1}, - new int[] {6, 6, 1, 2, 2, 2, 5, 6}); + new int[]{1, 2, 5, 5, 5, 6, 1, 1}, + new int[]{6, 6, 1, 2, 2, 2, 5, 6}); assertSeekPositionAllRows(t, 2, - new int[] {3, 3, 3, 7, 7, 7, 7, 3}, - new int[] {6, 6, 1, 2, 2, 2, 5, 6}); + new int[]{3, 3, 3, 7, 7, 7, 7, 3}, + new int[]{6, 6, 1, 2, 2, 2, 5, 6}); assertSeekPositionAllRows(t, 3, - new int[] {4, 4, 4, 4, 0, 0, 0, 0}, - new int[] {6, 6, 1, 2, 2, 2, 5, 6}); -} + new int[]{4, 4, 4, 4, 0, 0, 0, 0}, + new int[]{6, 6, 1, 2, 2, 2, 5, 6}); + } +} \ No newline at end of file From 194e1dbc36c1cf25a643e376c7d038f477119c9f Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 25 Mar 2024 17:10:20 -0400 Subject: [PATCH 20/21] fix formatting --- .../clientsupport/gotorow/SeekRowTest.java | 208 +++++++++--------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java index fe9e15a2cab..9fa90ffe362 100644 --- a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java +++ b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java @@ -23,7 +23,7 @@ public class SeekRowTest { /** * Helper to verify that a given value can not be found no matter which row is started from * - * @param t the table to search + * @param t the table to search * @param impossibleValue a value that isn't present in the table */ public static void assertNotFound(int impossibleValue, Table t) { @@ -38,14 +38,14 @@ public static void assertNotFound(int impossibleValue, Table t) { * Helper to run SeekRow and validate that the discovered row is what was expected. Validates the * {@code expectedPosition} before running, to ensure test data makes sense. * - * @param t the table to search - * @param seekValue the value to search for - * @param seekForward true to seek forward, false to seek backward - * @param currentPosition the position to start searching + * @param t the table to search + * @param seekValue the value to search for + * @param seekForward true to seek forward, false to seek backward + * @param currentPosition the position to start searching * @param expectedPosition the next expected position of the seek value */ private static void assertSeekPosition(Table t, int seekValue, boolean seekForward, int currentPosition, - int expectedPosition) { + int expectedPosition) { if (expectedPosition != -1) { // Confirm that the expected position matches assertEquals(seekValue, t.flatten().getColumnSource("num").getInt(expectedPosition)); @@ -62,13 +62,13 @@ private static void assertSeekPosition(Table t, int seekValue, boolean seekForwa * Helper to seek from every row in a table, and assert that a valid value can be found in a valid position from * each. * - * @param t the table to search - * @param seekValue the value to search for - * @param forwardPositions expected positions when searching forward, indexed on starting row + * @param t the table to search + * @param seekValue the value to search for + * @param forwardPositions expected positions when searching forward, indexed on starting row * @param backwardPositions expected positions when searching backwards, indexed on starting row */ private static void assertSeekPositionAllRows(Table t, int seekValue, int[] forwardPositions, - int[] backwardPositions) { + int[] backwardPositions) { assertEquals(t.size(), forwardPositions.length); assertEquals(t.size(), backwardPositions.length); for (int i = 0; i < t.size(); i++) { @@ -81,16 +81,16 @@ private static void assertSeekPositionAllRows(Table t, int seekValue, int[] forw /** * Helper to run asserts for int rows that are already sorted at initialization * - * @param data the data, must be sorted in ascending order already - * @param seekValue the value to search for - * @param ascForwardPositions expected positions when searching forwards for ascending data - * @param ascBackwardPositions expected positions when searching backwards for ascending data - * @param descForwardPositions expected positions when searching forwards for descending data + * @param data the data, must be sorted in ascending order already + * @param seekValue the value to search for + * @param ascForwardPositions expected positions when searching forwards for ascending data + * @param ascBackwardPositions expected positions when searching backwards for ascending data + * @param descForwardPositions expected positions when searching forwards for descending data * @param descBackwardPositions expected positions when searching backwards for descending data */ private static void assertNaturallySorted(int[] data, int seekValue, - int[] ascForwardPositions, int[] ascBackwardPositions, - int[] descForwardPositions, int[] descBackwardPositions) { + int[] ascForwardPositions, int[] ascBackwardPositions, + int[] descForwardPositions, int[] descBackwardPositions) { // ascending tables Table ascUnsorted = TableTools.newTable(intCol("num", data)); Table ascSorted = ascUnsorted.sort("num"); @@ -152,162 +152,162 @@ public void singleRow() { @Test public void mono1() { assertNaturallySorted( - new int[]{1}, 1, - new int[]{0}, - new int[]{0}, - new int[]{0}, - new int[]{0}); + new int[] {1}, 1, + new int[] {0}, + new int[] {0}, + new int[] {0}, + new int[] {0}); } @Test public void mono2() { assertNaturallySorted( - new int[]{1, 1}, 1, - new int[]{1, 0}, - new int[]{1, 0}, - new int[]{1, 0}, - new int[]{1, 0}); + new int[] {1, 1}, 1, + new int[] {1, 0}, + new int[] {1, 0}, + new int[] {1, 0}, + new int[] {1, 0}); } @Test public void mono3() { assertNaturallySorted( - new int[]{1, 1, 1}, 1, - new int[]{1, 2, 0}, - new int[]{2, 0, 1}, - new int[]{1, 2, 0}, - new int[]{2, 0, 1}); + new int[] {1, 1, 1}, 1, + new int[] {1, 2, 0}, + new int[] {2, 0, 1}, + new int[] {1, 2, 0}, + new int[] {2, 0, 1}); } @Test public void start1() { assertNaturallySorted( - new int[]{1, 2}, 1, - new int[]{0, 0}, - new int[]{0, 0}, - new int[]{1, 1}, - new int[]{1, 1}); + new int[] {1, 2}, 1, + new int[] {0, 0}, + new int[] {0, 0}, + new int[] {1, 1}, + new int[] {1, 1}); } @Test public void start2() { assertNaturallySorted( - new int[]{1, 1, 2}, 1, - new int[]{1, 0, 0}, - new int[]{1, 0, 1}, - new int[]{1, 2, 1}, - new int[]{2, 2, 1}); + new int[] {1, 1, 2}, 1, + new int[] {1, 0, 0}, + new int[] {1, 0, 1}, + new int[] {1, 2, 1}, + new int[] {2, 2, 1}); } @Test public void start3() { assertNaturallySorted( - new int[]{1, 1, 1, 2}, 1, - new int[]{1, 2, 0, 0}, - new int[]{2, 0, 1, 2}, - new int[]{1, 2, 3, 1}, - new int[]{3, 3, 1, 2}); + new int[] {1, 1, 1, 2}, 1, + new int[] {1, 2, 0, 0}, + new int[] {2, 0, 1, 2}, + new int[] {1, 2, 3, 1}, + new int[] {3, 3, 1, 2}); } @Test public void middle1() { assertNaturallySorted( - new int[]{1, 2, 3}, 2, - new int[]{1, 1, 1}, - new int[]{1, 1, 1}, - new int[]{1, 1, 1}, - new int[]{1, 1, 1}); + new int[] {1, 2, 3}, 2, + new int[] {1, 1, 1}, + new int[] {1, 1, 1}, + new int[] {1, 1, 1}, + new int[] {1, 1, 1}); } @Test public void middle2() { assertNaturallySorted( - new int[]{1, 2, 2, 3}, 2, - new int[]{1, 2, 1, 1}, - new int[]{2, 2, 1, 2}, - new int[]{1, 2, 1, 1}, - new int[]{2, 2, 1, 2}); + new int[] {1, 2, 2, 3}, 2, + new int[] {1, 2, 1, 1}, + new int[] {2, 2, 1, 2}, + new int[] {1, 2, 1, 1}, + new int[] {2, 2, 1, 2}); } @Test public void middle3() { assertNaturallySorted( - new int[]{1, 2, 2, 2, 3}, 2, - new int[]{1, 2, 3, 1, 1}, - new int[]{3, 3, 1, 2, 3}, - new int[]{1, 2, 3, 1, 1}, - new int[]{3, 3, 1, 2, 3}); + new int[] {1, 2, 2, 2, 3}, 2, + new int[] {1, 2, 3, 1, 1}, + new int[] {3, 3, 1, 2, 3}, + new int[] {1, 2, 3, 1, 1}, + new int[] {3, 3, 1, 2, 3}); } @Test public void end1() { assertNaturallySorted( - new int[]{1, 2}, 2, - new int[]{1, 1}, - new int[]{1, 1}, - new int[]{0, 0}, - new int[]{0, 0}); + new int[] {1, 2}, 2, + new int[] {1, 1}, + new int[] {1, 1}, + new int[] {0, 0}, + new int[] {0, 0}); } @Test public void end2() { assertNaturallySorted( - new int[]{1, 2, 2}, 2, - new int[]{1, 2, 1}, - new int[]{2, 2, 1}, - new int[]{1, 0, 0}, - new int[]{1, 0, 1}); + new int[] {1, 2, 2}, 2, + new int[] {1, 2, 1}, + new int[] {2, 2, 1}, + new int[] {1, 0, 0}, + new int[] {1, 0, 1}); } @Test public void end3() { assertNaturallySorted( - new int[]{1, 2, 2, 2}, 2, - new int[]{1, 2, 3, 1}, - new int[]{3, 3, 1, 2}, - new int[]{1, 2, 0, 0}, - new int[]{2, 0, 1, 2}); + new int[] {1, 2, 2, 2}, 2, + new int[] {1, 2, 3, 1}, + new int[] {3, 3, 1, 2}, + new int[] {1, 2, 0, 0}, + new int[] {2, 0, 1, 2}); } @Test public void notFound() { assertNaturallySorted( - new int[]{2, 4, 6}, 1, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}); + new int[] {2, 4, 6}, 1, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}); assertNaturallySorted( - new int[]{2, 4, 6}, 3, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}); + new int[] {2, 4, 6}, 3, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}); assertNaturallySorted( - new int[]{2, 4, 6}, 5, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}); + new int[] {2, 4, 6}, 5, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}); assertNaturallySorted( - new int[]{2, 4, 6}, 7, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}, - new int[]{-1, -1, -1}); + new int[] {2, 4, 6}, 7, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}, + new int[] {-1, -1, -1}); } @Test public void unsorted() { final Table t = newTable(intCol("num", 3, 1, 1, 2, 3, 1, 1, 2)); assertSeekPositionAllRows(t, 1, - new int[]{1, 2, 5, 5, 5, 6, 1, 1}, - new int[]{6, 6, 1, 2, 2, 2, 5, 6}); + new int[] {1, 2, 5, 5, 5, 6, 1, 1}, + new int[] {6, 6, 1, 2, 2, 2, 5, 6}); assertSeekPositionAllRows(t, 2, - new int[]{3, 3, 3, 7, 7, 7, 7, 3}, - new int[]{6, 6, 1, 2, 2, 2, 5, 6}); + new int[] {3, 3, 3, 7, 7, 7, 7, 3}, + new int[] {6, 6, 1, 2, 2, 2, 5, 6}); assertSeekPositionAllRows(t, 3, - new int[]{4, 4, 4, 4, 0, 0, 0, 0}, - new int[]{6, 6, 1, 2, 2, 2, 5, 6}); + new int[] {4, 4, 4, 4, 0, 0, 0, 0}, + new int[] {6, 6, 1, 2, 2, 2, 5, 6}); } -} \ No newline at end of file +} From fa80a627b1657f31619131266d9a468f4e69c3b3 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Tue, 26 Mar 2024 11:01:03 -0400 Subject: [PATCH 21/21] fix tests --- .../java/io/deephaven/clientsupport/gotorow/SeekRowTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java index 9fa90ffe362..d2367a00f3c 100644 --- a/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java +++ b/ClientSupport/src/test/java/io/deephaven/clientsupport/gotorow/SeekRowTest.java @@ -305,9 +305,9 @@ public void unsorted() { new int[] {6, 6, 1, 2, 2, 2, 5, 6}); assertSeekPositionAllRows(t, 2, new int[] {3, 3, 3, 7, 7, 7, 7, 3}, - new int[] {6, 6, 1, 2, 2, 2, 5, 6}); + new int[] {7, 7, 7, 7, 3, 3, 3, 3}); assertSeekPositionAllRows(t, 3, new int[] {4, 4, 4, 4, 0, 0, 0, 0}, - new int[] {6, 6, 1, 2, 2, 2, 5, 6}); + new int[] {4, 0, 0, 0, 0, 4, 4, 4}); } }