This is an automated email from the ASF dual-hosted git repository.
cwylie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new e373f626925 fix expression post aggregator array handling when
grouping wrapper types leak (#15543)
e373f626925 is described below
commit e373f6269251655f5be93ce895aee8dee8cc67dd
Author: Clint Wylie <[email protected]>
AuthorDate: Fri Dec 15 21:43:27 2023 -0800
fix expression post aggregator array handling when grouping wrapper types
leak (#15543)
* fix expression post aggregator array handling when grouping wrapper types
leak
* more consistent expression function error messaging
---
.../druid/math/expr/BinaryEvalOpExprBase.java | 2 +-
.../java/org/apache/druid/math/expr/ExprEval.java | 20 +-
.../org/apache/druid/math/expr/FunctionalExpr.java | 16 +-
.../apache/druid/math/expr/UnaryOperatorExpr.java | 2 +-
.../org/apache/druid/segment/column/Types.java | 16 ++
.../java/org/apache/druid/math/expr/EvalTest.java | 14 +
.../org/apache/druid/math/expr/FunctionTest.java | 271 +++++++++----------
.../druid/sql/calcite/CalciteArraysQueryTest.java | 93 +++++++
.../sql/calcite/expression/ExpressionTestBase.java | 36 ---
.../sql/calcite/expression/ExpressionsTest.java | 290 +++++++++++----------
.../calcite/expression/GreatestExpressionTest.java | 3 +-
.../expression/IPv4AddressMatchExpressionTest.java | 80 +++---
.../expression/IPv4AddressParseExpressionTest.java | 38 +--
.../IPv4AddressStringifyExpressionTest.java | 38 +--
.../calcite/expression/LeastExpressionTest.java | 3 +-
.../TimeFormatOperatorConversionTest.java | 3 +-
16 files changed, 521 insertions(+), 404 deletions(-)
diff --git
a/processing/src/main/java/org/apache/druid/math/expr/BinaryEvalOpExprBase.java
b/processing/src/main/java/org/apache/druid/math/expr/BinaryEvalOpExprBase.java
index 8dd4b960251..2104dcc45db 100644
---
a/processing/src/main/java/org/apache/druid/math/expr/BinaryEvalOpExprBase.java
+++
b/processing/src/main/java/org/apache/druid/math/expr/BinaryEvalOpExprBase.java
@@ -207,7 +207,7 @@ abstract class BinaryBooleanOpExprBase extends
BinaryOpExprBase
break;
}
if (!ExpressionProcessing.useStrictBooleans() && !type.is(ExprType.STRING)
&& !type.isArray()) {
- return ExprEval.ofBoolean(result, type.getType());
+ return ExprEval.ofBoolean(result, type);
}
return ExprEval.ofLongBoolean(result);
}
diff --git a/processing/src/main/java/org/apache/druid/math/expr/ExprEval.java
b/processing/src/main/java/org/apache/druid/math/expr/ExprEval.java
index e62021623bd..9c0f5e2736a 100644
--- a/processing/src/main/java/org/apache/druid/math/expr/ExprEval.java
+++ b/processing/src/main/java/org/apache/druid/math/expr/ExprEval.java
@@ -30,6 +30,9 @@ import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.segment.column.NullableTypeStrategy;
import org.apache.druid.segment.column.TypeStrategies;
import org.apache.druid.segment.column.TypeStrategy;
+import org.apache.druid.segment.column.Types;
+import org.apache.druid.segment.data.ComparableList;
+import org.apache.druid.segment.data.ComparableStringArray;
import org.apache.druid.segment.nested.StructuredData;
import javax.annotation.Nullable;
@@ -357,9 +360,9 @@ public abstract class ExprEval<T>
* instead.
*/
@Deprecated
- public static ExprEval ofBoolean(boolean value, ExprType type)
+ public static ExprEval ofBoolean(boolean value, ExpressionType type)
{
- switch (type) {
+ switch (type.getType()) {
case DOUBLE:
return ExprEval.of(Evals.asDouble(value));
case LONG:
@@ -367,7 +370,7 @@ public abstract class ExprEval<T>
case STRING:
return ExprEval.of(String.valueOf(value));
default:
- throw new IllegalArgumentException("Invalid type, cannot coerce [" +
type + "] to boolean");
+ throw new Types.InvalidCastBooleanException(type);
}
}
@@ -502,6 +505,13 @@ public abstract class ExprEval<T>
final List<?> theList = val instanceof List ? ((List<?>) val) :
Arrays.asList((Object[]) val);
return bestEffortArray(theList);
}
+ // handle leaky group by array types
+ if (val instanceof ComparableStringArray) {
+ return new ArrayExprEval(ExpressionType.STRING_ARRAY,
((ComparableStringArray) val).getDelegate());
+ }
+ if (val instanceof ComparableList) {
+ return bestEffortArray(((ComparableList) val).getDelegate());
+ }
// in 'best effort' mode, we couldn't possibly use byte[] as a complex or
anything else useful without type
// knowledge, so lets turn it into a base64 encoded string so at least
something downstream can use it by decoding
@@ -1569,8 +1579,8 @@ public abstract class ExprEval<T>
}
}
- public static IAE invalidCast(ExpressionType fromType, ExpressionType toType)
+ public static Types.InvalidCastException invalidCast(ExpressionType
fromType, ExpressionType toType)
{
- return new IAE("Invalid type, cannot cast [" + fromType + "] to [" +
toType + "]");
+ return new Types.InvalidCastException(fromType, toType);
}
}
diff --git
a/processing/src/main/java/org/apache/druid/math/expr/FunctionalExpr.java
b/processing/src/main/java/org/apache/druid/math/expr/FunctionalExpr.java
index 3d5a7f511f9..a87d5d9cd68 100644
--- a/processing/src/main/java/org/apache/druid/math/expr/FunctionalExpr.java
+++ b/processing/src/main/java/org/apache/druid/math/expr/FunctionalExpr.java
@@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableList;
import org.apache.druid.error.DruidException;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.math.expr.vector.ExprVectorProcessor;
+import org.apache.druid.segment.column.Types;
import javax.annotation.Nullable;
import java.util.List;
@@ -190,11 +191,22 @@ class FunctionExpr implements Expr
try {
return function.apply(args, bindings);
}
- catch (DruidException | ExpressionValidationException e) {
+ catch (ExpressionValidationException e) {
+ // ExpressionValidationException already contain function name
+ throw DruidException.forPersona(DruidException.Persona.USER)
+ .ofCategory(DruidException.Category.INVALID_INPUT)
+ .build(e, e.getMessage());
+ }
+ catch (Types.InvalidCastException | Types.InvalidCastBooleanException e) {
+ throw DruidException.forPersona(DruidException.Persona.USER)
+ .ofCategory(DruidException.Category.INVALID_INPUT)
+ .build(e, "Function[%s] encountered exception: %s",
name, e.getMessage());
+ }
+ catch (DruidException e) {
throw e;
}
catch (Exception e) {
- throw DruidException.defensive().build(e, "Invocation of function '%s'
encountered exception.", name);
+ throw DruidException.defensive().build(e, "Function[%s] encountered
unknown exception.", name);
}
}
diff --git
a/processing/src/main/java/org/apache/druid/math/expr/UnaryOperatorExpr.java
b/processing/src/main/java/org/apache/druid/math/expr/UnaryOperatorExpr.java
index 684f3ac2520..f9f2c5bbcc2 100644
--- a/processing/src/main/java/org/apache/druid/math/expr/UnaryOperatorExpr.java
+++ b/processing/src/main/java/org/apache/druid/math/expr/UnaryOperatorExpr.java
@@ -184,7 +184,7 @@ class UnaryNotExpr extends UnaryExpr
if (!ExpressionProcessing.useStrictBooleans()) {
// conforming to other boolean-returning binary operators
ExpressionType retType = ret.type().is(ExprType.DOUBLE) ?
ExpressionType.DOUBLE : ExpressionType.LONG;
- return ExprEval.ofBoolean(!ret.asBoolean(), retType.getType());
+ return ExprEval.ofBoolean(!ret.asBoolean(), retType);
}
return ExprEval.ofLongBoolean(!ret.asBoolean());
}
diff --git
a/processing/src/main/java/org/apache/druid/segment/column/Types.java
b/processing/src/main/java/org/apache/druid/segment/column/Types.java
index 2a0256f7667..831f5c76ce9 100644
--- a/processing/src/main/java/org/apache/druid/segment/column/Types.java
+++ b/processing/src/main/java/org/apache/druid/segment/column/Types.java
@@ -141,4 +141,20 @@ public class Types
super("Cannot implicitly cast [%s] to [%s]", type, other);
}
}
+
+ public static class InvalidCastException extends IAE
+ {
+ public InvalidCastException(TypeSignature<?> type, TypeSignature<?> other)
+ {
+ super("Invalid type, cannot cast [" + type + "] to [" + other + "]");
+ }
+ }
+
+ public static class InvalidCastBooleanException extends IAE
+ {
+ public InvalidCastBooleanException(TypeSignature<?> type)
+ {
+ super("Invalid type, cannot coerce [" + type + "] to boolean");
+ }
+ }
}
diff --git a/processing/src/test/java/org/apache/druid/math/expr/EvalTest.java
b/processing/src/test/java/org/apache/druid/math/expr/EvalTest.java
index 2f68840955f..f969ede92b9 100644
--- a/processing/src/test/java/org/apache/druid/math/expr/EvalTest.java
+++ b/processing/src/test/java/org/apache/druid/math/expr/EvalTest.java
@@ -28,6 +28,8 @@ import org.apache.druid.java.util.common.IAE;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.segment.column.TypeStrategies;
import org.apache.druid.segment.column.TypeStrategiesTest;
+import org.apache.druid.segment.data.ComparableList;
+import org.apache.druid.segment.data.ComparableStringArray;
import org.apache.druid.segment.nested.StructuredData;
import org.apache.druid.testing.InitializedNullHandlingTest;
import org.junit.Assert;
@@ -1683,6 +1685,18 @@ public class EvalTest extends InitializedNullHandlingTest
ExpressionType.UNKNOWN_COMPLEX,
someOtherComplex
);
+
+ assertBestEffortOf(
+ ComparableStringArray.of("a", "b", "c"),
+ ExpressionType.STRING_ARRAY,
+ new Object[]{"a", "b", "c"}
+ );
+
+ assertBestEffortOf(
+ new ComparableList<>(Arrays.asList(1L, 2L)),
+ ExpressionType.LONG_ARRAY,
+ new Object[]{1L, 2L}
+ );
}
private void assertBestEffortOf(@Nullable Object val, ExpressionType
expectedType, @Nullable Object expectedValue)
diff --git
a/processing/src/test/java/org/apache/druid/math/expr/FunctionTest.java
b/processing/src/test/java/org/apache/druid/math/expr/FunctionTest.java
index e38b2ea5145..670dbe93e1f 100644
--- a/processing/src/test/java/org/apache/druid/math/expr/FunctionTest.java
+++ b/processing/src/test/java/org/apache/druid/math/expr/FunctionTest.java
@@ -148,12 +148,14 @@ public class FunctionTest extends
InitializedNullHandlingTest
throw new RuntimeException("nested-exception");
}
};
- DruidException e = Assert.assertThrows(DruidException.class,
+ DruidException e = Assert.assertThrows(
+ DruidException.class,
() -> {
expr.eval(bind);
- });
+ }
+ );
- assertEquals("Invocation of function 'abs' encountered exception.",
e.getMessage());
+ assertEquals("Function[abs] encountered unknown exception.",
e.getMessage());
assertNotNull(e.getCause());
assertEquals("nested-exception", e.getCause().getMessage());
}
@@ -581,19 +583,17 @@ public class FunctionTest extends
InitializedNullHandlingTest
if (NullHandling.sqlCompatible()) {
assertExpr(StringUtils.format("round(%s)", argAndType.lhs), null);
} else {
- try {
- assertExpr(StringUtils.format("round(%s)", argAndType.lhs), null);
- Assert.fail("Did not throw IllegalArgumentException");
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals(
- StringUtils.format(
- "Function[round] first argument should be a LONG or DOUBLE
but got %s instead",
- argAndType.rhs
- ),
- e.getMessage()
- );
- }
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> assertExpr(StringUtils.format("round(%s)", argAndType.lhs),
null)
+ );
+ Assert.assertEquals(
+ StringUtils.format(
+ "Function[round] first argument should be a LONG or DOUBLE but
got %s instead",
+ argAndType.rhs
+ ),
+ t.getMessage()
+ );
}
}
}
@@ -609,19 +609,17 @@ public class FunctionTest extends
InitializedNullHandlingTest
);
for (Pair<String, String> argAndType : invalidArguments) {
- try {
- assertExpr(StringUtils.format("round(d, %s)", argAndType.lhs), null);
- Assert.fail("Did not throw IllegalArgumentException");
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals(
- StringUtils.format(
- "Function[round] second argument should be a LONG but got %s
instead",
- argAndType.rhs
- ),
- e.getMessage()
- );
- }
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> assertExpr(StringUtils.format("round(d, %s)", argAndType.lhs),
null)
+ );
+ Assert.assertEquals(
+ StringUtils.format(
+ "Function[round] second argument should be a LONG but got %s
instead",
+ argAndType.rhs
+ ),
+ t.getMessage()
+ );
}
}
@@ -639,13 +637,11 @@ public class FunctionTest extends
InitializedNullHandlingTest
assertExpr("greatest(1, 'A')", "A");
// Invalid types
- try {
- assertExpr("greatest(1, ['A'])", null);
- Assert.fail("Did not throw IllegalArgumentException");
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals("Function[greatest] does not accept ARRAY<STRING>
types", e.getMessage());
- }
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> assertExpr("greatest(1, ['A'])", null)
+ );
+ Assert.assertEquals("Function[greatest] does not accept ARRAY<STRING>
types", t.getMessage());
// Null handling
assertExpr("greatest()", null);
@@ -667,13 +663,11 @@ public class FunctionTest extends
InitializedNullHandlingTest
assertExpr("least(1, 'A')", "1");
// Invalid types
- try {
- assertExpr("least(1, [2, 3])", null);
- Assert.fail("Did not throw IllegalArgumentException");
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals("Function[least] does not accept ARRAY<LONG> types",
e.getMessage());
- }
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> assertExpr("least(1, [2, 3])", null)
+ );
+ Assert.assertEquals("Function[least] does not accept ARRAY<LONG> types",
t.getMessage());
// Null handling
assertExpr("least()", null);
@@ -754,118 +748,91 @@ public class FunctionTest extends
InitializedNullHandlingTest
@Test
public void testSizeForatInvalidArgumentType()
{
- try {
- //x = "foo"
- Parser.parse("human_readable_binary_byte_format(x)",
ExprMacroTable.nil())
- .eval(bestEffortBindings);
-
- // for sqlCompatible, function above returns null and goes here
- // but for non-sqlCompatible, it must not go to here
- Assert.assertTrue(NullHandling.sqlCompatible() ? true : false);
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals(
- "Function[human_readable_binary_byte_format] needs a number as its
first argument but got STRING instead",
- e.getMessage()
- );
- }
-
- try {
+ if (NullHandling.replaceWithDefault()) {
//x = "foo"
- Parser.parse("human_readable_binary_byte_format(1024, x)",
ExprMacroTable.nil())
- .eval(bestEffortBindings);
-
- //must not go to here
- Assert.assertTrue(false);
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals(
- "Function[human_readable_binary_byte_format] needs a LONG as its
second argument but got STRING instead",
- e.getMessage()
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> Parser.parse("human_readable_binary_byte_format(x)",
ExprMacroTable.nil())
+ .eval(bestEffortBindings)
);
- }
-
- try {
- //of = 0F
- Parser.parse("human_readable_binary_byte_format(1024, of)",
ExprMacroTable.nil())
- .eval(bestEffortBindings);
-
- //must not go to here
- Assert.assertTrue(false);
- }
- catch (ExpressionValidationException e) {
Assert.assertEquals(
- "Function[human_readable_binary_byte_format] needs a LONG as its
second argument but got DOUBLE instead",
- e.getMessage()
+ "Function[human_readable_binary_byte_format] needs a number as its
first argument but got STRING instead",
+ t.getMessage()
);
}
- try {
- //of = 0F
- Parser.parse("human_readable_binary_byte_format(1024, nonexist)",
ExprMacroTable.nil())
- .eval(bestEffortBindings);
+ // x = "foo"
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> Parser.parse("human_readable_binary_byte_format(1024, x)",
ExprMacroTable.nil()).eval(bestEffortBindings)
+ );
+ Assert.assertEquals(
+ "Function[human_readable_binary_byte_format] needs a LONG as its
second argument but got STRING instead",
+ t.getMessage()
+ );
+ //of = 0F
+ t = Assert.assertThrows(
+ DruidException.class,
+ () -> Parser.parse("human_readable_binary_byte_format(1024, of)",
ExprMacroTable.nil()).eval(bestEffortBindings)
+ );
+ Assert.assertEquals(
+ "Function[human_readable_binary_byte_format] needs a LONG as its
second argument but got DOUBLE instead",
+ t.getMessage()
+ );
- //must not go to here
- Assert.assertTrue(false);
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals(
- "Function[human_readable_binary_byte_format] needs a LONG as its
second argument but got STRING instead",
- e.getMessage()
- );
- }
+ //of = 0F
+ t = Assert.assertThrows(
+ DruidException.class,
+ () -> Parser.parse("human_readable_binary_byte_format(1024,
nonexist)", ExprMacroTable.nil())
+ .eval(bestEffortBindings)
+ );
+ Assert.assertEquals(
+ "Function[human_readable_binary_byte_format] needs a LONG as its
second argument but got STRING instead",
+ t.getMessage()
+ );
}
@Test
public void testSizeFormatInvalidPrecision()
{
- try {
- Parser.parse("human_readable_binary_byte_format(1024, maxLong)",
ExprMacroTable.nil())
- .eval(bestEffortBindings);
- Assert.assertTrue(false);
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals(
- "Function[human_readable_binary_byte_format] given
precision[9223372036854775807] must be in the range of [0,3]",
- e.getMessage()
- );
- }
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> Parser.parse("human_readable_binary_byte_format(1024, maxLong)",
ExprMacroTable.nil())
+ .eval(bestEffortBindings)
+ );
- try {
- Parser.parse("human_readable_binary_byte_format(1024, minLong)",
ExprMacroTable.nil())
- .eval(bestEffortBindings);
- Assert.assertTrue(false);
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals(
- "Function[human_readable_binary_byte_format] given
precision[-9223372036854775808] must be in the range of [0,3]",
- e.getMessage()
- );
- }
+ Assert.assertEquals(
+ "Function[human_readable_binary_byte_format] given
precision[9223372036854775807] must be in the range of [0,3]",
+ t.getMessage()
+ );
- try {
- Parser.parse("human_readable_binary_byte_format(1024, -1)",
ExprMacroTable.nil())
- .eval(bestEffortBindings);
- Assert.assertTrue(false);
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals(
- "Function[human_readable_binary_byte_format] given precision[-1]
must be in the range of [0,3]",
- e.getMessage()
- );
- }
+ t = Assert.assertThrows(
+ DruidException.class,
+ () -> Parser.parse("human_readable_binary_byte_format(1024, minLong)",
ExprMacroTable.nil())
+ .eval(bestEffortBindings)
+ );
+ Assert.assertEquals(
+ "Function[human_readable_binary_byte_format] given
precision[-9223372036854775808] must be in the range of [0,3]",
+ t.getMessage()
+ );
- try {
- Parser.parse("human_readable_binary_byte_format(1024, 4)",
ExprMacroTable.nil())
- .eval(bestEffortBindings);
- Assert.assertTrue(false);
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals(
- "Function[human_readable_binary_byte_format] given precision[4] must
be in the range of [0,3]",
- e.getMessage()
- );
- }
+ t = Assert.assertThrows(
+ DruidException.class,
+ () -> Parser.parse("human_readable_binary_byte_format(1024, -1)",
ExprMacroTable.nil()).eval(bestEffortBindings)
+ );
+ Assert.assertEquals(
+ "Function[human_readable_binary_byte_format] given precision[-1] must
be in the range of [0,3]",
+ t.getMessage()
+ );
+
+ t = Assert.assertThrows(
+ DruidException.class,
+ () -> Parser.parse("human_readable_binary_byte_format(1024, 4)",
ExprMacroTable.nil()).eval(bestEffortBindings)
+ );
+ Assert.assertEquals(
+ "Function[human_readable_binary_byte_format] given precision[4] must
be in the range of [0,3]",
+ t.getMessage()
+ );
}
@Test
@@ -923,16 +890,14 @@ public class FunctionTest extends
InitializedNullHandlingTest
assertExpr("bitwiseComplement(null)", null);
// data truncation
- try {
- assertExpr("bitwiseComplement(461168601842738800000000000000.000000)",
null);
- Assert.fail("Did not throw IllegalArgumentException");
- }
- catch (ExpressionValidationException e) {
- Assert.assertEquals(
- "Function[bitwiseComplement] Possible data truncation, param
[461168601842738800000000000000.000000] is out of LONG value range",
- e.getMessage()
- );
- }
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () ->
assertExpr("bitwiseComplement(461168601842738800000000000000.000000)", null)
+ );
+ Assert.assertEquals(
+ "Function[bitwiseComplement] Possible data truncation, param
[461168601842738800000000000000.000000] is out of LONG value range",
+ t.getMessage()
+ );
// doubles are cast
assertExpr("bitwiseOr(2.345, 1)", 3L);
@@ -975,7 +940,10 @@ public class FunctionTest extends
InitializedNullHandlingTest
public void testDecodeBase64UTF()
{
assertExpr("decode_base64_utf8('aGVsbG8=')", "hello");
-
assertExpr("decode_base64_utf8('V2hlbiBhbiBvbmlvbiBpcyBjdXQsIGNlcnRhaW4gKGxhY2hyeW1hdG9yKSBjb21wb3VuZHMgYXJlIHJlbGVhc2VkIGNhdXNpbmcgdGhlIG5lcnZlcyBhcm91bmQgdGhlIGV5ZXMgKGxhY3JpbWFsIGdsYW5kcykgdG8gYmVjb21lIGlycml0YXRlZC4=')",
"When an onion is cut, certain (lachrymator) compounds are released causing
the nerves around the eyes (lacrimal glands) to become irritated.");
+ assertExpr(
+
"decode_base64_utf8('V2hlbiBhbiBvbmlvbiBpcyBjdXQsIGNlcnRhaW4gKGxhY2hyeW1hdG9yKSBjb21wb3VuZHMgYXJlIHJlbGVhc2VkIGNhdXNpbmcgdGhlIG5lcnZlcyBhcm91bmQgdGhlIGV5ZXMgKGxhY3JpbWFsIGdsYW5kcykgdG8gYmVjb21lIGlycml0YXRlZC4=')",
+ "When an onion is cut, certain (lachrymator) compounds are released
causing the nerves around the eyes (lacrimal glands) to become irritated."
+ );
assertExpr("decode_base64_utf8('eyJ0ZXN0IjogMX0=')", "{\"test\": 1}");
assertExpr("decode_base64_utf8('')", NullHandling.sqlCompatible() ? "" :
null);
}
@@ -1039,6 +1007,7 @@ public class FunctionTest extends
InitializedNullHandlingTest
Assert.assertEquals(happiness,
Parser.parse(StringUtils.format("%s(1,2)", tea), exprMacroTable));
}
}
+
@Test
public void testComplexDecodeNull()
{
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteArraysQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteArraysQueryTest.java
index 372374f1e25..e1d2d128b8b 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteArraysQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteArraysQueryTest.java
@@ -50,6 +50,7 @@ import
org.apache.druid.query.aggregation.DoubleSumAggregatorFactory;
import org.apache.druid.query.aggregation.ExpressionLambdaAggregatorFactory;
import org.apache.druid.query.aggregation.FilteredAggregatorFactory;
import org.apache.druid.query.aggregation.LongSumAggregatorFactory;
+import org.apache.druid.query.aggregation.post.ExpressionPostAggregator;
import org.apache.druid.query.dimension.DefaultDimensionSpec;
import org.apache.druid.query.expression.TestExprMacroTable;
import org.apache.druid.query.extraction.SubstringDimExtractionFn;
@@ -80,6 +81,7 @@ import org.apache.druid.segment.column.RowSignature;
import org.apache.druid.segment.incremental.IncrementalIndexSchema;
import org.apache.druid.segment.join.JoinType;
import org.apache.druid.segment.join.JoinableFactoryWrapper;
+import org.apache.druid.segment.virtual.ExpressionVirtualColumn;
import
org.apache.druid.segment.writeout.OffHeapMemorySegmentWriteOutMediumFactory;
import org.apache.druid.server.QueryStackTests;
import org.apache.druid.server.SpecificSegmentsQuerySegmentWalker;
@@ -7193,4 +7195,95 @@ public class CalciteArraysQueryTest extends
BaseCalciteQueryTest
)
);
}
+
+ @Test
+ public void testArrayToMvPostaggInline()
+ {
+ cannotVectorize();
+ testQuery(
+ "WITH \"ext\" AS (\n"
+ + " SELECT\n"
+ + " CAST(\"c0\" AS TIMESTAMP) AS \"__time\",\n"
+ + " STRING_TO_ARRAY(\"c1\", '<#>') AS \"strings\",\n"
+ + " CAST(STRING_TO_ARRAY(\"c2\", '<#>') AS BIGINT ARRAY) AS
\"longs\"\n"
+ + " FROM (\n"
+ + " VALUES\n"
+ + " (0, 'A<#>B', '1<#>2'),\n"
+ + " (0, 'C<#>D', '3<#>4')\n"
+ + " ) AS \"t\" (\"c0\", \"c1\", \"c2\")\n"
+ + ")\n"
+ + "SELECT\n"
+ + " ARRAY_TO_MV(\"strings\") AS \"strings\",\n"
+ + " ARRAY_TO_MV(\"longs\") AS \"longs\",\n"
+ + " COUNT(*) AS \"count\"\n"
+ + "FROM \"ext\"\n"
+ + "GROUP BY \"strings\", \"longs\"",
+ ImmutableList.of(
+ GroupByQuery.builder()
+ .setDataSource(
+ InlineDataSource.fromIterable(
+ Arrays.asList(
+ new Object[]{0L, "A<#>B", "1<#>2"},
+ new Object[]{0L, "C<#>D", "3<#>4"}
+ ),
+ RowSignature.builder()
+ .add("c0", ColumnType.LONG)
+ .add("c1", ColumnType.STRING)
+ .add("c2", ColumnType.STRING)
+ .build()
+ )
+ )
+ .setQuerySegmentSpec(new
MultipleIntervalSegmentSpec(ImmutableList.of(Intervals.ETERNITY)))
+ .setDimensions(
+ new DefaultDimensionSpec("v0", "d0",
ColumnType.STRING_ARRAY),
+ new DefaultDimensionSpec("v1", "d1",
ColumnType.LONG_ARRAY)
+ )
+ .setVirtualColumns(
+ new ExpressionVirtualColumn(
+ "v0",
+ "string_to_array(\"c1\",'<#>')",
+ ColumnType.STRING_ARRAY,
+ TestExprMacroTable.INSTANCE
+ ),
+ new ExpressionVirtualColumn(
+ "v1",
+ "CAST(string_to_array(\"c2\",'<#>'),
'ARRAY<LONG>')",
+ ColumnType.LONG_ARRAY,
+ TestExprMacroTable.INSTANCE
+ )
+ )
+ .setAggregatorSpecs(
+ new CountAggregatorFactory("a0")
+ )
+ .setPostAggregatorSpecs(
+ new ExpressionPostAggregator(
+ "p0",
+ "array_to_mv(\"d0\")",
+ null,
+ ColumnType.STRING,
+ TestExprMacroTable.INSTANCE
+ ),
+ new ExpressionPostAggregator(
+ "p1",
+ "array_to_mv(\"d1\")",
+ null,
+ ColumnType.STRING,
+ TestExprMacroTable.INSTANCE
+ )
+ )
+ .setGranularity(Granularities.ALL)
+ .setContext(QUERY_CONTEXT_DEFAULT)
+ .build()
+ ),
+ ImmutableList.of(
+ new Object[]{"[\"A\",\"B\"]", "[\"1\",\"2\"]", 1L},
+ new Object[]{"[\"C\",\"D\"]", "[\"3\",\"4\"]", 1L}
+ ),
+ RowSignature.builder()
+ .add("strings", ColumnType.STRING)
+ .add("longs", ColumnType.STRING)
+ .add("count", ColumnType.LONG)
+ .build()
+ );
+ }
}
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionTestBase.java
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionTestBase.java
deleted file mode 100644
index 0a03bcc8aa7..00000000000
---
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionTestBase.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.sql.calcite.expression;
-
-import org.apache.druid.sql.calcite.util.CalciteTestBase;
-import org.junit.Rule;
-import org.junit.rules.ExpectedException;
-
-public abstract class ExpressionTestBase extends CalciteTestBase
-{
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- void expectException(Class<? extends Throwable> type, String message)
- {
- expectedException.expect(type);
- expectedException.expectMessage(message);
- }
-}
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionsTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionsTest.java
index 6610951f07d..2ca9323b902 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionsTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionsTest.java
@@ -30,8 +30,8 @@ import org.apache.calcite.sql.fun.SqlTrimFunction;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.druid.common.config.NullHandling;
+import org.apache.druid.error.DruidException;
import org.apache.druid.java.util.common.DateTimes;
-import org.apache.druid.math.expr.ExpressionValidationException;
import org.apache.druid.query.expression.TestExprMacroTable;
import org.apache.druid.query.extraction.RegexDimExtractionFn;
import org.apache.druid.query.extraction.SubstringDimExtractionFn;
@@ -65,7 +65,9 @@ import
org.apache.druid.sql.calcite.expression.builtin.TimeFormatOperatorConvers
import
org.apache.druid.sql.calcite.expression.builtin.TimeParseOperatorConversion;
import
org.apache.druid.sql.calcite.expression.builtin.TimeShiftOperatorConversion;
import
org.apache.druid.sql.calcite.expression.builtin.TruncateOperatorConversion;
+import org.apache.druid.sql.calcite.util.CalciteTestBase;
import org.joda.time.Period;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -73,7 +75,7 @@ import java.math.BigDecimal;
import java.util.Collections;
import java.util.Map;
-public class ExpressionsTest extends ExpressionTestBase
+public class ExpressionsTest extends CalciteTestBase
{
private static final RowSignature ROW_SIGNATURE = RowSignature
.builder()
@@ -100,28 +102,31 @@ public class ExpressionsTest extends ExpressionTestBase
.build();
private static final Map<String, Object> BINDINGS = ImmutableMap.<String,
Object>builder()
- .put("t", DateTimes.of("2000-02-03T04:05:06").getMillis())
- .put("a", 10)
- .put("b", 25)
- .put("p", 3)
- .put("x", 2.25)
- .put("y", 3.0)
- .put("z", -2.25)
- .put("o", 0)
- .put("nan", Double.NaN)
- .put("inf", Double.POSITIVE_INFINITY)
- .put("-inf", Double.NEGATIVE_INFINITY)
- .put("fnan", Float.NaN)
- .put("finf", Float.POSITIVE_INFINITY)
- .put("-finf", Float.NEGATIVE_INFINITY)
- .put("s", "foo")
- .put("hexstr", "EF")
- .put("intstr", "-100")
- .put("spacey", " hey there ")
- .put("newliney", "beep\nboop")
- .put("tstr", "2000-02-03 04:05:06")
- .put("dstr", "2000-02-03")
- .build();
+ .put(
+ "t",
+
DateTimes.of("2000-02-03T04:05:06").getMillis()
+ )
+ .put("a", 10)
+ .put("b", 25)
+ .put("p", 3)
+ .put("x",
2.25)
+ .put("y",
3.0)
+ .put("z",
-2.25)
+ .put("o", 0)
+ .put("nan",
Double.NaN)
+ .put("inf",
Double.POSITIVE_INFINITY)
+ .put("-inf",
Double.NEGATIVE_INFINITY)
+ .put("fnan",
Float.NaN)
+ .put("finf",
Float.POSITIVE_INFINITY)
+
.put("-finf", Float.NEGATIVE_INFINITY)
+ .put("s",
"foo")
+
.put("hexstr", "EF")
+
.put("intstr", "-100")
+
.put("spacey", " hey there ")
+
.put("newliney", "beep\nboop")
+ .put("tstr",
"2000-02-03 04:05:06")
+ .put("dstr",
"2000-02-03")
+ .build();
private ExpressionTestHelper testHelper;
@@ -1255,23 +1260,26 @@ public class ExpressionsTest extends ExpressionTestBase
final SqlFunction roundFunction = new
RoundOperatorConversion().calciteOperator();
if (!NullHandling.sqlCompatible()) {
- expectException(
- ExpressionValidationException.class,
- "Function[round] first argument should be a LONG or DOUBLE but got
STRING instead"
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> testHelper.testExpression(
+ roundFunction,
+ testHelper.makeInputRef("s"),
+ DruidExpression.ofExpression(
+ ColumnType.STRING,
+ DruidExpression.functionCall("round"),
+ ImmutableList.of(
+ DruidExpression.ofColumn(ColumnType.STRING, "s")
+ )
+ ),
+ NullHandling.sqlCompatible() ? null : "IAE Exception"
+ )
+ );
+ Assert.assertEquals(
+ "Function[round] first argument should be a LONG or DOUBLE but got
STRING instead",
+ t.getMessage()
);
}
- testHelper.testExpression(
- roundFunction,
- testHelper.makeInputRef("s"),
- DruidExpression.ofExpression(
- ColumnType.STRING,
- DruidExpression.functionCall("round"),
- ImmutableList.of(
- DruidExpression.ofColumn(ColumnType.STRING, "s")
- )
- ),
- NullHandling.sqlCompatible() ? null : "IAE Exception"
- );
}
@Test
@@ -1279,26 +1287,26 @@ public class ExpressionsTest extends ExpressionTestBase
{
final SqlFunction roundFunction = new
RoundOperatorConversion().calciteOperator();
- expectException(
- ExpressionValidationException.class,
- "Function[round] second argument should be a LONG but got STRING
instead"
- );
- testHelper.testExpressionString(
- roundFunction,
- ImmutableList.of(
- testHelper.makeInputRef("x"),
- testHelper.makeLiteral("foo")
- ),
- DruidExpression.ofExpression(
- ColumnType.FLOAT,
- DruidExpression.functionCall("round"),
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> testHelper.testExpressionString(
+ roundFunction,
ImmutableList.of(
- DruidExpression.ofColumn(ColumnType.FLOAT, "x"),
- DruidExpression.ofStringLiteral("foo")
- )
- ),
- "IAE Exception"
+ testHelper.makeInputRef("x"),
+ testHelper.makeLiteral("foo")
+ ),
+ DruidExpression.ofExpression(
+ ColumnType.FLOAT,
+ DruidExpression.functionCall("round"),
+ ImmutableList.of(
+ DruidExpression.ofColumn(ColumnType.FLOAT, "x"),
+ DruidExpression.ofStringLiteral("foo")
+ )
+ ),
+ "IAE Exception"
+ )
);
+ Assert.assertEquals("Function[round] second argument should be a LONG but
got STRING instead", t.getMessage());
}
@Test
@@ -2237,23 +2245,22 @@ public class ExpressionsTest extends ExpressionTestBase
@Test
public void testAbnormalReverseWithWrongType()
{
- expectException(
- ExpressionValidationException.class,
- "Function[reverse] needs a STRING argument but got LONG instead"
- );
-
- testHelper.testExpression(
- new ReverseOperatorConversion().calciteOperator(),
- testHelper.makeInputRef("a"),
- DruidExpression.ofExpression(
- ColumnType.STRING,
- DruidExpression.functionCall("reverse"),
- ImmutableList.of(
- DruidExpression.ofColumn(ColumnType.LONG, "a")
- )
- ),
- null
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> testHelper.testExpression(
+ new ReverseOperatorConversion().calciteOperator(),
+ testHelper.makeInputRef("a"),
+ DruidExpression.ofExpression(
+ ColumnType.STRING,
+ DruidExpression.functionCall("reverse"),
+ ImmutableList.of(
+ DruidExpression.ofColumn(ColumnType.LONG, "a")
+ )
+ ),
+ null
+ )
);
+ Assert.assertEquals("Function[reverse] needs a STRING argument but got
LONG instead", t.getMessage());
}
@Test
@@ -2313,38 +2320,39 @@ public class ExpressionsTest extends ExpressionTestBase
@Test
public void testAbnormalRightWithNegativeNumber()
{
- expectException(
- ExpressionValidationException.class,
- "Function[right] needs a positive integer as the second argument"
- );
-
- testHelper.testExpressionString(
- new RightOperatorConversion().calciteOperator(),
- ImmutableList.of(
- testHelper.makeInputRef("s"),
- testHelper.makeLiteral(-1)
- ),
- makeExpression("right(\"s\",-1)"),
- null
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> testHelper.testExpressionString(
+ new RightOperatorConversion().calciteOperator(),
+ ImmutableList.of(
+ testHelper.makeInputRef("s"),
+ testHelper.makeLiteral(-1)
+ ),
+ makeExpression("right(\"s\",-1)"),
+ null
+ )
);
+ Assert.assertEquals("Function[right] needs a positive integer as the
second argument", t.getMessage());
}
@Test
public void testAbnormalRightWithWrongType()
{
- expectException(
- ExpressionValidationException.class,
- "Function[right] needs a STRING as first argument and a LONG as second
argument"
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> testHelper.testExpressionString(
+ new RightOperatorConversion().calciteOperator(),
+ ImmutableList.of(
+ testHelper.makeInputRef("s"),
+ testHelper.makeInputRef("s")
+ ),
+ makeExpression("right(\"s\",\"s\")"),
+ null
+ )
);
-
- testHelper.testExpressionString(
- new RightOperatorConversion().calciteOperator(),
- ImmutableList.of(
- testHelper.makeInputRef("s"),
- testHelper.makeInputRef("s")
- ),
- makeExpression("right(\"s\",\"s\")"),
- null
+ Assert.assertEquals(
+ "Function[right] needs a STRING as first argument and a LONG as second
argument",
+ t.getMessage()
);
}
@@ -2405,38 +2413,39 @@ public class ExpressionsTest extends ExpressionTestBase
@Test
public void testAbnormalLeftWithNegativeNumber()
{
- expectException(
- ExpressionValidationException.class,
- "Function[left] needs a postive integer as second argument"
- );
-
- testHelper.testExpressionString(
- new LeftOperatorConversion().calciteOperator(),
- ImmutableList.of(
- testHelper.makeInputRef("s"),
- testHelper.makeLiteral(-1)
- ),
- makeExpression("left(\"s\",-1)"),
- null
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> testHelper.testExpressionString(
+ new LeftOperatorConversion().calciteOperator(),
+ ImmutableList.of(
+ testHelper.makeInputRef("s"),
+ testHelper.makeLiteral(-1)
+ ),
+ makeExpression("left(\"s\",-1)"),
+ null
+ )
);
+ Assert.assertEquals("Function[left] needs a postive integer as second
argument", t.getMessage());
}
@Test
public void testAbnormalLeftWithWrongType()
{
- expectException(
- ExpressionValidationException.class,
- "Function[left] needs a STRING as first argument and a LONG as second
argument"
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> testHelper.testExpressionString(
+ new LeftOperatorConversion().calciteOperator(),
+ ImmutableList.of(
+ testHelper.makeInputRef("s"),
+ testHelper.makeInputRef("s")
+ ),
+ makeExpression("left(\"s\",\"s\")"),
+ null
+ )
);
-
- testHelper.testExpressionString(
- new LeftOperatorConversion().calciteOperator(),
- ImmutableList.of(
- testHelper.makeInputRef("s"),
- testHelper.makeInputRef("s")
- ),
- makeExpression("left(\"s\",\"s\")"),
- null
+ Assert.assertEquals(
+ "Function[left] needs a STRING as first argument and a LONG as second
argument",
+ t.getMessage()
);
}
@@ -2477,19 +2486,21 @@ public class ExpressionsTest extends ExpressionTestBase
@Test
public void testAbnormalRepeatWithWrongType()
{
- expectException(
- ExpressionValidationException.class,
- "Function[repeat] needs a STRING as first argument and a LONG as
second argument"
+ Throwable t = Assert.assertThrows(
+ DruidException.class,
+ () -> testHelper.testExpressionString(
+ new RepeatOperatorConversion().calciteOperator(),
+ ImmutableList.of(
+ testHelper.makeInputRef("s"),
+ testHelper.makeInputRef("s")
+ ),
+ makeExpression("repeat(\"s\",\"s\")"),
+ null
+ )
);
-
- testHelper.testExpressionString(
- new RepeatOperatorConversion().calciteOperator(),
- ImmutableList.of(
- testHelper.makeInputRef("s"),
- testHelper.makeInputRef("s")
- ),
- makeExpression("repeat(\"s\",\"s\")"),
- null
+ Assert.assertEquals(
+ "Function[repeat] needs a STRING as first argument and a LONG as
second argument",
+ t.getMessage()
);
}
@@ -2528,7 +2539,8 @@ public class ExpressionsTest extends ExpressionTestBase
public void testOperatorConversionsDruidUnaryDoubleFn()
{
testHelper.testExpressionString(
-
OperatorConversions.druidUnaryDoubleFn("BITWISE_CONVERT_LONG_BITS_TO_DOUBLE",
"bitwiseConvertLongBitsToDouble").calciteOperator(),
+
OperatorConversions.druidUnaryDoubleFn("BITWISE_CONVERT_LONG_BITS_TO_DOUBLE",
"bitwiseConvertLongBitsToDouble")
+ .calciteOperator(),
ImmutableList.of(
testHelper.makeInputRef("a")
),
@@ -2537,7 +2549,8 @@ public class ExpressionsTest extends ExpressionTestBase
);
testHelper.testExpressionString(
-
OperatorConversions.druidUnaryDoubleFn("BITWISE_CONVERT_LONG_BITS_TO_DOUBLE",
"bitwiseConvertLongBitsToDouble").calciteOperator(),
+
OperatorConversions.druidUnaryDoubleFn("BITWISE_CONVERT_LONG_BITS_TO_DOUBLE",
"bitwiseConvertLongBitsToDouble")
+ .calciteOperator(),
ImmutableList.of(
testHelper.makeInputRef("x")
),
@@ -2546,7 +2559,8 @@ public class ExpressionsTest extends ExpressionTestBase
);
testHelper.testExpressionString(
-
OperatorConversions.druidUnaryDoubleFn("BITWISE_CONVERT_LONG_BITS_TO_DOUBLE",
"bitwiseConvertLongBitsToDouble").calciteOperator(),
+
OperatorConversions.druidUnaryDoubleFn("BITWISE_CONVERT_LONG_BITS_TO_DOUBLE",
"bitwiseConvertLongBitsToDouble")
+ .calciteOperator(),
ImmutableList.of(
testHelper.makeInputRef("s")
),
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/GreatestExpressionTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/GreatestExpressionTest.java
index 8418edf994e..816befbdc0d 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/GreatestExpressionTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/GreatestExpressionTest.java
@@ -28,6 +28,7 @@ import org.apache.druid.java.util.common.DateTimes;
import org.apache.druid.segment.column.ColumnType;
import org.apache.druid.segment.column.RowSignature;
import
org.apache.druid.sql.calcite.expression.builtin.GreatestOperatorConversion;
+import org.apache.druid.sql.calcite.util.CalciteTestBase;
import org.junit.Before;
import org.junit.Test;
@@ -37,7 +38,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
-public class GreatestExpressionTest extends ExpressionTestBase
+public class GreatestExpressionTest extends CalciteTestBase
{
private static final String DOUBLE_KEY = "d";
private static final double DOUBLE_VALUE = 3.1;
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressMatchExpressionTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressMatchExpressionTest.java
index 9db4868c47e..cf1a221d7ac 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressMatchExpressionTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressMatchExpressionTest.java
@@ -25,6 +25,8 @@ import
org.apache.druid.math.expr.ExpressionValidationException;
import org.apache.druid.segment.column.ColumnType;
import org.apache.druid.segment.column.RowSignature;
import
org.apache.druid.sql.calcite.expression.builtin.IPv4AddressMatchOperatorConversion;
+import org.apache.druid.sql.calcite.util.CalciteTestBase;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -33,7 +35,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
-public class IPv4AddressMatchExpressionTest extends ExpressionTestBase
+public class IPv4AddressMatchExpressionTest extends CalciteTestBase
{
private static final String IPV4 = "192.168.0.1";
private static final long IPV4_LONG = 3232235521L;
@@ -65,65 +67,73 @@ public class IPv4AddressMatchExpressionTest extends
ExpressionTestBase
@Test
public void testTooFewArgs()
{
- expectException(IllegalArgumentException.class, "requires 2 arguments");
-
- testExpression(
- Collections.emptyList(),
- buildExpectedExpression(),
- IGNORE_EXPECTED_RESULT
+ Throwable t = Assert.assertThrows(
+ ExpressionValidationException.class,
+ () -> testExpression(
+ Collections.emptyList(),
+ buildExpectedExpression(),
+ IGNORE_EXPECTED_RESULT
+ )
);
+ Assert.assertEquals("Function[ipv4_match] requires 2 arguments",
t.getMessage());
}
@Test
public void testTooManyArgs()
{
- expectException(IllegalArgumentException.class, "requires 2 arguments");
-
String address = IPV4;
String subnet = SUBNET_192_168;
- testExpression(
- Arrays.asList(
- testHelper.makeLiteral(address),
- testHelper.makeLiteral(subnet),
- testHelper.makeLiteral(address)
- ),
- buildExpectedExpression(address, subnet, address),
- IGNORE_EXPECTED_RESULT
+ Throwable t = Assert.assertThrows(
+ ExpressionValidationException.class,
+ () -> testExpression(
+ Arrays.asList(
+ testHelper.makeLiteral(address),
+ testHelper.makeLiteral(subnet),
+ testHelper.makeLiteral(address)
+ ),
+ buildExpectedExpression(address, subnet, address),
+ IGNORE_EXPECTED_RESULT
+ )
);
+ Assert.assertEquals("Function[ipv4_match] requires 2 arguments",
t.getMessage());
}
@Test
public void testSubnetArgNotLiteral()
{
- expectException(ExpressionValidationException.class, "subnet argument must
be a literal");
-
String address = IPV4;
String variableName = VAR;
- testExpression(
- Arrays.asList(
- testHelper.makeLiteral(address),
- testHelper.makeInputRef(variableName)
- ),
- buildExpectedExpression(address,
testHelper.makeVariable(variableName)),
- IGNORE_EXPECTED_RESULT
+ Throwable t = Assert.assertThrows(
+ ExpressionValidationException.class,
+ () -> testExpression(
+ Arrays.asList(
+ testHelper.makeLiteral(address),
+ testHelper.makeInputRef(variableName)
+ ),
+ buildExpectedExpression(address,
testHelper.makeVariable(variableName)),
+ IGNORE_EXPECTED_RESULT
+ )
);
+ Assert.assertEquals("Function[ipv4_match] subnet argument must be a
literal", t.getMessage());
}
@Test
public void testSubnetArgInvalid()
{
- expectException(IllegalArgumentException.class, "subnet arg has an invalid
format");
-
String address = IPV4;
String invalidSubnet = "192.168.0.1/invalid";
- testExpression(
- Arrays.asList(
- testHelper.makeLiteral(address),
- testHelper.makeLiteral(invalidSubnet)
- ),
- buildExpectedExpression(address, invalidSubnet),
- IGNORE_EXPECTED_RESULT
+ Throwable t = Assert.assertThrows(
+ ExpressionValidationException.class,
+ () -> testExpression(
+ Arrays.asList(
+ testHelper.makeLiteral(address),
+ testHelper.makeLiteral(invalidSubnet)
+ ),
+ buildExpectedExpression(address, invalidSubnet),
+ IGNORE_EXPECTED_RESULT
+ )
);
+ Assert.assertEquals("Function[ipv4_match] subnet arg has an invalid
format: 192.168.0.1/invalid", t.getMessage());
}
@Test
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressParseExpressionTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressParseExpressionTest.java
index 6e4273f3552..f495b6e9500 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressParseExpressionTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressParseExpressionTest.java
@@ -25,6 +25,8 @@ import
org.apache.druid.math.expr.ExpressionValidationException;
import org.apache.druid.segment.column.ColumnType;
import org.apache.druid.segment.column.RowSignature;
import
org.apache.druid.sql.calcite.expression.builtin.IPv4AddressParseOperatorConversion;
+import org.apache.druid.sql.calcite.util.CalciteTestBase;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -33,7 +35,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
-public class IPv4AddressParseExpressionTest extends ExpressionTestBase
+public class IPv4AddressParseExpressionTest extends CalciteTestBase
{
private static final String VALID = "192.168.0.1";
private static final long EXPECTED = 3232235521L;
@@ -56,28 +58,32 @@ public class IPv4AddressParseExpressionTest extends
ExpressionTestBase
@Test
public void testTooFewArgs()
{
- expectException(ExpressionValidationException.class, "requires 1
argument");
-
- testExpression(
- Collections.emptyList(),
- buildExpectedExpression(),
- IGNORE_EXPECTED_RESULT
+ Throwable t = Assert.assertThrows(
+ ExpressionValidationException.class,
+ () -> testExpression(
+ Collections.emptyList(),
+ buildExpectedExpression(),
+ IGNORE_EXPECTED_RESULT
+ )
);
+ Assert.assertEquals("Function[ipv4_parse] requires 1 argument",
t.getMessage());
}
@Test
public void testTooManyArgs()
{
- expectException(ExpressionValidationException.class, "requires 1
argument");
-
- testExpression(
- Arrays.asList(
- testHelper.getConstantNull(),
- testHelper.getConstantNull()
- ),
- buildExpectedExpression(null, null),
- IGNORE_EXPECTED_RESULT
+ Throwable t = Assert.assertThrows(
+ ExpressionValidationException.class,
+ () -> testExpression(
+ Arrays.asList(
+ testHelper.getConstantNull(),
+ testHelper.getConstantNull()
+ ),
+ buildExpectedExpression(null, null),
+ IGNORE_EXPECTED_RESULT
+ )
);
+ Assert.assertEquals("Function[ipv4_parse] requires 1 argument",
t.getMessage());
}
@Test
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressStringifyExpressionTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressStringifyExpressionTest.java
index f434b7dca10..fb1b358cb08 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressStringifyExpressionTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/IPv4AddressStringifyExpressionTest.java
@@ -25,6 +25,8 @@ import
org.apache.druid.math.expr.ExpressionValidationException;
import org.apache.druid.segment.column.ColumnType;
import org.apache.druid.segment.column.RowSignature;
import
org.apache.druid.sql.calcite.expression.builtin.IPv4AddressStringifyOperatorConversion;
+import org.apache.druid.sql.calcite.util.CalciteTestBase;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -33,7 +35,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
-public class IPv4AddressStringifyExpressionTest extends ExpressionTestBase
+public class IPv4AddressStringifyExpressionTest extends CalciteTestBase
{
private static final long VALID = 3232235521L;
private static final String EXPECTED = "192.168.0.1";
@@ -57,28 +59,32 @@ public class IPv4AddressStringifyExpressionTest extends
ExpressionTestBase
@Test
public void testTooFewArgs()
{
- expectException(ExpressionValidationException.class, "requires 1
argument");
-
- testExpression(
- Collections.emptyList(),
- buildExpectedExpression(),
- IGNORE_EXPECTED_RESULT
+ Throwable t = Assert.assertThrows(
+ ExpressionValidationException.class,
+ () -> testExpression(
+ Collections.emptyList(),
+ buildExpectedExpression(),
+ IGNORE_EXPECTED_RESULT
+ )
);
+ Assert.assertEquals("Function[ipv4_stringify] requires 1 argument",
t.getMessage());
}
@Test
public void testTooManyArgs()
{
- expectException(ExpressionValidationException.class, "requires 1
argument");
-
- testExpression(
- Arrays.asList(
- testHelper.makeLiteral(VALID),
- testHelper.makeLiteral(VALID)
- ),
- buildExpectedExpression(VALID, VALID),
- IGNORE_EXPECTED_RESULT
+ Throwable t = Assert.assertThrows(
+ ExpressionValidationException.class,
+ () -> testExpression(
+ Arrays.asList(
+ testHelper.makeLiteral(VALID),
+ testHelper.makeLiteral(VALID)
+ ),
+ buildExpectedExpression(VALID, VALID),
+ IGNORE_EXPECTED_RESULT
+ )
);
+ Assert.assertEquals("Function[ipv4_stringify] requires 1 argument",
t.getMessage());
}
@Test
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/LeastExpressionTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/LeastExpressionTest.java
index 6702769e927..496543a5dd7 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/LeastExpressionTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/LeastExpressionTest.java
@@ -28,6 +28,7 @@ import org.apache.druid.java.util.common.DateTimes;
import org.apache.druid.segment.column.ColumnType;
import org.apache.druid.segment.column.RowSignature;
import org.apache.druid.sql.calcite.expression.builtin.LeastOperatorConversion;
+import org.apache.druid.sql.calcite.util.CalciteTestBase;
import org.junit.Before;
import org.junit.Test;
@@ -37,7 +38,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
-public class LeastExpressionTest extends ExpressionTestBase
+public class LeastExpressionTest extends CalciteTestBase
{
private static final String DOUBLE_KEY = "d";
private static final double DOUBLE_VALUE = 3.1;
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/TimeFormatOperatorConversionTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/TimeFormatOperatorConversionTest.java
index 204b7784281..021e3579515 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/TimeFormatOperatorConversionTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/TimeFormatOperatorConversionTest.java
@@ -27,6 +27,7 @@ import org.apache.druid.java.util.common.IAE;
import org.apache.druid.segment.column.ColumnType;
import org.apache.druid.segment.column.RowSignature;
import
org.apache.druid.sql.calcite.expression.builtin.TimeFormatOperatorConversion;
+import org.apache.druid.sql.calcite.util.CalciteTestBase;
import org.junit.Before;
import org.junit.Test;
@@ -36,7 +37,7 @@ import java.util.Map;
/**
* Tests for TIME_FORMAT
*/
-public class TimeFormatOperatorConversionTest extends ExpressionTestBase
+public class TimeFormatOperatorConversionTest extends CalciteTestBase
{
private static final RowSignature ROW_SIGNATURE = RowSignature
.builder()
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]