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 5824ab9608 fix issue with boolean expression input (#12429)
5824ab9608 is described below
commit 5824ab9608dc05aa6d04152e9b0357585c6823bf
Author: Clint Wylie <[email protected]>
AuthorDate: Wed Apr 13 16:34:01 2022 -0700
fix issue with boolean expression input (#12429)
---
.../java/org/apache/druid/math/expr/ExprEval.java | 49 +++--
.../java/org/apache/druid/math/expr/EvalTest.java | 238 +++++++++++++++++++++
.../ExpressionLambdaAggregatorFactoryTest.java | 2 +-
.../druid/segment/transform/TransformSpecTest.java | 90 +++++++-
4 files changed, 351 insertions(+), 28 deletions(-)
diff --git a/core/src/main/java/org/apache/druid/math/expr/ExprEval.java
b/core/src/main/java/org/apache/druid/math/expr/ExprEval.java
index 158eb3d9c8..3152fb26d5 100644
--- a/core/src/main/java/org/apache/druid/math/expr/ExprEval.java
+++ b/core/src/main/java/org/apache/druid/math/expr/ExprEval.java
@@ -130,19 +130,19 @@ public abstract class ExprEval<T>
if (coercedType == Long.class || coercedType == Integer.class) {
return new NonnullPair<>(
ExpressionType.LONG_ARRAY,
- val.stream().map(x -> x != null ? ((Number) x).longValue() :
null).toArray()
+ val.stream().map(x -> x != null ?
ExprEval.ofType(ExpressionType.LONG, x).value() : null).toArray()
);
}
if (coercedType == Float.class || coercedType == Double.class) {
return new NonnullPair<>(
ExpressionType.DOUBLE_ARRAY,
- val.stream().map(x -> x != null ? ((Number) x).doubleValue() :
null).toArray()
+ val.stream().map(x -> x != null ?
ExprEval.ofType(ExpressionType.DOUBLE, x).value() : null).toArray()
);
}
// default to string
return new NonnullPair<>(
ExpressionType.STRING_ARRAY,
- val.stream().map(x -> x != null ? x.toString() : null).toArray()
+ val.stream().map(x -> x != null ?
ExprEval.ofType(ExpressionType.STRING, x).value() : null).toArray()
);
}
if (homogenizeMultiValueStrings) {
@@ -194,7 +194,7 @@ public abstract class ExprEval<T>
*/
private static Class convertType(@Nullable Class existing, Class next)
{
- if (Number.class.isAssignableFrom(next) || next == String.class) {
+ if (Number.class.isAssignableFrom(next) || next == String.class || next ==
Boolean.class) {
if (existing == null) {
return next;
}
@@ -348,6 +348,12 @@ public abstract class ExprEval<T>
}
return new LongExprEval((Number) val);
}
+ if (val instanceof Boolean) {
+ if (ExpressionProcessing.useStrictBooleans()) {
+ return ofLongBoolean((Boolean) val);
+ }
+ return new StringExprEval(String.valueOf(val));
+ }
if (val instanceof Long[]) {
return new ArrayExprEval(ExpressionType.LONG_ARRAY, (Long[]) val);
}
@@ -360,20 +366,13 @@ public abstract class ExprEval<T>
if (val instanceof String[]) {
return new ArrayExprEval(ExpressionType.STRING_ARRAY, (String[]) val);
}
- if (val instanceof Object[]) {
- ExpressionType arrayType = findArrayType((Object[]) val);
- if (arrayType != null) {
- return new ArrayExprEval(arrayType, (Object[]) val);
- }
- // default to string if array is empty
- return new ArrayExprEval(ExpressionType.STRING_ARRAY, (Object[]) val);
- }
- if (val instanceof List) {
+ if (val instanceof List || val instanceof Object[]) {
+ final List<?> theList = val instanceof List ? ((List<?>) val) :
Arrays.asList((Object[]) val);
// do not convert empty lists to arrays with a single null element here,
because that should have been done
// by the selectors preparing their ObjectBindings if necessary. If we
get to this point it was legitimately
// empty
- NonnullPair<ExpressionType, Object[]> coerced =
coerceListToArray((List<?>) val, false);
+ NonnullPair<ExpressionType, Object[]> coerced =
coerceListToArray(theList, false);
if (coerced == null) {
return bestEffortOf(null);
}
@@ -400,7 +399,7 @@ public abstract class ExprEval<T>
return new ArrayExprEval(ExpressionType.STRING_ARRAY, (String[])
value);
}
if (value instanceof Object[]) {
- return new ArrayExprEval(ExpressionType.STRING_ARRAY, (Object[])
value);
+ return bestEffortOf(value);
}
if (value instanceof List) {
return bestEffortOf(value);
@@ -413,6 +412,9 @@ public abstract class ExprEval<T>
if (value instanceof Number) {
return ofLong((Number) value);
}
+ if (value instanceof Boolean) {
+ return ofLongBoolean((Boolean) value);
+ }
if (value instanceof String) {
return ofLong(ExprEval.computeNumber((String) value));
}
@@ -421,6 +423,12 @@ public abstract class ExprEval<T>
if (value instanceof Number) {
return ofDouble((Number) value);
}
+ if (value instanceof Boolean) {
+ if (ExpressionProcessing.useStrictBooleans()) {
+ return ofLongBoolean((Boolean) value);
+ }
+ return ofDouble(Evals.asDouble((Boolean) value));
+ }
if (value instanceof String) {
return ofDouble(ExprEval.computeNumber((String) value));
}
@@ -442,13 +450,14 @@ public abstract class ExprEval<T>
return ofComplex(type, value);
case ARRAY:
- if (value instanceof Object[]) {
+ // nested arrays, here be dragons... don't do any fancy coercion,
assume everything is already sane types...
+ if (type.getElementType().isArray()) {
return ofArray(type, (Object[]) value);
}
// in a better world, we might get an object that matches the type
signature for arrays and could do a switch
// statement here, but this is not that world yet, and things that are
array typed might also be non-arrays,
// e.g. we might get a String instead of String[], so just fallback to
bestEffortOf
- return bestEffortOf(value);
+ return bestEffortOf(value).castTo(type);
}
throw new IAE("Cannot create type [%s]", type);
}
@@ -459,6 +468,12 @@ public abstract class ExprEval<T>
if (value == null) {
return null;
}
+ if (Evals.asBoolean(value)) {
+ return 1.0;
+ }
+ if (value.equalsIgnoreCase("false")) {
+ return 0.0;
+ }
Number rv;
Long v = GuavaUtils.tryParseLong(value);
// Do NOT use ternary operator here, because it makes Java to convert Long
to Double
diff --git a/core/src/test/java/org/apache/druid/math/expr/EvalTest.java
b/core/src/test/java/org/apache/druid/math/expr/EvalTest.java
index 4b85836f7c..b15f5f8106 100644
--- a/core/src/test/java/org/apache/druid/math/expr/EvalTest.java
+++ b/core/src/test/java/org/apache/druid/math/expr/EvalTest.java
@@ -22,12 +22,20 @@ package org.apache.druid.math.expr;
import com.google.common.collect.ImmutableMap;
import org.apache.druid.common.config.NullHandling;
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.testing.InitializedNullHandlingTest;
import org.junit.Assert;
+import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -35,6 +43,16 @@ import static org.junit.Assert.assertNull;
*/
public class EvalTest extends InitializedNullHandlingTest
{
+
+ @BeforeClass
+ public static void setupClass()
+ {
+ TypeStrategies.registerComplex(
+ TypeStrategiesTest.NULLABLE_TEST_PAIR_TYPE.getComplexTypeName(),
+ new TypeStrategiesTest.NullableLongPairTypeStrategy()
+ );
+ }
+
@Rule
public ExpectedException expectedException = ExpectedException.none();
@@ -576,4 +594,224 @@ public class EvalTest extends InitializedNullHandlingTest
ExpressionProcessing.initializeForTests(null);
}
}
+
+ @Test
+ public void testBooleanInputs()
+ {
+ Map<String, Object> bindingsMap = new HashMap<>();
+ bindingsMap.put("l1", 100L);
+ bindingsMap.put("l2", 0L);
+ bindingsMap.put("d1", 1.1);
+ bindingsMap.put("d2", 0.0);
+ bindingsMap.put("s1", "true");
+ bindingsMap.put("s2", "false");
+ bindingsMap.put("b1", true);
+ bindingsMap.put("b2", false);
+ Expr.ObjectBinding bindings = InputBindings.withMap(bindingsMap);
+
+ try {
+ ExpressionProcessing.initializeForStrictBooleansTests(true);
+ assertEquals(1L, eval("s1 && s1", bindings).value());
+ assertEquals(0L, eval("s1 && s2", bindings).value());
+ assertEquals(0L, eval("s2 && s1", bindings).value());
+ assertEquals(0L, eval("s2 && s2", bindings).value());
+
+ assertEquals(1L, eval("s1 || s1", bindings).value());
+ assertEquals(1L, eval("s1 || s2", bindings).value());
+ assertEquals(1L, eval("s2 || s1", bindings).value());
+ assertEquals(0L, eval("s2 || s2", bindings).value());
+
+ assertEquals(1L, eval("l1 && l1", bindings).value());
+ assertEquals(0L, eval("l1 && l2", bindings).value());
+ assertEquals(0L, eval("l2 && l1", bindings).value());
+ assertEquals(0L, eval("l2 && l2", bindings).value());
+
+ assertEquals(1L, eval("b1 && b1", bindings).value());
+ assertEquals(0L, eval("b1 && b2", bindings).value());
+ assertEquals(0L, eval("b2 && b1", bindings).value());
+ assertEquals(0L, eval("b2 && b2", bindings).value());
+
+ assertEquals(1L, eval("d1 && d1", bindings).value());
+ assertEquals(0L, eval("d1 && d2", bindings).value());
+ assertEquals(0L, eval("d2 && d1", bindings).value());
+ assertEquals(0L, eval("d2 && d2", bindings).value());
+
+ assertEquals(1L, eval("b1", bindings).value());
+ assertEquals(1L, eval("if(b1,1,0)", bindings).value());
+ assertEquals(1L, eval("if(l1,1,0)", bindings).value());
+ assertEquals(1L, eval("if(d1,1,0)", bindings).value());
+ assertEquals(1L, eval("if(s1,1,0)", bindings).value());
+ assertEquals(0L, eval("if(b2,1,0)", bindings).value());
+ assertEquals(0L, eval("if(l2,1,0)", bindings).value());
+ assertEquals(0L, eval("if(d2,1,0)", bindings).value());
+ assertEquals(0L, eval("if(s2,1,0)", bindings).value());
+ }
+ finally {
+ // reset
+ ExpressionProcessing.initializeForTests(null);
+ }
+
+ try {
+ // turn on legacy insanity mode
+ ExpressionProcessing.initializeForStrictBooleansTests(false);
+
+ assertEquals("true", eval("s1 && s1", bindings).value());
+ assertEquals("false", eval("s1 && s2", bindings).value());
+ assertEquals("false", eval("s2 && s1", bindings).value());
+ assertEquals("false", eval("s2 && s2", bindings).value());
+
+ assertEquals("true", eval("b1 && b1", bindings).value());
+ assertEquals("false", eval("b1 && b2", bindings).value());
+ assertEquals("false", eval("b2 && b1", bindings).value());
+ assertEquals("false", eval("b2 && b2", bindings).value());
+
+ assertEquals(100L, eval("l1 && l1", bindings).value());
+ assertEquals(0L, eval("l1 && l2", bindings).value());
+ assertEquals(0L, eval("l2 && l1", bindings).value());
+ assertEquals(0L, eval("l2 && l2", bindings).value());
+
+ assertEquals(1.1, eval("d1 && d1", bindings).value());
+ assertEquals(0.0, eval("d1 && d2", bindings).value());
+ assertEquals(0.0, eval("d2 && d1", bindings).value());
+ assertEquals(0.0, eval("d2 && d2", bindings).value());
+
+ assertEquals("true", eval("b1", bindings).value());
+ assertEquals(1L, eval("if(b1,1,0)", bindings).value());
+ assertEquals(1L, eval("if(l1,1,0)", bindings).value());
+ assertEquals(1L, eval("if(d1,1,0)", bindings).value());
+ assertEquals(1L, eval("if(s1,1,0)", bindings).value());
+ assertEquals(0L, eval("if(b2,1,0)", bindings).value());
+ assertEquals(0L, eval("if(l2,1,0)", bindings).value());
+ assertEquals(0L, eval("if(d2,1,0)", bindings).value());
+ assertEquals(0L, eval("if(s2,1,0)", bindings).value());
+ }
+ finally {
+ // reset
+ ExpressionProcessing.initializeForTests(null);
+ }
+ }
+
+ @Test
+ public void testEvalOfType()
+ {
+ // strings
+ ExprEval eval = ExprEval.ofType(ExpressionType.STRING, "stringy");
+ Assert.assertEquals(ExpressionType.STRING, eval.type());
+ Assert.assertEquals("stringy", eval.value());
+
+ eval = ExprEval.ofType(ExpressionType.STRING, 1L);
+ Assert.assertEquals(ExpressionType.STRING, eval.type());
+ Assert.assertEquals("1", eval.value());
+
+ eval = ExprEval.ofType(ExpressionType.STRING, 1.0);
+ Assert.assertEquals(ExpressionType.STRING, eval.type());
+ Assert.assertEquals("1.0", eval.value());
+
+ eval = ExprEval.ofType(ExpressionType.STRING, true);
+ Assert.assertEquals(ExpressionType.STRING, eval.type());
+ Assert.assertEquals("true", eval.value());
+
+ // longs
+ eval = ExprEval.ofType(ExpressionType.LONG, 1L);
+ Assert.assertEquals(ExpressionType.LONG, eval.type());
+ Assert.assertEquals(1L, eval.value());
+
+ eval = ExprEval.ofType(ExpressionType.LONG, 1.0);
+ Assert.assertEquals(ExpressionType.LONG, eval.type());
+ Assert.assertEquals(1L, eval.value());
+
+ eval = ExprEval.ofType(ExpressionType.LONG, "1");
+ Assert.assertEquals(ExpressionType.LONG, eval.type());
+ Assert.assertEquals(1L, eval.value());
+
+ eval = ExprEval.ofType(ExpressionType.LONG, true);
+ Assert.assertEquals(ExpressionType.LONG, eval.type());
+ Assert.assertEquals(1L, eval.value());
+
+ // doubles
+ eval = ExprEval.ofType(ExpressionType.DOUBLE, 1L);
+ Assert.assertEquals(ExpressionType.DOUBLE, eval.type());
+ Assert.assertEquals(1.0, eval.value());
+
+ eval = ExprEval.ofType(ExpressionType.DOUBLE, 1.0);
+ Assert.assertEquals(ExpressionType.DOUBLE, eval.type());
+ Assert.assertEquals(1.0, eval.value());
+
+ eval = ExprEval.ofType(ExpressionType.DOUBLE, "1");
+ Assert.assertEquals(ExpressionType.DOUBLE, eval.type());
+ Assert.assertEquals(1.0, eval.value());
+
+ eval = ExprEval.ofType(ExpressionType.DOUBLE, true);
+ Assert.assertEquals(ExpressionType.DOUBLE, eval.type());
+ Assert.assertEquals(1.0, eval.value());
+
+ // complex
+ TypeStrategiesTest.NullableLongPair pair = new
TypeStrategiesTest.NullableLongPair(1L, 2L);
+ ExpressionType type =
ExpressionType.fromColumnType(TypeStrategiesTest.NULLABLE_TEST_PAIR_TYPE);
+
+ eval = ExprEval.ofType(type, pair);
+ Assert.assertEquals(type, eval.type());
+ Assert.assertEquals(pair, eval.value());
+
+ ByteBuffer buffer =
ByteBuffer.allocate(TypeStrategiesTest.NULLABLE_TEST_PAIR_TYPE.getStrategy().estimateSizeBytes(pair));
+ TypeStrategiesTest.NULLABLE_TEST_PAIR_TYPE.getStrategy().write(buffer,
pair, buffer.limit());
+ byte[] pairBytes = buffer.array();
+ eval = ExprEval.ofType(type, pairBytes);
+ Assert.assertEquals(type, eval.type());
+ Assert.assertEquals(pair, eval.value());
+
+ eval = ExprEval.ofType(type, StringUtils.encodeBase64String(pairBytes));
+ Assert.assertEquals(type, eval.type());
+ Assert.assertEquals(pair, eval.value());
+
+ // arrays fall back to using 'bestEffortOf', but cast it to the expected
output type
+ 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());
+
+ 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());
+
+ 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());
+
+ 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());
+
+ // etc
+ 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());
+
+ 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());
+
+ 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());
+
+ 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());
+
+ 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());
+
+ 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());
+
+ 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());
+
+ 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());
+ }
}
diff --git
a/processing/src/test/java/org/apache/druid/query/aggregation/ExpressionLambdaAggregatorFactoryTest.java
b/processing/src/test/java/org/apache/druid/query/aggregation/ExpressionLambdaAggregatorFactoryTest.java
index fe5c206126..499bcef08f 100644
---
a/processing/src/test/java/org/apache/druid/query/aggregation/ExpressionLambdaAggregatorFactoryTest.java
+++
b/processing/src/test/java/org/apache/druid/query/aggregation/ExpressionLambdaAggregatorFactoryTest.java
@@ -254,7 +254,7 @@ public class ExpressionLambdaAggregatorFactoryTest extends
InitializedNullHandli
ImmutableSet.of("x"),
null,
"0",
- "ARRAY<LONG>[]",
+ "ARRAY<STRING>[]",
true,
true,
false,
diff --git
a/processing/src/test/java/org/apache/druid/segment/transform/TransformSpecTest.java
b/processing/src/test/java/org/apache/druid/segment/transform/TransformSpecTest.java
index 3537c4cef8..b9244b3ae1 100644
---
a/processing/src/test/java/org/apache/druid/segment/transform/TransformSpecTest.java
+++
b/processing/src/test/java/org/apache/druid/segment/transform/TransformSpecTest.java
@@ -30,6 +30,7 @@ import org.apache.druid.data.input.impl.MapInputRowParser;
import org.apache.druid.data.input.impl.TimeAndDimsParseSpec;
import org.apache.druid.data.input.impl.TimestampSpec;
import org.apache.druid.java.util.common.DateTimes;
+import org.apache.druid.math.expr.ExpressionProcessing;
import org.apache.druid.query.expression.TestExprMacroTable;
import org.apache.druid.query.filter.AndDimFilter;
import org.apache.druid.query.filter.SelectorDimFilter;
@@ -50,18 +51,20 @@ public class TransformSpecTest extends
InitializedNullHandlingTest
);
private static final Map<String, Object> ROW1 = ImmutableMap.<String,
Object>builder()
- .put("x", "foo")
- .put("y", "bar")
- .put("a", 2.0)
- .put("b", 3L)
- .build();
+ .put("x", "foo")
+ .put("y", "bar")
+ .put("a", 2.0)
+ .put("b", 3L)
+ .put("bool",
true)
+ .build();
private static final Map<String, Object> ROW2 = ImmutableMap.<String,
Object>builder()
- .put("x", "foo")
- .put("y", "baz")
- .put("a", 2.0)
- .put("b", 4L)
- .build();
+ .put("x", "foo")
+ .put("y", "baz")
+ .put("a", 2.0)
+ .put("b", 4L)
+ .put("bool",
false)
+ .build();
@Test
public void testTransforms()
@@ -202,6 +205,73 @@ public class TransformSpecTest extends
InitializedNullHandlingTest
Assert.assertEquals(DateTimes.of("2000-01-01T01:00:00Z").getMillis(),
row.getTimestampFromEpoch());
}
+ @Test
+ public void testBoolTransforms()
+ {
+ try {
+ ExpressionProcessing.initializeForStrictBooleansTests(true);
+ final TransformSpec transformSpec = new TransformSpec(
+ null,
+ ImmutableList.of(
+ new ExpressionTransform("truthy1", "bool",
TestExprMacroTable.INSTANCE),
+ new ExpressionTransform("truthy2", "if(bool,1,0)",
TestExprMacroTable.INSTANCE)
+ )
+ );
+
+ Assert.assertEquals(
+ ImmutableSet.of("bool"),
+ transformSpec.getRequiredColumns()
+ );
+
+ final InputRowParser<Map<String, Object>> parser =
transformSpec.decorate(PARSER);
+ final InputRow row = parser.parseBatch(ROW1).get(0);
+
+ Assert.assertNotNull(row);
+ Assert.assertEquals(1L, row.getRaw("truthy1"));
+ Assert.assertEquals(1L, row.getRaw("truthy2"));
+
+ final InputRow row2 = parser.parseBatch(ROW2).get(0);
+
+ Assert.assertNotNull(row2);
+ Assert.assertEquals(0L, row2.getRaw("truthy1"));
+ Assert.assertEquals(0L, row2.getRaw("truthy2"));
+ }
+ finally {
+ ExpressionProcessing.initializeForTests(null);
+ }
+ try {
+ ExpressionProcessing.initializeForStrictBooleansTests(false);
+ final TransformSpec transformSpec = new TransformSpec(
+ null,
+ ImmutableList.of(
+ new ExpressionTransform("truthy1", "bool",
TestExprMacroTable.INSTANCE),
+ new ExpressionTransform("truthy2", "if(bool,1,0)",
TestExprMacroTable.INSTANCE)
+ )
+ );
+
+ Assert.assertEquals(
+ ImmutableSet.of("bool"),
+ transformSpec.getRequiredColumns()
+ );
+
+ final InputRowParser<Map<String, Object>> parser =
transformSpec.decorate(PARSER);
+ final InputRow row = parser.parseBatch(ROW1).get(0);
+
+ Assert.assertNotNull(row);
+ Assert.assertEquals("true", row.getRaw("truthy1"));
+ Assert.assertEquals(1L, row.getRaw("truthy2"));
+
+ final InputRow row2 = parser.parseBatch(ROW2).get(0);
+
+ Assert.assertNotNull(row2);
+ Assert.assertEquals("false", row2.getRaw("truthy1"));
+ Assert.assertEquals(0L, row2.getRaw("truthy2"));
+ }
+ finally {
+ ExpressionProcessing.initializeForTests(null);
+ }
+ }
+
@Test
public void testSerde() throws Exception
{
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]