in common/src/main/java/org/apache/drill/common/Typifier.java [163:309]
public static Entry<Class, String> typify(String data,
boolean bool01,
boolean commonTypes,
boolean postfixFL,
boolean parseDates) {
// -2. if the input data has 0 length, return as null object
if (data == null || data.length() == 0) {
return new SimpleEntry<>(Object.class, null);
}
String s = data.trim();
int slen = s.length();
// -1. if the input data is only whitespace, return "String" and input as-is
if (slen == 0) {
return new SimpleEntry<>(String.class, data);
}
// In most data, numerical values are more common than true/false values. So,
// if we want to speed up data parsing, we can move this block to the end when
// looking only for common types.
/// Check if the data is Boolean (true or false)
if (!commonTypes) {
if (contains(falseAliases, s)) {
return new SimpleEntry<>(Boolean.class, "false");
} else if (contains(trueAliases, s)) {
return new SimpleEntry<>(Boolean.class, "true");
}
}
// Check for any String-only characters; if we find them, don't bother trying to parse this as a number
if (!containsAny(s, StringCharacters)) {
// try again for boolean -- need to make sure it's not parsed as Byte
if (bool01) {
if (s.equals("0")) {
return new SimpleEntry<>(Boolean.class, "false");
} else if (s.equals("1")) {
return new SimpleEntry<>(Boolean.class, "true");
}
}
char lastChar = s.charAt(slen - 1);
boolean lastCharF = (lastChar == 'f' || lastChar == 'F');
boolean lastCharL = (lastChar == 'l' || lastChar == 'L');
// If we're not restricted to common types, look for anything
if (!commonTypes) {
// 1. Check if data is a Byte (1-byte integer with range [-(2e7) = -128, ((2e7)-1) = 127])
try {
byte b = Byte.parseByte(s);
return new SimpleEntry<>(Byte.class, Byte.toString(b));
} catch (NumberFormatException ex) {
// Okay, guess it's not a Byte
}
// 2. Check if data is a Short (2-byte integer with range [-(2e15) = -32768, ((2e15)-1) = 32767])
try {
short h = Short.parseShort(s);
return new SimpleEntry<>(Short.class, Short.toString(h));
} catch (NumberFormatException ex) {
// Okay, guess it's not a Short
}
// 3. Check if data is an Integer (4-byte integer with range [-(2e31), (2e31)-1])
try {
int i = Integer.parseInt(s);
return new SimpleEntry<>(Integer.class, Integer.toString(i));
} catch (NumberFormatException ex) {
// okay, guess it's not an Integer
}
String s_L_trimmed = s;
// 4. Check if data is a Long (8-byte integer with range [-(2e63), (2e63)-1])
// ...first, see if the last character of the string is "L" or "l"
// ... Java parses "3.3F", etc. fine as a float, but throws an error with "3L", etc.
if (postfixFL && slen > 1 && lastCharL) {
s_L_trimmed = s.substring(0, slen - 1);
}
try {
long l = Long.parseLong(s_L_trimmed);
return new SimpleEntry<>(Long.class, Long.toString(l));
} catch (NumberFormatException ex) {
// okay, guess it's not a Long
}
// 5. Check if data is a Float (32-bit IEEE 754 floating point with approximate extents +/- 3.4028235e38)
if (postfixFL || !lastCharF) {
try {
float f = Float.parseFloat(s);
// If it's beyond the range of Float, maybe it's not beyond the range of Double
if (!Float.isInfinite(f)) {
return new SimpleEntry<>(Float.class, Float.toString(f));
}
} catch (NumberFormatException ex) {
// okay, guess it's not a Float
}
}
}
// 6. Check if data is a Double (64-bit IEEE 754 floating point with approximate extents +/- 1.797693134862315e308 )
if (postfixFL || !lastCharF) {
try {
double d = Double.parseDouble(s);
if (!Double.isInfinite(d)) {
return new SimpleEntry<>(Double.class, Double.toString(d));
} else {
return new SimpleEntry<>(String.class, s);
}
} catch (NumberFormatException ex) {
// okay, guess it's not a Double
}
}
}
// Check for either Boolean or String
if (commonTypes) {
if (contains(falseAliases, s)) {
return new SimpleEntry<>(Boolean.class, "false");
} else if (contains(trueAliases, s)) {
return new SimpleEntry<>(Boolean.class, "true");
}
}
// 7. revert to String by default, with caveats...
// 7a. if string has length 1, it is a single character
if (!commonTypes && slen == 1) {
return new SimpleEntry<>(Character.class, s); // end uncommon types 2/2
}
// 7b. attempt to parse String as a LocalDateTime
if (parseDates && stringAsDateTime(s) != null) {
return new SimpleEntry<>(LocalDateTime.class, s);
}
// 7c. Attempt to parse the String as a LocalDate
if (parseDates && stringAsDate(s) != null) {
return new SimpleEntry<>(LocalDate.class, s);
}
// ...if we've made it all the way to here without returning, give up and return "String" and input as-is
return new SimpleEntry<>(String.class, data);
}