Fix bug in Variance Buffer Aggregator resulting in intermittent NaN when druid.generic.useDefaultValueForNull=false (#11617)

* Fix bug in Variance Aggregator resulting in intermittent NaN when druid.generic.useDefaultValueForNull=false

* fix checkstyle

* address comments
This commit is contained in:
Maytas Monsereenusorn 2021-08-20 23:13:51 +07:00 committed by GitHub
parent ec334a641b
commit b36242b404
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 1 deletions

View File

@ -231,6 +231,9 @@ public abstract class VarianceBufferAggregator implements BufferAggregator
{
VarianceAggregatorCollector holder2 = (VarianceAggregatorCollector) selector.getObject();
Preconditions.checkState(holder2 != null);
if (holder2.count == 0) {
return;
}
long count = getCount(buf, position);
if (count == 0) {
buf.putLong(position, holder2.count);
@ -238,7 +241,6 @@ public abstract class VarianceBufferAggregator implements BufferAggregator
buf.putDouble(position + NVARIANCE_OFFSET, holder2.nvariance);
return;
}
double sum = getSum(buf, position);
double nvariance = buf.getDouble(position + NVARIANCE_OFFSET);

View File

@ -22,7 +22,10 @@ package org.apache.druid.query.aggregation.variance;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.jackson.DefaultObjectMapper;
import org.apache.druid.query.aggregation.TestFloatColumnSelector;
import org.apache.druid.query.aggregation.TestObjectColumnSelector;
import org.apache.druid.segment.ColumnSelectorFactory;
import org.apache.druid.segment.column.ColumnCapabilitiesImpl;
import org.apache.druid.segment.column.ValueType;
import org.apache.druid.testing.InitializedNullHandlingTest;
import org.easymock.EasyMock;
import org.junit.Assert;
@ -122,6 +125,34 @@ public class VarianceAggregatorTest extends InitializedNullHandlingTest
assertValues((VarianceAggregatorCollector) agg.get(buffer, 0), 4, 8.6d, 3.95d);
}
@Test
public void testObjectVarianceBufferAggregatorWithZeroCount()
{
VarianceAggregatorCollector holder1 = new VarianceAggregatorCollector().add(1.1f);
VarianceAggregatorCollector holder2 = new VarianceAggregatorCollector().add(2.7f);
VarianceAggregatorCollector holder3 = new VarianceAggregatorCollector();
VarianceAggregatorCollector[] values = {holder1, holder2, holder3};
TestObjectColumnSelector<VarianceAggregatorCollector> selector = new TestObjectColumnSelector(values);
colSelectorFactory = EasyMock.createMock(ColumnSelectorFactory.class);
EasyMock.expect(colSelectorFactory.makeColumnValueSelector("nilly")).andReturn(selector);
EasyMock.expect(colSelectorFactory.getColumnCapabilities("nilly")).andReturn(new ColumnCapabilitiesImpl().setType(ValueType.COMPLEX));
EasyMock.replay(colSelectorFactory);
VarianceBufferAggregator agg = (VarianceBufferAggregator) aggFactory.factorizeBuffered(
colSelectorFactory
);
ByteBuffer buffer = ByteBuffer.wrap(new byte[aggFactory.getMaxIntermediateSizeWithNulls()]);
agg.init(buffer, 0);
assertValues((VarianceAggregatorCollector) agg.get(buffer, 0), 0, 0d, 0d);
aggregate(selector, agg, buffer, 0);
assertValues((VarianceAggregatorCollector) agg.get(buffer, 0), 1, 1.1d, 0d);
aggregate(selector, agg, buffer, 0);
assertValues((VarianceAggregatorCollector) agg.get(buffer, 0), 2, 3.8d, 1.28d);
aggregate(selector, agg, buffer, 0);
assertValues((VarianceAggregatorCollector) agg.get(buffer, 0), 2, 3.8d, 1.28d);
}
@Test
public void testCombine()
{
@ -160,4 +191,15 @@ public class VarianceAggregatorTest extends InitializedNullHandlingTest
agg.aggregate(buff, position);
selector.increment();
}
private void aggregate(
TestObjectColumnSelector<VarianceAggregatorCollector> selector,
VarianceBufferAggregator agg,
ByteBuffer buff,
int position
)
{
agg.aggregate(buff, position);
selector.increment();
}
}