in pinot-common/src/main/java/org/apache/pinot/common/request/context/RequestContextUtils.java [295:424]
public static FilterContext getFilter(FunctionContext filterFunction) {
String functionOperator = filterFunction.getFunctionName().toUpperCase();
// convert "WHERE startsWith(col, 'str')" to "WHERE startsWith(col, 'str') = true"
if (!EnumUtils.isValidEnum(FilterKind.class, functionOperator)) {
return FilterContext.forPredicate(new EqPredicate(ExpressionContext.forFunction(filterFunction), "true"));
}
FilterKind filterKind = FilterKind.valueOf(filterFunction.getFunctionName().toUpperCase());
List<ExpressionContext> operands = filterFunction.getArguments();
int numOperands = operands.size();
switch (filterKind) {
case AND: {
List<FilterContext> children = new ArrayList<>(numOperands);
for (ExpressionContext operand : operands) {
FilterContext filter = getFilter(operand);
if (!filter.isConstant()) {
children.add(filter);
} else {
if (filter.isConstantFalse()) {
return FilterContext.CONSTANT_FALSE;
}
}
}
int numChildren = children.size();
if (numChildren == 0) {
return FilterContext.CONSTANT_TRUE;
} else if (numChildren == 1) {
return children.get(0);
} else {
return FilterContext.forAnd(children);
}
}
case OR: {
List<FilterContext> children = new ArrayList<>(numOperands);
for (ExpressionContext operand : operands) {
FilterContext filter = getFilter(operand);
if (!filter.isConstant()) {
children.add(filter);
} else {
if (filter.isConstantTrue()) {
return FilterContext.CONSTANT_TRUE;
}
}
}
int numChildren = children.size();
if (numChildren == 0) {
return FilterContext.CONSTANT_FALSE;
} else if (numChildren == 1) {
return children.get(0);
} else {
return FilterContext.forOr(children);
}
}
case NOT: {
assert numOperands == 1;
FilterContext filter = getFilter(operands.get(0));
if (!filter.isConstant()) {
return FilterContext.forNot(filter);
} else {
return filter.isConstantTrue() ? FilterContext.CONSTANT_FALSE : FilterContext.CONSTANT_TRUE;
}
}
case EQUALS:
return FilterContext.forPredicate(new EqPredicate(operands.get(0), getStringValue(operands.get(1))));
case NOT_EQUALS:
return FilterContext.forPredicate(new NotEqPredicate(operands.get(0), getStringValue(operands.get(1))));
case IN: {
List<String> values = new ArrayList<>(numOperands - 1);
for (int i = 1; i < numOperands; i++) {
values.add(getStringValue(operands.get(i)));
}
return FilterContext.forPredicate(new InPredicate(operands.get(0), values));
}
case NOT_IN: {
List<String> values = new ArrayList<>(numOperands - 1);
for (int i = 1; i < numOperands; i++) {
values.add(getStringValue(operands.get(i)));
}
return FilterContext.forPredicate(new NotInPredicate(operands.get(0), values));
}
case GREATER_THAN:
return FilterContext.forPredicate(
new RangePredicate(operands.get(0), false, getStringValue(operands.get(1)), false, RangePredicate.UNBOUNDED,
operands.get(1).getLiteral().getType()));
case GREATER_THAN_OR_EQUAL:
return FilterContext.forPredicate(
new RangePredicate(operands.get(0), true, getStringValue(operands.get(1)), false, RangePredicate.UNBOUNDED,
operands.get(1).getLiteral().getType()));
case LESS_THAN:
return FilterContext.forPredicate(
new RangePredicate(operands.get(0), false, RangePredicate.UNBOUNDED, false, getStringValue(operands.get(1)),
operands.get(1).getLiteral().getType()));
case LESS_THAN_OR_EQUAL:
return FilterContext.forPredicate(
new RangePredicate(operands.get(0), false, RangePredicate.UNBOUNDED, true, getStringValue(operands.get(1)),
operands.get(1).getLiteral().getType()));
case BETWEEN:
return FilterContext.forPredicate(
new RangePredicate(operands.get(0), true, getStringValue(operands.get(1)), true,
getStringValue(operands.get(2)), operands.get(1).getLiteral().getType()));
case RANGE:
return FilterContext.forPredicate(new RangePredicate(operands.get(0), getStringValue(operands.get(1))));
case REGEXP_LIKE:
return FilterContext.forPredicate(new RegexpLikePredicate(operands.get(0), getStringValue(operands.get(1))));
case LIKE:
return FilterContext.forPredicate(new RegexpLikePredicate(operands.get(0),
RegexpPatternConverterUtils.likeToRegexpLike(getStringValue(operands.get(1)))));
case TEXT_CONTAINS:
return FilterContext.forPredicate(new TextContainsPredicate(operands.get(0), getStringValue(operands.get(1))));
case TEXT_MATCH:
return FilterContext.forPredicate(new TextMatchPredicate(operands.get(0), getStringValue(operands.get(1))));
case JSON_MATCH:
return FilterContext.forPredicate(new JsonMatchPredicate(operands.get(0), getStringValue(operands.get(1)),
operands.size() == 3?getStringValue(operands.get(2)): null));
case VECTOR_SIMILARITY:
int topK = VectorSimilarityPredicate.DEFAULT_TOP_K;
if (operands.size() == 3) {
topK = (int) operands.get(2).getLiteral().getLongValue();
}
return FilterContext.forPredicate(
new VectorSimilarityPredicate(operands.get(0), getVectorValue(operands.get(1)), topK));
case IS_NULL:
return FilterContext.forPredicate(new IsNullPredicate(operands.get(0)));
case IS_NOT_NULL:
return FilterContext.forPredicate(new IsNotNullPredicate(operands.get(0)));
default:
throw new IllegalStateException();
}
}