Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.facebook.presto.common.block.Block;
import com.facebook.presto.common.type.AbstractLongType;
import com.facebook.presto.common.type.StandardTypes;
import com.facebook.presto.spi.PrestoException;
import com.facebook.presto.spi.function.BlockIndex;
import com.facebook.presto.spi.function.BlockPosition;
import com.facebook.presto.spi.function.IsNull;
Expand All @@ -42,8 +43,11 @@
import static com.facebook.presto.common.function.OperatorType.NEGATION;
import static com.facebook.presto.common.function.OperatorType.NOT_EQUAL;
import static com.facebook.presto.common.function.OperatorType.SUBTRACT;
import static com.facebook.presto.spi.StandardErrorCode.DIVISION_BY_ZERO;
import static com.facebook.presto.spi.StandardErrorCode.NUMERIC_VALUE_OUT_OF_RANGE;
import static com.facebook.presto.type.IntervalDayTimeType.INTERVAL_DAY_TIME;
import static io.airlift.slice.Slices.utf8Slice;
import static java.lang.String.format;

public final class IntervalDayTimeOperators
{
Expand All @@ -55,56 +59,104 @@ private IntervalDayTimeOperators()
@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND)
public static long add(@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long left, @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long right)
{
return left + right;
try {
return Math.addExact(left, right);
}
catch (ArithmeticException e) {
throw new PrestoException(NUMERIC_VALUE_OUT_OF_RANGE, format("interval_day_to_second addition overflow: %s ms + %s ms", left, right), e);
}
}

@ScalarOperator(SUBTRACT)
@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND)
public static long subtract(@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long left, @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long right)
{
return left - right;
try {
return Math.subtractExact(left, right);
}
catch (ArithmeticException e) {
throw new PrestoException(NUMERIC_VALUE_OUT_OF_RANGE, format("interval_day_to_second subtraction overflow: %s ms - %s ms", left, right), e);
}
}

@ScalarOperator(MULTIPLY)
@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND)
public static long multiplyByBigint(@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long left, @SqlType(StandardTypes.BIGINT) long right)
{
return left * right;
try {
return Math.multiplyExact(left, right);
}
catch (ArithmeticException e) {
throw new PrestoException(NUMERIC_VALUE_OUT_OF_RANGE, format("interval_day_to_second multiply overflow: %s ms * %s", left, right), e);
}
}

@ScalarOperator(MULTIPLY)
@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND)
public static long multiplyByDouble(@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long left, @SqlType(StandardTypes.DOUBLE) double right)
{
return (long) (left * right);
try {
return Math.addExact(
(long) (left * (right - (long) right)),
Math.multiplyExact(left, (long) right));
}
catch (ArithmeticException e) {
throw new PrestoException(NUMERIC_VALUE_OUT_OF_RANGE, format("interval_day_to_second multiply overflow: %s ms * %s", left, right), e);
}
}

@ScalarOperator(MULTIPLY)
@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND)
public static long bigintMultiply(@SqlType(StandardTypes.BIGINT) long left, @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long right)
{
return left * right;
try {
return Math.multiplyExact(left, right);
}
catch (ArithmeticException e) {
throw new PrestoException(NUMERIC_VALUE_OUT_OF_RANGE, format("interval_day_to_second multiply overflow: %s * %s ms", left, right), e);
}
}

@ScalarOperator(MULTIPLY)
@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND)
public static long doubleMultiply(@SqlType(StandardTypes.DOUBLE) double left, @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long right)
{
return (long) (left * right);
try {
return Math.addExact(
Math.multiplyExact((long) left, right),
(long) ((left - (long) left) * right));
}
catch (ArithmeticException e) {
throw new PrestoException(NUMERIC_VALUE_OUT_OF_RANGE, format("interval_day_to_second multiply overflow: %s * %s ms", left, right), e);
}
}

@ScalarOperator(DIVIDE)
@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND)
public static long divideByDouble(@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long left, @SqlType(StandardTypes.DOUBLE) double right)
{
return (long) (left / right);
if (right == 0) {
throw new PrestoException(DIVISION_BY_ZERO, format("interval_day_to_second division by zero: %s ms / %s", left, right));
}

try {
return multiplyByDouble(left, 1.0 / right);
}
catch (PrestoException e) {
throw new PrestoException(NUMERIC_VALUE_OUT_OF_RANGE, format("interval_day_to_second division overflow: %s ms / %s", left, right));
}
}

@ScalarOperator(NEGATION)
@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND)
public static long negate(@SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long value)
{
return -value;
try {
return Math.negateExact(value);
}
catch (ArithmeticException e) {
throw new PrestoException(NUMERIC_VALUE_OUT_OF_RANGE, "interval_day_to_second negation overflow: " + value, e);
}
}

@ScalarOperator(EQUAL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static com.facebook.presto.common.type.BooleanType.BOOLEAN;
import static com.facebook.presto.common.type.VarcharType.VARCHAR;
import static com.facebook.presto.type.IntervalDayTimeType.INTERVAL_DAY_TIME;
import static java.lang.String.format;
import static java.util.concurrent.TimeUnit.DAYS;
import static org.testng.Assert.assertEquals;

Expand Down Expand Up @@ -131,6 +132,9 @@ public void testMultiply()
assertFunction("2 * INTERVAL '6' DAY", INTERVAL_DAY_TIME, new SqlIntervalDayTime(12 * 24 * 60 * 60 * 1000));
assertFunction("INTERVAL '1' DAY * 2.5", INTERVAL_DAY_TIME, new SqlIntervalDayTime((long) (2.5 * 24 * 60 * 60 * 1000)));
assertFunction("2.5 * INTERVAL '1' DAY", INTERVAL_DAY_TIME, new SqlIntervalDayTime((long) (2.5 * 24 * 60 * 60 * 1000)));
assertNumericOverflow(
format("%s * INTERVAL '%s' DAY", Integer.MAX_VALUE, 64),
format("interval_day_to_second multiply overflow: %s * %s ms", Integer.MAX_VALUE, (64 * 24 * 60 * 60 * 1000L)));
}

@Test
Expand All @@ -141,6 +145,9 @@ public void testDivide()

assertFunction("INTERVAL '3' DAY / 2", INTERVAL_DAY_TIME, new SqlIntervalDayTime((long) (1.5 * 24 * 60 * 60 * 1000)));
assertFunction("INTERVAL '4' DAY / 2.5", INTERVAL_DAY_TIME, new SqlIntervalDayTime((long) (1.6 * 24 * 60 * 60 * 1000)));
assertNumericOverflow(
format("INTERVAL '%s' DAY / %s", 64, 1 / (double) Integer.MAX_VALUE),
format("interval_day_to_second division overflow: %s ms / %s", (64 * 24 * 60 * 60 * 1000L), 1 / (double) Integer.MAX_VALUE));
}

@Test
Expand Down