Skip to content

Commit

Permalink
Fix ZonedDateTime and Array Shenanigans
Browse files Browse the repository at this point in the history
  • Loading branch information
nbauernfeind committed Jun 7, 2024
1 parent 89eee34 commit 480bedf
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,15 @@ Object convertParamValue(Object paramValue) {
return paramValue;
}

final void convertValue(
/**
* Convert the string value to the appropriate type for the column.
* @param column the column definition
* @param strValue the string value to convert
* @param queryScopeVariables the query scope variables
* @param valueConsumer the consumer for the converted value
* @return whether the value was an array or collection
*/
final boolean convertValue(
@NotNull final ColumnDefinition<?> column,
@NotNull final String strValue,
@NotNull final Map<String, Object> queryScopeVariables,
Expand All @@ -279,10 +287,12 @@ final void convertValue(
for (int ai = 0; ai < accessor.length(); ++ai) {
valueConsumer.accept(convertParamValue(accessor.get(ai)));
}
return true;
} else if (paramValue != null && Collection.class.isAssignableFrom(paramValue.getClass())) {
for (final Object paramValueMember : (Collection<?>) paramValue) {
valueConsumer.accept(convertParamValue(paramValueMember));
}
return true;
} else {
valueConsumer.accept(convertParamValue(paramValue));
}
Expand All @@ -294,6 +304,7 @@ final void convertValue(
"> for column \"" + column.getName() + "\" of type " + column.getDataType().getName(), t);
}
}
return false;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,12 @@ public void init(
MatchFilter.ColumnTypeConvertorFactory.getConvertor(def.getDataType());

final MutableObject<Object> realValue = new MutableObject<>();
convertor.convertValue(def, value, compilationProcessor.getQueryScopeVariables(),
parsedValue -> {
if (realValue.getValue() != null) {
throw new IllegalArgumentException(value + " is an array type");
}
realValue.setValue(parsedValue);
});
boolean wasAnArrayType = convertor.convertValue(
def, value, compilationProcessor.getQueryScopeVariables(), realValue::setValue);
if (wasAnArrayType) {
throw new IllegalArgumentException("RangeConditionFilter does not support array types for column "
+ columnName + " with value <" + value + ">");
}

if (colClass == double.class || colClass == Double.class) {
filter = DoubleRangeFilter.makeDoubleRangeFilter(columnName, condition, (double) realValue.getValue());
Expand Down Expand Up @@ -231,6 +230,21 @@ private static LongRangeFilter makeInstantRangeFilter(String columnName, Conditi
}
}

private static LongRangeFilter makeZonedDateTimeRangeFilter(String columnName, Condition condition, long value) {
switch (condition) {
case LESS_THAN:
return new ZonedDateTimeRangeFilter(columnName, value, Long.MIN_VALUE, true, false);
case LESS_THAN_OR_EQUAL:
return new ZonedDateTimeRangeFilter(columnName, value, Long.MIN_VALUE, true, true);
case GREATER_THAN:
return new ZonedDateTimeRangeFilter(columnName, value, Long.MAX_VALUE, false, true);
case GREATER_THAN_OR_EQUAL:
return new ZonedDateTimeRangeFilter(columnName, value, Long.MAX_VALUE, true, true);
default:
throw new IllegalArgumentException("RangeConditionFilter does not support condition " + condition);
}
}

private static SingleSidedComparableRangeFilter makeComparableRangeFilter(String columnName, Condition condition,
Comparable<?> comparable) {
switch (condition) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
//
package io.deephaven.engine.table.impl.select;

import io.deephaven.base.verify.Assert;
import io.deephaven.engine.table.ColumnDefinition;
import io.deephaven.engine.table.TableDefinition;
import io.deephaven.engine.table.impl.chunkfilter.ChunkFilter;
import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys;
import io.deephaven.engine.table.ColumnSource;
import io.deephaven.engine.table.impl.sources.ReinterpretUtils;
import io.deephaven.chunk.*;
import io.deephaven.chunk.attributes.Values;
import io.deephaven.engine.rowset.WritableRowSet;
import io.deephaven.engine.rowset.RowSet;
import io.deephaven.time.DateTimeUtils;
import org.jetbrains.annotations.NotNull;

import java.time.ZonedDateTime;

public class ZonedDateTimeRangeFilter extends LongRangeFilter {

public ZonedDateTimeRangeFilter(String columnName, ZonedDateTime val1, ZonedDateTime val2) {
super(columnName, DateTimeUtils.epochNanos(val1), DateTimeUtils.epochNanos(val2), true, true);
}

public ZonedDateTimeRangeFilter(
String columnName, ZonedDateTime val1, ZonedDateTime val2, boolean lowerInclusive, boolean upperInclusive) {
super(columnName, DateTimeUtils.epochNanos(val1), DateTimeUtils.epochNanos(val2),
lowerInclusive, upperInclusive);
}

public ZonedDateTimeRangeFilter(
String columnName, long val1, long val2, boolean lowerInclusive, boolean upperInclusive) {
super(columnName, val1, val2, lowerInclusive, upperInclusive);
}

@Override
public void init(@NotNull final TableDefinition tableDefinition) {
if (chunkFilter != null) {
return;
}

final ColumnDefinition<?> def = tableDefinition.getColumn(columnName);
if (def == null) {
throw new RuntimeException("Column \"" + columnName + "\" doesn't exist in this table, available columns: "
+ tableDefinition.getColumnNames());
}

final Class<?> colClass = def.getDataType();
Assert.eq(colClass, "colClass", ZonedDateTime.class);

longFilter = super.initChunkFilter();
chunkFilter = new ZonedDateTimeLongChunkFilterAdapter();
}

@Override
public ZonedDateTimeRangeFilter copy() {
final ZonedDateTimeRangeFilter copy =
new ZonedDateTimeRangeFilter(columnName, lower, upper, lowerInclusive, upperInclusive);
copy.chunkFilter = chunkFilter;
copy.longFilter = longFilter;
return copy;
}

@Override
public String toString() {
return "ZonedDateTimeRangeFilter(" + columnName + " in "
+ (lowerInclusive ? "[" : "(")
+ DateTimeUtils.epochNanosToInstant(lower) + "," + DateTimeUtils.epochNanosToInstant(upper)
+ (upperInclusive ? "]" : ")") + ")";
}

@NotNull
@Override
WritableRowSet binarySearch(
@NotNull final RowSet selection,
@NotNull final ColumnSource<?> columnSource,
final boolean usePrev,
final boolean reverse) {
if (selection.isEmpty()) {
return selection.copy();
}

// noinspection unchecked
final ColumnSource<Long> instantColumnSource =
ReinterpretUtils.zonedDateTimeToLongSource((ColumnSource<ZonedDateTime>) columnSource);
return super.binarySearch(selection, instantColumnSource, usePrev, reverse);
}

private class ZonedDateTimeLongChunkFilterAdapter implements ChunkFilter {
@Override
public void filter(Chunk<? extends Values> values, LongChunk<OrderedRowKeys> keys,
WritableLongChunk<OrderedRowKeys> results) {
try (final WritableLongChunk<Values> writableLongChunk =
WritableLongChunk.makeWritableChunk(values.size())) {

final ObjectChunk<ZonedDateTime, ? extends Values> objectValues = values.asObjectChunk();
for (int ii = 0; ii < values.size(); ++ii) {
final ZonedDateTime instant = objectValues.get(ii);
writableLongChunk.set(ii, DateTimeUtils.epochNanos(instant));
}
writableLongChunk.setSize(values.size());
longFilter.filter(writableLongChunk, keys, results);
}
}
}
}

0 comments on commit 480bedf

Please sign in to comment.