blob: 734d7e3d6e8cd67893f60e50cd234e873b31c658 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.druid.query.aggregation.firstlast.first;
import org.apache.druid.java.util.common.DateTimes;
import org.apache.druid.java.util.common.Pair;
import org.apache.druid.query.aggregation.SerializablePairLongDouble;
import org.apache.druid.query.aggregation.VectorAggregator;
import org.apache.druid.query.aggregation.firstlast.FirstLastVectorAggregator;
import org.apache.druid.query.dimension.DimensionSpec;
import org.apache.druid.segment.column.ColumnCapabilities;
import org.apache.druid.segment.column.ColumnCapabilitiesImpl;
import org.apache.druid.segment.column.ColumnType;
import org.apache.druid.segment.vector.BaseDoubleVectorValueSelector;
import org.apache.druid.segment.vector.BaseLongVectorValueSelector;
import org.apache.druid.segment.vector.MultiValueDimensionVectorSelector;
import org.apache.druid.segment.vector.NoFilterVectorOffset;
import org.apache.druid.segment.vector.ReadableVectorInspector;
import org.apache.druid.segment.vector.SingleValueDimensionVectorSelector;
import org.apache.druid.segment.vector.VectorColumnSelectorFactory;
import org.apache.druid.segment.vector.VectorObjectSelector;
import org.apache.druid.segment.vector.VectorValueSelector;
import org.apache.druid.testing.InitializedNullHandlingTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import javax.annotation.Nullable;
import java.nio.ByteBuffer;
import java.util.concurrent.ThreadLocalRandom;
public class DoubleFirstVectorAggregatorTest extends InitializedNullHandlingTest
{
private static final double EPSILON = 1e-5;
private static final double[] VALUES = new double[]{7.8d, 11, 23.67, 60};
private static final long[] LONG_VALUES = new long[]{1L, 2L, 3L, 4L};
private static final float[] FLOAT_VALUES = new float[]{1.0f, 2.0f, 3.0f, 4.0f};
private static final double[] DOUBLE_VALUES = new double[]{1.0, 2.0, 3.0, 4.0};
private static final String NAME = "NAME";
private static final String FIELD_NAME = "FIELD_NAME";
private static final String FIELD_NAME_LONG = "LONG_NAME";
private static final String TIME_COL = "__time";
private final long[] times = {2345001L, 2345100L, 2345200L, 2345300L};
private final SerializablePairLongDouble[] pairs = {
new SerializablePairLongDouble(2345001L, 1D),
new SerializablePairLongDouble(2345100L, 2D),
new SerializablePairLongDouble(2345200L, 3D),
new SerializablePairLongDouble(2345300L, 4D)
};
private VectorObjectSelector selector;
private BaseLongVectorValueSelector timeSelector;
private ByteBuffer buf;
private DoubleFirstVectorAggregator target;
private DoubleFirstAggregatorFactory doubleFirstAggregatorFactory;
private VectorColumnSelectorFactory selectorFactory;
private VectorValueSelector longValueSelector;
private VectorValueSelector doubleValueSelector;
@Before
public void setup()
{
byte[] randomBytes = new byte[1024];
ThreadLocalRandom.current().nextBytes(randomBytes);
buf = ByteBuffer.wrap(randomBytes);
timeSelector = new BaseLongVectorValueSelector(new NoFilterVectorOffset(times.length, 0, times.length)
{
})
{
@Override
public long[] getLongVector()
{
return times;
}
@Nullable
@Override
public boolean[] getNullVector()
{
return null;
}
};
selector = new VectorObjectSelector()
{
@Override
public Object[] getObjectVector()
{
return pairs;
}
@Override
public int getMaxVectorSize()
{
return 4;
}
@Override
public int getCurrentVectorSize()
{
return 0;
}
};
longValueSelector = new BaseLongVectorValueSelector(new NoFilterVectorOffset(
LONG_VALUES.length,
0,
LONG_VALUES.length
))
{
@Override
public long[] getLongVector()
{
return LONG_VALUES;
}
@Override
public float[] getFloatVector()
{
return FLOAT_VALUES;
}
@Override
public double[] getDoubleVector()
{
return DOUBLE_VALUES;
}
@Nullable
@Override
public boolean[] getNullVector()
{
return null;
}
@Override
public int getMaxVectorSize()
{
return 4;
}
@Override
public int getCurrentVectorSize()
{
return 4;
}
};
doubleValueSelector = new BaseDoubleVectorValueSelector(new NoFilterVectorOffset(VALUES.length, 0, VALUES.length))
{
@Override
public double[] getDoubleVector()
{
return VALUES;
}
@Nullable
@Override
public boolean[] getNullVector()
{
return null;
}
};
selectorFactory = new VectorColumnSelectorFactory()
{
@Override
public ReadableVectorInspector getReadableVectorInspector()
{
return new NoFilterVectorOffset(VALUES.length, 0, VALUES.length);
}
@Override
public SingleValueDimensionVectorSelector makeSingleValueDimensionSelector(DimensionSpec dimensionSpec)
{
return null;
}
@Override
public MultiValueDimensionVectorSelector makeMultiValueDimensionSelector(DimensionSpec dimensionSpec)
{
return null;
}
@Override
public VectorValueSelector makeValueSelector(String column)
{
if (TIME_COL.equals(column)) {
return timeSelector;
} else if (FIELD_NAME_LONG.equals(column)) {
return longValueSelector;
} else if (FIELD_NAME.equals(column)) {
return doubleValueSelector;
}
return null;
}
@Override
public VectorObjectSelector makeObjectSelector(String column)
{
if (FIELD_NAME.equals(column)) {
return selector;
} else {
return null;
}
}
@Nullable
@Override
public ColumnCapabilities getColumnCapabilities(String column)
{
if (FIELD_NAME.equals(column)) {
return ColumnCapabilitiesImpl.createSimpleNumericColumnCapabilities(ColumnType.DOUBLE);
} else if (FIELD_NAME_LONG.equals(column)) {
return ColumnCapabilitiesImpl.createSimpleNumericColumnCapabilities(ColumnType.LONG);
}
return null;
}
};
target = new DoubleFirstVectorAggregator(timeSelector, selector);
clearBufferForPositions(0, 0);
doubleFirstAggregatorFactory = new DoubleFirstAggregatorFactory(NAME, FIELD_NAME, TIME_COL);
}
@Test
public void testFactory()
{
Assert.assertTrue(doubleFirstAggregatorFactory.canVectorize(selectorFactory));
VectorAggregator vectorAggregator = doubleFirstAggregatorFactory.factorizeVector(selectorFactory);
Assert.assertNotNull(vectorAggregator);
Assert.assertEquals(DoubleFirstVectorAggregator.class, vectorAggregator.getClass());
}
@Test
public void testInit()
{
target.init(buf, 0);
Assert.assertEquals(DateTimes.MAX.getMillis(), buf.getLong(0));
Assert.assertEquals(0, buf.getDouble(FirstLastVectorAggregator.VALUE_OFFSET), EPSILON);
}
@Test
public void testAggregate()
{
target.aggregate(buf, 0, 0, pairs.length);
Pair<Long, Double> result = (Pair<Long, Double>) target.get(buf, 0);
Assert.assertEquals(pairs[0].lhs.longValue(), result.lhs.longValue());
Assert.assertEquals(pairs[0].rhs, result.rhs, EPSILON);
}
@Test
public void testAggregateWithNulls()
{
target.aggregate(buf, 0, 0, pairs.length);
Pair<Long, Double> result = (Pair<Long, Double>) target.get(buf, 0);
Assert.assertEquals(pairs[0].lhs.longValue(), result.lhs.longValue());
Assert.assertEquals(pairs[0].rhs, result.rhs, EPSILON);
}
@Test
public void testAggregateBatchWithoutRows()
{
int[] positions = new int[]{0, 43, 70};
int positionOffset = 2;
clearBufferForPositions(positionOffset, positions);
target.aggregate(buf, 3, positions, null, positionOffset);
for (int i = 0; i < positions.length; i++) {
Pair<Long, Double> result = (Pair<Long, Double>) target.get(buf, positions[i] + positionOffset);
Assert.assertEquals(pairs[i].getLhs().longValue(), result.lhs.longValue());
Assert.assertEquals(pairs[i].rhs, result.rhs, EPSILON);
}
}
@Test
public void testAggregateBatchWithRows()
{
int[] positions = new int[]{0, 43, 70};
int[] rows = new int[]{3, 0, 2};
int positionOffset = 2;
clearBufferForPositions(positionOffset, positions);
target.aggregate(buf, 3, positions, rows, positionOffset);
for (int i = 0; i < positions.length; i++) {
Pair<Long, Double> result = (Pair<Long, Double>) target.get(buf, positions[i] + positionOffset);
Assert.assertEquals(pairs[rows[i]].lhs.longValue(), result.lhs.longValue());
Assert.assertEquals(pairs[rows[i]].rhs, result.rhs, EPSILON);
}
}
private void clearBufferForPositions(int offset, int... positions)
{
for (int position : positions) {
target.init(buf, offset + position);
}
}
}