in exec/java-exec/src/main/java/org/apache/drill/exec/store/ischema/InfoSchemaFilter.java [177:309]
private Result evaluateHelperFunction(
Map<String, String> recordValues,
boolean prefixMatchesInconclusive,
FunctionExprNode exprNode
) {
switch (exprNode.function) {
case FunctionNames.LIKE: {
FieldExprNode col = (FieldExprNode) exprNode.args.get(0);
ConstantExprNode pattern = (ConstantExprNode) exprNode.args.get(1);
ConstantExprNode escape = exprNode.args.size() > 2 ? (ConstantExprNode) exprNode.args.get(2) : null;
final String fieldValue = recordValues.get(col.field);
if (fieldValue == null) {
return Result.INCONCLUSIVE;
}
RegexpUtil.SqlPatternInfo spi = escape == null
? sqlToRegexLike(pattern.value)
: sqlToRegexLike(pattern.value, escape.value);
if (Pattern.matches(spi.getJavaPatternString(), fieldValue)) {
// E.g. pattern = 'dfs.%', schema path = 'dfs.tmp'.
// The entire schema path matches.
return Result.TRUE;
}
if (!prefixMatchesInconclusive) {
// E.g. pattern = 'dfs.%', schema path = 'dfs'.
// There may be prefix match but prefixMatchesInconclusive is false.
return Result.FALSE;
}
if ((spi.getPatternType() == SqlPatternType.STARTS_WITH || spi.getPatternType() == SqlPatternType.CONSTANT) &&
!spi.getSimplePatternString().startsWith(fieldValue)) {
// E.g. pattern = 'dfs.%', schema path = 'cp'.
// No match, not even to a prefix.
return Result.FALSE;
}
// E.g. pattern = 'dfs.%', schema path = 'dfs'.
// A prefix matches
return Result.INCONCLUSIVE;
}
case FunctionNames.EQ:
case "not equal": // TODO: Is this name correct?
case "notequal": // TODO: Is this name correct?
case FunctionNames.NE: {
FieldExprNode col = (FieldExprNode) exprNode.args.get(0);
ConstantExprNode arg = (ConstantExprNode) exprNode.args.get(1);
final String value = recordValues.get(col.field);
if (Strings.isNullOrEmpty(value)) {
return Result.INCONCLUSIVE;
}
boolean prefixMatch = arg.value.startsWith(value);
boolean exactMatch = prefixMatch && arg.value.equals(value);
if (exprNode.function.equals(FunctionNames.EQ)) {
// Equality case
if (exactMatch) {
return Result.TRUE;
} else {
return prefixMatchesInconclusive && prefixMatch ? Result.INCONCLUSIVE: Result.FALSE;
}
} else {
// Inequality case
if (exactMatch) {
return Result.FALSE;
} else {
return prefixMatchesInconclusive && prefixMatch ? Result.INCONCLUSIVE : Result.TRUE;
}
}
}
case FunctionNames.OR:
case "booleanor": { // TODO: Is this name correct?
// If at least one arg returns TRUE, then the OR function value is TRUE
// If all args return FALSE, then OR function value is FALSE
// For all other cases, return INCONCLUSIVE
Result result = Result.FALSE;
for(ExprNode arg : exprNode.args) {
Result exprResult = evaluateHelper(recordValues, prefixMatchesInconclusive, arg);
if (exprResult == Result.TRUE) {
return Result.TRUE;
} else if (exprResult == Result.INCONCLUSIVE) {
result = Result.INCONCLUSIVE;
}
}
return result;
}
case FunctionNames.AND:
case "booleanand": { // TODO: Is this name correct?
// If at least one arg returns FALSE, then the AND function value is FALSE
// If at least one arg returns INCONCLUSIVE, then the AND function value is INCONCLUSIVE
// If all args return TRUE, then the AND function value is TRUE
Result result = Result.TRUE;
for(ExprNode arg : exprNode.args) {
Result exprResult = evaluateHelper(recordValues, prefixMatchesInconclusive, arg);
if (exprResult == Result.FALSE) {
return exprResult;
}
if (exprResult == Result.INCONCLUSIVE) {
result = Result.INCONCLUSIVE;
}
}
return result;
}
case "in": {
// This case will probably only ever run if the user submits a manually
// crafted plan because the IN operator is compiled either to a chain
// of boolean ORs, or to a hash join with a relation which uses VALUES
// to generate the list of constants provided to the IN operator in
// the query. See the planner.in_subquery_threshold option.
FieldExprNode col = (FieldExprNode) exprNode.args.get(0);
List<ExprNode> args = exprNode.args.subList(1, exprNode.args.size());
final String fieldValue = recordValues.get(col.field);
if (fieldValue != null) {
for(ExprNode arg: args) {
if (fieldValue.equals(((ConstantExprNode) arg).value)) {
return Result.TRUE;
}
}
return Result.FALSE;
}
return Result.INCONCLUSIVE;
}
}
throw new UnsupportedOperationException(
String.format("Unknown function '%s' in InfoSchemaFilter", exprNode.function));
}