Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQL: Add range checks to interval multiplication operation #83478

Merged
merged 3 commits into from
Feb 7, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Add overflow check to interval multiplications
This adds checks on the multiplication operation on intervals (with
integer).
  • Loading branch information
bpintea committed Feb 3, 2022
commit edbedfac6ad7cc4c91df47980a285d9b31ab22b1
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics;
import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics.NumericArithmetic;
import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticOperation;
import org.elasticsearch.xpack.ql.type.DataTypeConverter;
import org.elasticsearch.xpack.sql.expression.literal.interval.Interval;
import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalArithmetics;
import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalDayTime;
Expand All @@ -24,6 +25,8 @@
import java.time.temporal.Temporal;
import java.util.function.BiFunction;

import static org.elasticsearch.xpack.ql.type.DataTypeConverter.safeToLong;

public enum SqlBinaryArithmeticOperation implements BinaryArithmeticOperation {

ADD((Object l, Object r) -> {
Expand Down Expand Up @@ -85,17 +88,17 @@ public enum SqlBinaryArithmeticOperation implements BinaryArithmeticOperation {
if (l instanceof Number && r instanceof Number) {
return Arithmetics.mul((Number) l, (Number) r);
}
if (l instanceof Number && r instanceof IntervalYearMonth) {
return ((IntervalYearMonth) r).mul(((Number) l).intValue());
if (l instanceof Number number && r instanceof IntervalYearMonth) {
return ((IntervalYearMonth) r).mul(safeToLong(number));
}
if (r instanceof Number && l instanceof IntervalYearMonth) {
return ((IntervalYearMonth) l).mul(((Number) r).intValue());
if (r instanceof Number number && l instanceof IntervalYearMonth) {
return ((IntervalYearMonth) l).mul(safeToLong(number));
}
if (l instanceof Number && r instanceof IntervalDayTime) {
return ((IntervalDayTime) r).mul(((Number) l).longValue());
if (l instanceof Number number && r instanceof IntervalDayTime) {
return ((IntervalDayTime) r).mul(safeToLong(number));
}
if (r instanceof Number && l instanceof IntervalDayTime) {
return ((IntervalDayTime) l).mul(((Number) r).longValue());
if (r instanceof Number number && l instanceof IntervalDayTime) {
return ((IntervalDayTime) l).mul(safeToLong(number));
}

throw new QlIllegalArgumentException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import static org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics.mod;
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
import static org.elasticsearch.xpack.ql.util.NumericUtils.UNSIGNED_LONG_MAX;
import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY;
import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_HOUR;
import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR;
Expand Down Expand Up @@ -243,6 +244,36 @@ public void testMulNullInterval() {
assertEquals(INTERVAL_MONTH, result.dataType());
}

public void testMulIntegerIntervalYearMonthOverflow() {
Literal l = interval(Period.ofYears(1).plusMonths(11), INTERVAL_YEAR);
ArithmeticException expect = expectThrows(ArithmeticException.class, () -> mul(l, L(Integer.MAX_VALUE)));
assertEquals("integer overflow", expect.getMessage());
}

public void testMulLongIntervalYearMonthOverflow() {
Literal l = interval(Period.ofYears(1), INTERVAL_YEAR);
QlIllegalArgumentException expect = expectThrows(QlIllegalArgumentException.class, () -> mul(l, L(Long.MAX_VALUE)));
assertEquals("[9223372036854775807] out of [integer] range", expect.getMessage());
}

public void testMulUnsignedLongIntervalYearMonthOverflow() {
Literal l = interval(Period.ofYears(1), INTERVAL_YEAR);
QlIllegalArgumentException expect = expectThrows(QlIllegalArgumentException.class, () -> mul(l, L(UNSIGNED_LONG_MAX)));
assertEquals("[18446744073709551615] out of [long] range", expect.getMessage());
}

public void testMulLongIntervalDayTimeOverflow() {
Literal l = interval(Duration.ofDays(1), INTERVAL_DAY);
ArithmeticException expect = expectThrows(ArithmeticException.class, () -> mul(l, L(Long.MAX_VALUE)));
assertEquals("Exceeds capacity of Duration: 796899343984252629724800000000000", expect.getMessage());
}

public void testMulUnsignedLongIntervalDayTimeOverflow() {
Literal l = interval(Duration.ofDays(1), INTERVAL_DAY);
QlIllegalArgumentException expect = expectThrows(QlIllegalArgumentException.class, () -> mul(l, L(UNSIGNED_LONG_MAX)));
assertEquals("[18446744073709551615] out of [long] range", expect.getMessage());
}

public void testAddNullInterval() {
Literal literal = interval(Period.ofMonths(1), INTERVAL_MONTH);
Add result = new Add(EMPTY, L(null), literal);
Expand Down