未验证 提交 810d5ffd 编写于 作者: J jaugsburger 提交者: GitHub

fix(griffin) - avg() ksum() nsum() sum() handling of infinity #313 (#338)

上级 982c77dd
......@@ -32,6 +32,7 @@ import io.questdb.cairo.sql.Record;
import io.questdb.griffin.engine.functions.DoubleFunction;
import io.questdb.griffin.engine.functions.GroupByFunction;
import io.questdb.griffin.engine.functions.UnaryFunction;
import io.questdb.std.Numbers;
import org.jetbrains.annotations.NotNull;
public class AvgDoubleGroupByFunction extends DoubleFunction implements GroupByFunction, UnaryFunction {
......@@ -46,7 +47,7 @@ public class AvgDoubleGroupByFunction extends DoubleFunction implements GroupByF
@Override
public void computeFirst(MapValue mapValue, Record record) {
final double d = arg.getDouble(record);
if (d == d) {
if (Numbers.isFinite(d)) {
mapValue.putDouble(valueIndex, d);
mapValue.putLong(valueIndex + 1, 1L);
} else {
......@@ -58,7 +59,7 @@ public class AvgDoubleGroupByFunction extends DoubleFunction implements GroupByF
@Override
public void computeNext(MapValue mapValue, Record record) {
final double d = arg.getDouble(record);
if (d == d) {
if (Numbers.isFinite(d)) {
mapValue.addDouble(valueIndex, d);
mapValue.addLong(valueIndex + 1, 1L);
}
......
......@@ -32,6 +32,7 @@ import io.questdb.cairo.sql.Record;
import io.questdb.griffin.engine.functions.DoubleFunction;
import io.questdb.griffin.engine.functions.GroupByFunction;
import io.questdb.griffin.engine.functions.UnaryFunction;
import io.questdb.std.Numbers;
import org.jetbrains.annotations.NotNull;
public class KSumDoubleGroupByFunction extends DoubleFunction implements GroupByFunction, UnaryFunction {
......@@ -46,7 +47,7 @@ public class KSumDoubleGroupByFunction extends DoubleFunction implements GroupBy
@Override
public void computeFirst(MapValue mapValue, Record record) {
final double value = arg.getDouble(record);
if (value == value) {
if (Numbers.isFinite(value)) {
mapValue.putDouble(valueIndex, value);
mapValue.putDouble(valueIndex + 1, value - value);
mapValue.putLong(valueIndex + 2, 1);
......@@ -60,7 +61,7 @@ public class KSumDoubleGroupByFunction extends DoubleFunction implements GroupBy
@Override
public void computeNext(MapValue mapValue, Record record) {
final double value = arg.getDouble(record);
if (value == value) {
if (Numbers.isFinite(value)) {
double sum = mapValue.getDouble(valueIndex);
double c = mapValue.getDouble(valueIndex + 1);
double y = value - c;
......
......@@ -32,6 +32,7 @@ import io.questdb.cairo.sql.Record;
import io.questdb.griffin.engine.functions.DoubleFunction;
import io.questdb.griffin.engine.functions.GroupByFunction;
import io.questdb.griffin.engine.functions.UnaryFunction;
import io.questdb.std.Numbers;
import org.jetbrains.annotations.NotNull;
public class NSumDoubleGroupByFunction extends DoubleFunction implements GroupByFunction, UnaryFunction {
......@@ -46,7 +47,7 @@ public class NSumDoubleGroupByFunction extends DoubleFunction implements GroupBy
@Override
public void computeFirst(MapValue mapValue, Record record) {
final double value = arg.getDouble(record);
if (value == value) {
if (Numbers.isFinite(value)) {
sum(mapValue, value, 0, 0);
mapValue.putLong(valueIndex + 2, 1);
} else {
......@@ -59,7 +60,7 @@ public class NSumDoubleGroupByFunction extends DoubleFunction implements GroupBy
@Override
public void computeNext(MapValue mapValue, Record record) {
final double value = arg.getDouble(record);
if (value == value) {
if (Numbers.isFinite(value)) {
sum(mapValue, value, mapValue.getDouble(valueIndex), mapValue.getDouble(valueIndex + 1));
mapValue.addLong(valueIndex + 2, 1);
}
......
......@@ -32,6 +32,7 @@ import io.questdb.cairo.sql.Record;
import io.questdb.griffin.engine.functions.DoubleFunction;
import io.questdb.griffin.engine.functions.GroupByFunction;
import io.questdb.griffin.engine.functions.UnaryFunction;
import io.questdb.std.Numbers;
import org.jetbrains.annotations.NotNull;
public class SumDoubleGroupByFunction extends DoubleFunction implements GroupByFunction, UnaryFunction {
......@@ -46,7 +47,7 @@ public class SumDoubleGroupByFunction extends DoubleFunction implements GroupByF
@Override
public void computeFirst(MapValue mapValue, Record record) {
final double value = arg.getDouble(record);
if (value == value) {
if (Numbers.isFinite(value)) {
mapValue.putDouble(valueIndex, value);
mapValue.putLong(valueIndex + 1, 1);
} else {
......@@ -58,7 +59,7 @@ public class SumDoubleGroupByFunction extends DoubleFunction implements GroupByF
@Override
public void computeNext(MapValue mapValue, Record record) {
final double value = arg.getDouble(record);
if (value == value) {
if (Numbers.isFinite(value)) {
mapValue.addDouble(valueIndex, value);
mapValue.addLong(valueIndex + 1, 1);
}
......
......@@ -1073,6 +1073,10 @@ public final class Numbers {
return Double.longBitsToDouble(Double.doubleToRawLongBits(roundUp00PosScale(absValue, scale)) | signMask);
}
public static boolean isFinite(double d) {
return ((Double.doubleToRawLongBits(d) & EXP_BIT_MASK) != EXP_BIT_MASK);
}
private static void appendLongHex4(CharSink sink, long value) {
appendLongHexPad(sink, hexDigits[(int) ((value) & 0xf)]);
}
......
......@@ -28,11 +28,19 @@ import io.questdb.cairo.sql.RecordCursor;
import io.questdb.cairo.sql.RecordCursorFactory;
import io.questdb.griffin.AbstractGriffinTest;
import io.questdb.griffin.CompiledQuery;
import io.questdb.griffin.engine.functions.rnd.SharedRandom;
import io.questdb.std.Rnd;
import io.questdb.test.tools.TestUtils;
import org.junit.Before;
import org.junit.Test;
public class AvgDoubleGroupByFunctionFactoryTest extends AbstractGriffinTest {
@Before
public void setUp3() {
SharedRandom.RANDOM.set(new Rnd());
}
@Test
public void testAll() throws Exception {
assertMemoryLeak(() -> {
......@@ -51,4 +59,37 @@ public class AvgDoubleGroupByFunctionFactoryTest extends AbstractGriffinTest {
});
}
@Test
public void testAvgWithInfinity() throws Exception {
assertMemoryLeak(() -> {
compiler.compile("create table test2 as(select case when rnd_double() > 0.6 then 1.0 else 0.0 end val from long_sequence(100));", sqlExecutionContext);
CompiledQuery cq = compiler.compile("select avg(1/val) from test2", sqlExecutionContext);
try (RecordCursorFactory factory = cq.getRecordCursorFactory()) {
sink.clear();
try (RecordCursor cursor = factory.getCursor(sqlExecutionContext)) {
printer.print(cursor, factory.getMetadata(), true);
}
}
TestUtils.assertEquals("avg\n1.0\n", sink);
});
}
@Test
public void testAllWithInfinity() throws Exception {
assertMemoryLeak(() -> {
compiler.compile("create table test2 as(select case when rnd_double() > 0.6 then 1.0 else 0.0 end val from long_sequence(100));", sqlExecutionContext);
CompiledQuery cq = compiler.compile("select sum(1/val) , avg(1/val), max(1/val), min(1/val), ksum(1/val), nsum(1/val) from test2", sqlExecutionContext);
try (RecordCursorFactory factory = cq.getRecordCursorFactory()) {
sink.clear();
try (RecordCursor cursor = factory.getCursor(sqlExecutionContext)) {
printer.print(cursor, factory.getMetadata(), true);
}
}
TestUtils.assertEquals("sum\tavg\tmax\tmin\tksum\tnsum\n" +
"44.0\t1.0\tInfinity\t1.0\t44.0\t44.0\n",
sink);
});
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册