SQL: Fix string to boolean conversion (elastic/x-pack-elasticsearch#2728)

This commit also adds tests for conversion to boolean

Original commit: elastic/x-pack-elasticsearch@d7740929a2
This commit is contained in:
Igor Motov 2017-10-11 19:56:36 -04:00 committed by GitHub
parent 06b4c043b9
commit 7f0c44f138
2 changed files with 55 additions and 1 deletions

View File

@ -10,6 +10,7 @@ import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat; import org.joda.time.format.ISODateTimeFormat;
import java.util.Locale;
import java.util.function.DoubleFunction; import java.util.function.DoubleFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.LongFunction; import java.util.function.LongFunction;
@ -292,6 +293,13 @@ public abstract class DataTypeConversion {
return Math.round(x); return Math.round(x);
} }
public static boolean convertToBoolean(String val) {
String lowVal = val.toLowerCase(Locale.ROOT);
if (Booleans.isBoolean(lowVal) == false) {
throw new SqlIllegalArgumentException("cannot cast [" + val + "] to [Boolean]");
}
return Booleans.parseBoolean(lowVal);
}
public static Object convert(Object value, DataType dataType) { public static Object convert(Object value, DataType dataType) {
DataType detectedType = DataTypes.fromJava(value); DataType detectedType = DataTypes.fromJava(value);
if (detectedType.equals(dataType)) { if (detectedType.equals(dataType)) {
@ -333,7 +341,7 @@ public abstract class DataTypeConversion {
STRING_TO_DOUBLE(fromString(Double::valueOf, "Double")), STRING_TO_DOUBLE(fromString(Double::valueOf, "Double")),
STRING_TO_DATE(fromString(UTC_DATE_FORMATTER::parseMillis, "Date")), STRING_TO_DATE(fromString(UTC_DATE_FORMATTER::parseMillis, "Date")),
NUMERIC_TO_BOOLEAN(fromLong(value -> value != 0)), NUMERIC_TO_BOOLEAN(fromLong(value -> value != 0)),
STRING_TO_BOOLEAN(fromString(Booleans::isBoolean, "Boolean")), // NOCOMMIT probably wrong STRING_TO_BOOLEAN(fromString(DataTypeConversion::convertToBoolean, "Boolean")),
; ;
private final Function<Object, Object> converter; private final Function<Object, Object> converter;

View File

@ -93,4 +93,50 @@ public class DataTypeConversionTests extends ESTestCase {
assertEquals("cannot cast [0xff] to [Double]", e.getMessage()); assertEquals("cannot cast [0xff] to [Double]", e.getMessage());
} }
} }
public void testConversionToBoolean() {
{
Conversion conversion = DataTypeConversion.conversionFor(new FloatType(true), new BooleanType(true));
assertNull(conversion.convert(null));
assertEquals(true, conversion.convert(10.0f));
assertEquals(true, conversion.convert(-10.0f));
assertEquals(false, conversion.convert(0.0f));
}
{
Conversion conversion = DataTypeConversion.conversionFor(new IntegerType(true), new BooleanType(true));
assertNull(conversion.convert(null));
assertEquals(true, conversion.convert(10));
assertEquals(true, conversion.convert(-10));
assertEquals(false, conversion.convert(0));
}
{
Conversion conversion = DataTypeConversion.conversionFor(new DoubleType(true), new BooleanType(true));
assertNull(conversion.convert(null));
assertEquals(true, conversion.convert(10.0));
assertEquals(true, conversion.convert(-10.0));
assertEquals(false, conversion.convert(0.0));
}
{
Conversion conversion = DataTypeConversion.conversionFor(KeywordType.DEFAULT, new BooleanType(true));
assertNull(conversion.convert(null));
// We only handled upper and lower case true and false
assertEquals(true, conversion.convert("true"));
assertEquals(false, conversion.convert("false"));
assertEquals(true, conversion.convert("True"));
assertEquals(false, conversion.convert("fAlSe"));
// Everything else should fail
Exception e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert("10"));
assertEquals("cannot cast [10] to [Boolean]", e.getMessage());
e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert("-1"));
assertEquals("cannot cast [-1] to [Boolean]", e.getMessage());
e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert("0"));
assertEquals("cannot cast [0] to [Boolean]", e.getMessage());
e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert("blah"));
assertEquals("cannot cast [blah] to [Boolean]", e.getMessage());
e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert("Yes"));
assertEquals("cannot cast [Yes] to [Boolean]", e.getMessage());
e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert("nO"));
assertEquals("cannot cast [nO] to [Boolean]", e.getMessage());
}
}
} }