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 2e456d25ae fix issue with ExprEval.bestEffortOf and mixed type arrays
containing ARRAY<COMPLEX<json>> and other complicated casts (#14710)
2e456d25ae is described below
commit 2e456d25ae38e0dbaa073f2f196c7fcb1d478340
Author: Clint Wylie <[email protected]>
AuthorDate: Tue Aug 1 09:25:14 2023 -0700
fix issue with ExprEval.bestEffortOf and mixed type arrays containing
ARRAY<COMPLEX<json>> and other complicated casts (#14710)
---
.../java/org/apache/druid/math/expr/ExprEval.java | 40 ++-
.../java/org/apache/druid/math/expr/EvalTest.java | 214 +++++++-------
.../org/apache/druid/math/expr/ExprEvalTest.java | 316 ++++++++++++++++++++-
3 files changed, 451 insertions(+), 119 deletions(-)
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 7291083602..4bd29a19d0 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
@@ -235,6 +235,9 @@ public abstract class ExprEval<T>
*/
private static Class convertType(@Nullable Class existing, Class next)
{
+ if (existing != null && existing.equals(Object.class)) {
+ return existing;
+ }
if (Number.class.isAssignableFrom(next) || next == String.class || next ==
Boolean.class) {
// coerce booleans
if (next == Boolean.class) {
@@ -866,7 +869,7 @@ public abstract class ExprEval<T>
@Override
public Object[] asArray()
{
- return isNumericNull() ? null : new Object[] {value.doubleValue()};
+ return value == null ? null : new
Object[]{valueOrDefault().doubleValue()};
}
@Override
@@ -888,11 +891,13 @@ public abstract class ExprEval<T>
case DOUBLE:
return ExprEval.ofDoubleArray(asArray());
case LONG:
- return ExprEval.ofLongArray(value == null ? null : new Object[]
{value.longValue()});
+ return ExprEval.ofLongArray(value == null ? null : new
Object[]{value.longValue()});
case STRING:
- return ExprEval.ofStringArray(value == null ? null : new
Object[] {value.toString()});
+ return ExprEval.ofStringArray(value == null ? null : new
Object[]{value.toString()});
+ default:
+ ExpressionType elementType = (ExpressionType)
castTo.getElementType();
+ return new ArrayExprEval(castTo, new
Object[]{castTo(elementType).value()});
}
- break;
case COMPLEX:
if (ExpressionType.NESTED_DATA.equals(castTo)) {
return new NestedDataExprEval(value);
@@ -945,7 +950,7 @@ public abstract class ExprEval<T>
@Override
public Object[] asArray()
{
- return isNumericNull() ? null : new Object[] {value.longValue()};
+ return value == null ? null : new Object[]{valueOrDefault().longValue()};
}
@Override
@@ -963,15 +968,20 @@ public abstract class ExprEval<T>
case STRING:
return ExprEval.of(asString());
case ARRAY:
+ if (value == null) {
+ return new ArrayExprEval(castTo, null);
+ }
switch (castTo.getElementType().getType()) {
case DOUBLE:
- return ExprEval.ofDoubleArray(value == null ? null : new
Object[] {value.doubleValue()});
+ return ExprEval.ofDoubleArray(new Object[]{value.doubleValue()});
case LONG:
return ExprEval.ofLongArray(asArray());
case STRING:
- return ExprEval.ofStringArray(value == null ? null : new
Object[] {value.toString()});
+ return ExprEval.ofStringArray(new Object[]{value.toString()});
+ default:
+ ExpressionType elementType = (ExpressionType)
castTo.getElementType();
+ return new ArrayExprEval(castTo, new
Object[]{castTo(elementType).value()});
}
- break;
case COMPLEX:
if (ExpressionType.NESTED_DATA.equals(castTo)) {
return new NestedDataExprEval(value);
@@ -1062,7 +1072,7 @@ public abstract class ExprEval<T>
@Override
public Object[] asArray()
{
- return value == null ? null : new Object[] {value};
+ return value == null ? null : new Object[]{value};
}
private int computeInt()
@@ -1134,18 +1144,24 @@ public abstract class ExprEval<T>
case STRING:
return this;
case ARRAY:
+ if (value == null) {
+ return new ArrayExprEval(castTo, null);
+ }
final Number number = computeNumber();
switch (castTo.getElementType().getType()) {
case DOUBLE:
return ExprEval.ofDoubleArray(
- value == null ? null : new Object[] {number == null ? null :
number.doubleValue()}
+ new Object[]{number == null ? null : number.doubleValue()}
);
case LONG:
return ExprEval.ofLongArray(
- value == null ? null : new Object[] {number == null ? null :
number.longValue()}
+ new Object[]{number == null ? null : number.longValue()}
);
case STRING:
- return ExprEval.ofStringArray(value == null ? null : new
Object[] {value});
+ return ExprEval.ofStringArray(new Object[]{value});
+ default:
+ ExpressionType elementType = (ExpressionType)
castTo.getElementType();
+ return new ArrayExprEval(castTo, new
Object[]{castTo(elementType).value()});
}
case COMPLEX:
if (ExpressionType.NESTED_DATA.equals(castTo)) {
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 45191ade72..16ecc39c0c 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
@@ -451,10 +451,30 @@ public class EvalTest extends InitializedNullHandlingTest
).asArray()
);
- Assert.assertThrows(IAE.class, () ->
ExprEval.ofLong(1234L).castTo(nestedArray));
- Assert.assertThrows(IAE.class, () ->
ExprEval.of("hello").castTo(nestedArray));
- Assert.assertThrows(IAE.class, () ->
ExprEval.ofDouble(1.234).castTo(nestedArray));
- Assert.assertThrows(IAE.class, () ->
ExprEval.ofComplex(ExpressionType.NESTED_DATA, 1234L).castTo(nestedArray));
+ cast = ExprEval.ofLong(1234L).castTo(nestedArray);
+ Assert.assertEquals(nestedArray, cast.type());
+ Assert.assertArrayEquals(
+ new Object[]{1234L},
+ cast.asArray()
+ );
+ cast = ExprEval.of("hello").castTo(nestedArray);
+ Assert.assertEquals(nestedArray, cast.type());
+ Assert.assertArrayEquals(
+ new Object[]{"hello"},
+ cast.asArray()
+ );
+ cast = ExprEval.ofDouble(1.234).castTo(nestedArray);
+ Assert.assertEquals(nestedArray, cast.type());
+ Assert.assertArrayEquals(
+ new Object[]{1.234},
+ cast.asArray()
+ );
+ cast = ExprEval.ofComplex(ExpressionType.NESTED_DATA,
1234L).castTo(nestedArray);
+ Assert.assertArrayEquals(
+ new Object[]{1234L},
+ cast.asArray()
+ );
+ Assert.assertEquals(nestedArray, cast.type());
}
@Test
@@ -1146,145 +1166,145 @@ public class EvalTest extends
InitializedNullHandlingTest
Assert.assertEquals("notbase64", eval.value());
// arrays
- eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1L, 2L,
3L});
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[]{1L, 2L,
3L});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L}, (Object[])
eval.value());
eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, ImmutableList.of(1L, 2L,
3L));
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L}, (Object[])
eval.value());
eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Long[]{1L, 2L, 3L});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L}, (Object[])
eval.value());
eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new long[]{1L, 2L, 3L});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L}, (Object[])
eval.value());
eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new int[]{1, 2, 3});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1L, 2L,
null, 3L});
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[]{1L, 2L,
null, 3L});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, null, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, null, 3L}, (Object[])
eval.value());
// arrays might have to fall back to using 'bestEffortOf', but will cast
it to the expected output type
- eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {"1", "2",
"3"});
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[]{"1", "2",
"3"});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new String[] {"1", "2",
"3"});
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new String[]{"1", "2",
"3"});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {"1", "2",
"wat", "3"});
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[]{"1", "2",
"wat", "3"});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, null, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, null, 3L}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1.0, 2.0,
3.0});
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[]{1.0, 2.0,
3.0});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new double[] {1.0, 2.0,
3.0});
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new double[]{1.0, 2.0,
3.0});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1.0, 2.0,
null, 3.0});
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[]{1.0, 2.0,
null, 3.0});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, null, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, null, 3L}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1.0, 2L,
"3", true, false});
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[]{1.0, 2L,
"3", true, false});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L, 1L, 0L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L, 1L, 0L}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new float[] {1.0f, 2.0f,
3.0f});
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new float[]{1.0f, 2.0f,
3.0f});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1L, 2L, 3L}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1L, 2L, 3L}, (Object[])
eval.value());
// etc
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {1.0,
2.0, 3.0});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[]{1.0, 2.0,
3.0});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, 3.0}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, 3.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Double[] {1.0,
2.0, 3.0});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Double[]{1.0, 2.0,
3.0});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, 3.0}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, 3.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new double[] {1.0,
2.0, 3.0});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new double[]{1.0, 2.0,
3.0});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, 3.0}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, 3.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {"1",
"2", "3"});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[]{"1", "2",
"3"});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, 3.0}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, 3.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {"1",
"2", "wat", "3"});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[]{"1", "2",
"wat", "3"});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, null, 3.0}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, null, 3.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {1L, 2L,
3L});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[]{1L, 2L,
3L});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, 3.0}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, 3.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new long[] {1L, 2L,
3L});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new long[]{1L, 2L,
3L});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, 3.0}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, 3.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {1L, 2L,
null, 3L});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[]{1L, 2L,
null, 3L});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, null, 3.0}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, null, 3.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {1.0, 2L,
"3", true, false});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[]{1.0, 2L,
"3", true, false});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, 3.0, 1.0, 0.0},
(Object[]) eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, 3.0, 1.0, 0.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Float[] {1.0f,
2.0f, 3.0f});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Float[]{1.0f,
2.0f, 3.0f});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, 3.0}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, 3.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new float[] {1.0f,
2.0f, 3.0f});
+ eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new float[]{1.0f,
2.0f, 3.0f});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {1.0, 2.0, 3.0}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, 3.0}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.STRING_ARRAY, new Object[] {"1",
"2", "3"});
+ eval = ExprEval.ofType(ExpressionType.STRING_ARRAY, new Object[]{"1", "2",
"3"});
Assert.assertEquals(ExpressionType.STRING_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {"1", "2", "3"}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{"1", "2", "3"}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.STRING_ARRAY, new Object[] {1L, 2L,
3L});
+ eval = ExprEval.ofType(ExpressionType.STRING_ARRAY, new Object[]{1L, 2L,
3L});
Assert.assertEquals(ExpressionType.STRING_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {"1", "2", "3"}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{"1", "2", "3"}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.STRING_ARRAY, new Object[] {1.0,
2.0, 3.0});
+ eval = ExprEval.ofType(ExpressionType.STRING_ARRAY, new Object[]{1.0, 2.0,
3.0});
Assert.assertEquals(ExpressionType.STRING_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {"1.0", "2.0", "3.0"}, (Object[])
eval.value());
+ Assert.assertArrayEquals(new Object[]{"1.0", "2.0", "3.0"}, (Object[])
eval.value());
- eval = ExprEval.ofType(ExpressionType.STRING_ARRAY, new Object[] {1.0, 2L,
"3", true, false});
+ eval = ExprEval.ofType(ExpressionType.STRING_ARRAY, new Object[]{1.0, 2L,
"3", true, false});
Assert.assertEquals(ExpressionType.STRING_ARRAY, eval.type());
- Assert.assertArrayEquals(new Object[] {"1.0", "2", "3", "true", "false"},
(Object[]) eval.value());
+ Assert.assertArrayEquals(new Object[]{"1.0", "2", "3", "true", "false"},
(Object[]) eval.value());
// nested arrays
ExpressionType nestedLongArray =
ExpressionTypeFactory.getInstance().ofArray(ExpressionType.LONG_ARRAY);
final Object[] expectedLongArray = new Object[]{
- new Object[] {1L, 2L, 3L},
- new Object[] {5L, null, 9L},
+ new Object[]{1L, 2L, 3L},
+ new Object[]{5L, null, 9L},
null,
- new Object[] {2L, 4L, 6L}
+ new Object[]{2L, 4L, 6L}
};
List<?> longArrayInputs = Arrays.asList(
new Object[]{
- new Object[] {1L, 2L, 3L},
- new Object[] {5L, null, 9L},
+ new Object[]{1L, 2L, 3L},
+ new Object[]{5L, null, 9L},
null,
- new Object[] {2L, 4L, 6L}
+ new Object[]{2L, 4L, 6L}
},
Arrays.asList(
- new Object[] {1L, 2L, 3L},
- new Object[] {5L, null, 9L},
+ new Object[]{1L, 2L, 3L},
+ new Object[]{5L, null, 9L},
null,
- new Object[] {2L, 4L, 6L}
+ new Object[]{2L, 4L, 6L}
),
Arrays.asList(
Arrays.asList(1L, 2L, 3L),
@@ -1312,18 +1332,18 @@ public class EvalTest extends
InitializedNullHandlingTest
ExpressionType nestedDoubleArray =
ExpressionTypeFactory.getInstance().ofArray(ExpressionType.DOUBLE_ARRAY);
final Object[] expectedDoubleArray = new Object[]{
- new Object[] {1.1, 2.2, 3.3},
- new Object[] {5.5, null, 9.9},
+ new Object[]{1.1, 2.2, 3.3},
+ new Object[]{5.5, null, 9.9},
null,
- new Object[] {2.2, 4.4, 6.6}
+ new Object[]{2.2, 4.4, 6.6}
};
List<?> doubleArrayInputs = Arrays.asList(
new Object[]{
- new Object[] {1.1, 2.2, 3.3},
- new Object[] {5.5, null, 9.9},
+ new Object[]{1.1, 2.2, 3.3},
+ new Object[]{5.5, null, 9.9},
null,
- new Object[] {2.2, 4.4, 6.6}
+ new Object[]{2.2, 4.4, 6.6}
},
new Object[]{
Arrays.asList(1.1, 2.2, 3.3),
@@ -1338,10 +1358,10 @@ public class EvalTest extends
InitializedNullHandlingTest
Arrays.asList(2.2, 4.4, 6.6)
),
new Object[]{
- new Object[] {"1.1", "2.2", "3.3"},
+ new Object[]{"1.1", "2.2", "3.3"},
Arrays.asList("5.5", null, "9.9"),
null,
- new String[] {"2.2", "4.4", "6.6"}
+ new String[]{"2.2", "4.4", "6.6"}
}
);
@@ -1392,38 +1412,38 @@ public class EvalTest extends
InitializedNullHandlingTest
assertBestEffortOf(1.0f, ExpressionType.DOUBLE, 1.0);
// arrays
- assertBestEffortOf(new Object[] {1L, 2L, 3L}, ExpressionType.LONG_ARRAY,
new Object[] {1L, 2L, 3L});
- assertBestEffortOf(new Object[] {1L, 2L, null, 3L},
ExpressionType.LONG_ARRAY, new Object[] {1L, 2L, null, 3L});
- assertBestEffortOf(ImmutableList.of(1L, 2L, 3L),
ExpressionType.LONG_ARRAY, new Object[] {1L, 2L, 3L});
- assertBestEffortOf(new long[] {1L, 2L, 3L}, ExpressionType.LONG_ARRAY, new
Object[] {1L, 2L, 3L});
- assertBestEffortOf(new Object[] {1, 2, 3}, ExpressionType.LONG_ARRAY, new
Object[] {1L, 2L, 3L});
- assertBestEffortOf(new Integer[] {1, 2, 3}, ExpressionType.LONG_ARRAY, new
Object[] {1L, 2L, 3L});
- assertBestEffortOf(new int[] {1, 2, 3}, ExpressionType.LONG_ARRAY, new
Object[] {1L, 2L, 3L});
-
- assertBestEffortOf(new Object[] {1.0, 2.0, 3.0},
ExpressionType.DOUBLE_ARRAY, new Object[] {1.0, 2.0, 3.0});
+ assertBestEffortOf(new Object[]{1L, 2L, 3L}, ExpressionType.LONG_ARRAY,
new Object[]{1L, 2L, 3L});
+ assertBestEffortOf(new Object[]{1L, 2L, null, 3L},
ExpressionType.LONG_ARRAY, new Object[]{1L, 2L, null, 3L});
+ assertBestEffortOf(ImmutableList.of(1L, 2L, 3L),
ExpressionType.LONG_ARRAY, new Object[]{1L, 2L, 3L});
+ assertBestEffortOf(new long[]{1L, 2L, 3L}, ExpressionType.LONG_ARRAY, new
Object[]{1L, 2L, 3L});
+ assertBestEffortOf(new Object[]{1, 2, 3}, ExpressionType.LONG_ARRAY, new
Object[]{1L, 2L, 3L});
+ assertBestEffortOf(new Integer[]{1, 2, 3}, ExpressionType.LONG_ARRAY, new
Object[]{1L, 2L, 3L});
+ assertBestEffortOf(new int[]{1, 2, 3}, ExpressionType.LONG_ARRAY, new
Object[]{1L, 2L, 3L});
+
+ assertBestEffortOf(new Object[]{1.0, 2.0, 3.0},
ExpressionType.DOUBLE_ARRAY, new Object[]{1.0, 2.0, 3.0});
assertBestEffortOf(
- new Object[] {null, 1.0, 2.0, 3.0},
+ new Object[]{null, 1.0, 2.0, 3.0},
ExpressionType.DOUBLE_ARRAY,
- new Object[] {null, 1.0, 2.0, 3.0}
+ new Object[]{null, 1.0, 2.0, 3.0}
);
- assertBestEffortOf(new Double[] {1.0, 2.0, 3.0},
ExpressionType.DOUBLE_ARRAY, new Object[] {1.0, 2.0, 3.0});
- assertBestEffortOf(new double[] {1.0, 2.0, 3.0},
ExpressionType.DOUBLE_ARRAY, new Object[] {1.0, 2.0, 3.0});
- assertBestEffortOf(new Object[] {1.0f, 2.0f, 3.0f},
ExpressionType.DOUBLE_ARRAY, new Object[] {1.0, 2.0, 3.0});
- assertBestEffortOf(new Float[] {1.0f, 2.0f, 3.0f},
ExpressionType.DOUBLE_ARRAY, new Object[] {1.0, 2.0, 3.0});
- assertBestEffortOf(new float[] {1.0f, 2.0f, 3.0f},
ExpressionType.DOUBLE_ARRAY, new Object[] {1.0, 2.0, 3.0});
+ assertBestEffortOf(new Double[]{1.0, 2.0, 3.0},
ExpressionType.DOUBLE_ARRAY, new Object[]{1.0, 2.0, 3.0});
+ assertBestEffortOf(new double[]{1.0, 2.0, 3.0},
ExpressionType.DOUBLE_ARRAY, new Object[]{1.0, 2.0, 3.0});
+ assertBestEffortOf(new Object[]{1.0f, 2.0f, 3.0f},
ExpressionType.DOUBLE_ARRAY, new Object[]{1.0, 2.0, 3.0});
+ assertBestEffortOf(new Float[]{1.0f, 2.0f, 3.0f},
ExpressionType.DOUBLE_ARRAY, new Object[]{1.0, 2.0, 3.0});
+ assertBestEffortOf(new float[]{1.0f, 2.0f, 3.0f},
ExpressionType.DOUBLE_ARRAY, new Object[]{1.0, 2.0, 3.0});
- assertBestEffortOf(new Object[] {"1", "2", "3"},
ExpressionType.STRING_ARRAY, new Object[] {"1", "2", "3"});
- assertBestEffortOf(new String[] {"1", "2", "3"},
ExpressionType.STRING_ARRAY, new Object[] {"1", "2", "3"});
- assertBestEffortOf(ImmutableList.of("1", "2", "3"),
ExpressionType.STRING_ARRAY, new Object[] {"1", "2", "3"});
+ assertBestEffortOf(new Object[]{"1", "2", "3"},
ExpressionType.STRING_ARRAY, new Object[]{"1", "2", "3"});
+ assertBestEffortOf(new String[]{"1", "2", "3"},
ExpressionType.STRING_ARRAY, new Object[]{"1", "2", "3"});
+ assertBestEffortOf(ImmutableList.of("1", "2", "3"),
ExpressionType.STRING_ARRAY, new Object[]{"1", "2", "3"});
// arrays end up as the least restrictive type
- assertBestEffortOf(new Object[] {1.0, 2L}, ExpressionType.DOUBLE_ARRAY,
new Object[] {1.0, 2.0});
+ assertBestEffortOf(new Object[]{1.0, 2L}, ExpressionType.DOUBLE_ARRAY, new
Object[]{1.0, 2.0});
// arrays end up as the least restrictive type
assertBestEffortOf(
- new Object[] {1.0, 2L, "3", true, false},
+ new Object[]{1.0, 2L, "3", true, false},
ExpressionType.STRING_ARRAY,
- new Object[] {"1.0", "2", "3", "true", "false"}
+ new Object[]{"1.0", "2", "3", "true", "false"}
);
assertBestEffortOf(
diff --git
a/processing/src/test/java/org/apache/druid/math/expr/ExprEvalTest.java
b/processing/src/test/java/org/apache/druid/math/expr/ExprEvalTest.java
index 99acecd309..e624ed04e5 100644
--- a/processing/src/test/java/org/apache/druid/math/expr/ExprEvalTest.java
+++ b/processing/src/test/java/org/apache/druid/math/expr/ExprEvalTest.java
@@ -22,6 +22,7 @@ package org.apache.druid.math.expr;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.druid.collections.SerializablePair;
+import org.apache.druid.java.util.common.IAE;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.NonnullPair;
import org.apache.druid.java.util.common.StringUtils;
@@ -333,6 +334,49 @@ public class ExprEvalTest extends
InitializedNullHandlingTest
coerced.rhs
);
+ Map<String, Object> nested1 = ImmutableMap.of("x", 1L, "y", 2L);
+ List<Object> mixedObject = ImmutableList.of(
+ "a",
+ 1L,
+ 3.0,
+ nested1
+ );
+ coerced = ExprEval.coerceListToArray(mixedObject, false);
+ Assert.assertEquals(
+
ExpressionTypeFactory.getInstance().ofArray(ExpressionType.NESTED_DATA),
+ coerced.lhs
+ );
+ Assert.assertArrayEquals(
+ new Object[]{
+ "a",
+ 1L,
+ 3.0,
+ nested1
+ },
+ coerced.rhs
+ );
+
+ List<Object> mixedObject2 = ImmutableList.of(
+ nested1,
+ "a",
+ 1L,
+ 3.0
+ );
+ coerced = ExprEval.coerceListToArray(mixedObject2, false);
+ Assert.assertEquals(
+
ExpressionTypeFactory.getInstance().ofArray(ExpressionType.NESTED_DATA),
+ coerced.lhs
+ );
+ Assert.assertArrayEquals(
+ new Object[]{
+ nested1,
+ "a",
+ 1L,
+ 3.0
+ },
+ coerced.rhs
+ );
+
List<List<String>> nestedLists = ImmutableList.of(
ImmutableList.of("a", "b", "c"),
ImmutableList.of("d", "e", "f")
@@ -344,7 +388,7 @@ public class ExprEvalTest extends
InitializedNullHandlingTest
coerced.rhs
);
- Map<String, Object> nested1 = ImmutableMap.of("x", 1L, "y", 2L);
+
Map<String, Object> nested2 = ImmutableMap.of("x", 4L, "y", 5L);
List<Map<String, Object>> listUnknownComplex = ImmutableList.of(nested1,
nested2);
coerced = ExprEval.coerceListToArray(listUnknownComplex, false);
@@ -421,6 +465,66 @@ public class ExprEvalTest extends
InitializedNullHandlingTest
coerced.rhs
);
+ List<Object> mixedNested2 = ImmutableList.of(
+ "a",
+ 1L,
+ 3.0,
+ ImmutableList.of("a", "b", "c"),
+ ImmutableList.of(1L, 2L, 3L),
+ ImmutableList.of(3.0, 4.0, 5.0),
+ ImmutableList.of(nested1, nested2, nested3)
+ );
+ coerced = ExprEval.coerceListToArray(mixedNested2, false);
+ Assert.assertEquals(
+ ExpressionTypeFactory.getInstance().ofArray(
+
ExpressionTypeFactory.getInstance().ofArray(ExpressionType.NESTED_DATA)
+ ),
+ coerced.lhs
+ );
+ Assert.assertArrayEquals(
+ new Object[]{
+ new Object[]{"a"},
+ new Object[]{1L},
+ new Object[]{3.0},
+ new Object[]{"a", "b", "c"},
+ new Object[]{1L, 2L, 3L},
+ new Object[]{3.0, 4.0, 5.0},
+ new Object[]{nested1, nested2, nested3}
+ },
+ coerced.rhs
+ );
+
+
+ List<Object> mixedNested3 = ImmutableList.of(
+ "a",
+ 1L,
+ 3.0,
+ nested1,
+ ImmutableList.of("a", "b", "c"),
+ ImmutableList.of(1L, 2L, 3L),
+ ImmutableList.of(3.0, 4.0, 5.0),
+ ImmutableList.of(nested1, nested2, nested3)
+ );
+ coerced = ExprEval.coerceListToArray(mixedNested3, false);
+ // this one is only ARRAY<COMPLEX<json>> instead of
ARRAY<ARRAY<COMPLEX<json>> because of a COMPLEX<json> element..
+ Assert.assertEquals(
+
ExpressionTypeFactory.getInstance().ofArray(ExpressionType.NESTED_DATA),
+ coerced.lhs
+ );
+ Assert.assertArrayEquals(
+ new Object[]{
+ "a",
+ 1L,
+ 3.0,
+ nested1,
+ new Object[]{"a", "b", "c"},
+ new Object[]{1L, 2L, 3L},
+ new Object[]{3.0, 4.0, 5.0},
+ new Object[]{nested1, nested2, nested3}
+ },
+ coerced.rhs
+ );
+
List<List<Object>> mixedUnknown = ImmutableList.of(
ImmutableList.of("a", "b", "c"),
ImmutableList.of(1L, 2L, 3L),
@@ -435,17 +539,209 @@ public class ExprEvalTest extends
InitializedNullHandlingTest
}
@Test
- public void testStringArrayToNumberArray()
+ public void testCastString()
{
- ExprEval someStringArray = ExprEval.ofStringArray(new String[]{"1", "2",
"foo", null, "3.3"});
- Assert.assertArrayEquals(
- new Object[]{1L, 2L, null, null, 3L},
- someStringArray.castTo(ExpressionType.LONG_ARRAY).asArray()
- );
- Assert.assertArrayEquals(
- new Object[]{1.0, 2.0, null, null, 3.3},
- someStringArray.castTo(ExpressionType.DOUBLE_ARRAY).asArray()
+ ExprEval<?> eval = ExprEval.of("hello");
+
+ ExprEval<?> cast = eval.castTo(ExpressionType.DOUBLE);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.STRING_ARRAY);
+ Assert.assertArrayEquals(new Object[]{"hello"}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG_ARRAY);
+ Assert.assertArrayEquals(new Object[]{null}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.DOUBLE_ARRAY);
+ Assert.assertArrayEquals(new Object[]{null}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.NESTED_DATA);
+ Assert.assertEquals("hello", cast.value());
+
+ cast =
eval.castTo(ExpressionTypeFactory.getInstance().ofArray(ExpressionType.NESTED_DATA));
+ Assert.assertArrayEquals(new Object[]{"hello"}, (Object[]) cast.value());
+
+ eval = ExprEval.of("1234.3");
+
+ cast = eval.castTo(ExpressionType.DOUBLE);
+ Assert.assertEquals(1234.3, cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG);
+ Assert.assertEquals(1234L, cast.value());
+
+ cast = eval.castTo(ExpressionType.DOUBLE_ARRAY);
+ Assert.assertArrayEquals(new Object[]{1234.3}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG_ARRAY);
+ Assert.assertArrayEquals(new Object[]{1234L}, (Object[]) cast.value());
+
+ eval = ExprEval.ofType(ExpressionType.STRING, null);
+
+ cast = eval.castTo(ExpressionType.DOUBLE);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.STRING_ARRAY);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG_ARRAY);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.DOUBLE_ARRAY);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.NESTED_DATA);
+ Assert.assertNull(cast.value());
+ }
+
+ @Test
+ public void testCastDouble()
+ {
+ ExprEval<?> eval = ExprEval.of(123.4);
+
+ ExprEval<?> cast = eval.castTo(ExpressionType.STRING);
+ Assert.assertEquals("123.4", cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG);
+ Assert.assertEquals(123L, cast.value());
+
+ cast = eval.castTo(ExpressionType.STRING_ARRAY);
+ Assert.assertArrayEquals(new Object[]{"123.4"}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG_ARRAY);
+ Assert.assertArrayEquals(new Object[]{123L}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.DOUBLE_ARRAY);
+ Assert.assertArrayEquals(new Object[]{123.4}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.NESTED_DATA);
+ Assert.assertEquals(123.4, cast.value());
+
+ eval = ExprEval.ofType(ExpressionType.DOUBLE, null);
+
+ cast = eval.castTo(ExpressionType.STRING);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.STRING_ARRAY);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG_ARRAY);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.DOUBLE_ARRAY);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.NESTED_DATA);
+ Assert.assertNull(cast.value());
+ }
+
+ @Test
+ public void testCastLong()
+ {
+ ExprEval<?> eval = ExprEval.of(1234L);
+
+ ExprEval<?> cast = eval.castTo(ExpressionType.STRING);
+ Assert.assertEquals("1234", cast.value());
+
+ cast = eval.castTo(ExpressionType.DOUBLE);
+ Assert.assertEquals(1234.0, cast.value());
+
+ cast = eval.castTo(ExpressionType.STRING_ARRAY);
+ Assert.assertArrayEquals(new Object[]{"1234"}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG_ARRAY);
+ Assert.assertArrayEquals(new Object[]{1234L}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.DOUBLE_ARRAY);
+ Assert.assertArrayEquals(new Object[]{1234.0}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.NESTED_DATA);
+ Assert.assertEquals(1234L, cast.value());
+
+ eval = ExprEval.ofType(ExpressionType.LONG, null);
+
+ cast = eval.castTo(ExpressionType.STRING);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.STRING_ARRAY);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG_ARRAY);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.DOUBLE_ARRAY);
+ Assert.assertNull(cast.value());
+
+ cast = eval.castTo(ExpressionType.NESTED_DATA);
+ Assert.assertNull(cast.value());
+ }
+
+ @Test
+ public void testCastArray()
+ {
+ ExprEval<?> eval = ExprEval.ofStringArray(new String[]{"1", "2", "foo",
null, "3.3"});
+
+ ExprEval<?> cast = eval.castTo(ExpressionType.LONG_ARRAY);
+ Assert.assertArrayEquals(new Object[]{1L, 2L, null, null, 3L}, (Object[])
cast.value());
+
+ cast = eval.castTo(ExpressionType.DOUBLE_ARRAY);
+ Assert.assertArrayEquals(new Object[]{1.0, 2.0, null, null, 3.3},
(Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.NESTED_DATA);
+ Assert.assertArrayEquals(new Object[]{"1", "2", "foo", null, "3.3"},
(Object[]) cast.value());
+
+ cast =
eval.castTo(ExpressionTypeFactory.getInstance().ofArray(ExpressionType.NESTED_DATA));
+ Assert.assertArrayEquals(new Object[]{"1", "2", "foo", null, "3.3"},
(Object[]) cast.value());
+
+ ExprEval<?> finalEval = eval;
+ Throwable t = Assert.assertThrows(IAE.class, () ->
finalEval.castTo(ExpressionType.LONG));
+ Assert.assertEquals("Invalid type, cannot cast [ARRAY<STRING>] to [LONG]",
t.getMessage());
+
+ t = Assert.assertThrows(IAE.class, () ->
finalEval.castTo(ExpressionType.DOUBLE));
+ Assert.assertEquals("Invalid type, cannot cast [ARRAY<STRING>] to
[DOUBLE]", t.getMessage());
+
+ t = Assert.assertThrows(IAE.class, () ->
finalEval.castTo(ExpressionType.STRING));
+ Assert.assertEquals("Invalid type, cannot cast [ARRAY<STRING>] to
[STRING]", t.getMessage());
+
+ eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[]{1234L});
+
+ cast = eval.castTo(ExpressionType.DOUBLE_ARRAY);
+ Assert.assertArrayEquals(new Object[]{1234.0}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.STRING_ARRAY);
+ Assert.assertArrayEquals(new Object[]{"1234"}, (Object[]) cast.value());
+
+ cast = eval.castTo(ExpressionType.STRING);
+ Assert.assertEquals("1234", cast.value());
+
+ cast = eval.castTo(ExpressionType.DOUBLE);
+ Assert.assertEquals(1234.0, cast.value());
+
+ cast = eval.castTo(ExpressionType.LONG);
+ Assert.assertEquals(1234L, cast.value());
+ }
+
+ @Test
+ public void testCastNestedData()
+ {
+ ExprEval<?> eval = ExprEval.ofType(ExpressionType.NESTED_DATA,
ImmutableMap.of("x", 1234L, "y", 12.34));
+ Assert.assertEquals(
+ ImmutableMap.of("x", 1234L, "y", 12.34),
+ eval.castTo(ExpressionType.NESTED_DATA).value()
);
+ Throwable t = Assert.assertThrows(IAE.class, () ->
eval.castTo(ExpressionType.LONG));
+ Assert.assertEquals("Invalid type, cannot cast [COMPLEX<json>] to [LONG]",
t.getMessage());
}
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]