prestodb/presto · error · PinotException
PINOT_UNSUPPORTED_EXPRESSION
PINOT_UNSUPPORTED_EXPRESSION
Error message
'%s' is not supported in filter
What it means
PinotFilterExpressionConverter.handleLogicalBinary translates logical operators in WHERE clauses to Pinot filter syntax. Only operators in LOGICAL_BINARY_OPS_FILTER (AND/OR family) are pushable; any other logical binary operator reaching this method is rejected with ''%s' is not supported in filter'.
Source
Thrown at presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/query/PinotFilterExpressionConverter.java:109
}
private PinotExpression handleIsNull(
SpecialFormExpression specialForm,
boolean isWhitelist,
Function<VariableReferenceExpression, Selection> context)
{
return derived(format("(%s %s)",
specialForm.getArguments().get(0).accept(this, context).getDefinition(),
isWhitelist ? "IS NULL" : "IS NOT NULL"));
}
private PinotExpression handleLogicalBinary(
String operator,
CallExpression call,
Function<VariableReferenceExpression, Selection> context)
{
if (!LOGICAL_BINARY_OPS_FILTER.contains(operator)) {
throw new PinotException(PINOT_UNSUPPORTED_EXPRESSION, Optional.empty(), format("'%s' is not supported in filter", operator));
}
List<RowExpression> arguments = call.getArguments();
if (arguments.size() == 2) {
// Check if call compares a date/time column with a date/time constant. Otherwise just treat it like a regular binary operator.
return handleDateOrTimestampBinaryExpression(operator, arguments, context).orElseGet(
() -> derived(format(
"(%s %s %s)",
arguments.get(0).accept(this, context).getDefinition(),
operator,
arguments.get(1).accept(this, context).getDefinition())));
}
throw new PinotException(PINOT_UNSUPPORTED_EXPRESSION, Optional.empty(), format("Unknown logical binary: '%s'", call));
}
private Optional<PinotExpression> handleDateOrTimestampBinaryExpression(String operator, List<RowExpression> arguments, Function<VariableReferenceExpression, Selection> context)
{
Optional<String> left = handleTimeValueCast(context, arguments.get(1), arguments.get(0));
Optional<String> right = handleTimeValueCast(context, arguments.get(0), arguments.get(1));View on GitHub (pinned to 55bb57d202)
Solutions
- Rewrite the predicate using AND/OR/NOT: XOR(a, b) becomes (a AND NOT b) OR (NOT a AND b)
- Split the query so unsupported boolean logic is applied outside the Pinot-pushed filter (outer query over a subquery)
- Inspect LOGICAL_BINARY_OPS_FILTER in your connector version and restrict queries to those operators
- Upgrade the connector if newer versions added the operator to the filter allowlist
Example fix
// before SELECT * FROM t WHERE a XOR b; // after SELECT * FROM t WHERE (a AND NOT b) OR (NOT a AND b);
Defensive patterns
Strategy: validation
Validate before calling
// Check WHERE-clause logical operators against the connector allowlist
private static final Set<String> FILTER_LOGICAL_OPS = Set.of("AND", "OR");
if (!FILTER_LOGICAL_OPS.contains(op.toUpperCase(Locale.ROOT))) {
throw new IllegalArgumentException(
"Logical operator not pushable to Pinot filter: " + op);
} Type guard
private static boolean isFilterPushableLogical(String operator) {
return operator != null
&& Set.of("AND", "OR").contains(operator.toUpperCase(Locale.ROOT));
} Try / catch
try {
PinotExpression filter = filterConverter.visitCall(call, context);
} catch (PinotException ex) {
if (ex.getMessage() != null && ex.getMessage().endsWith("is not supported in filter")) {
// keep this predicate for Presto-side filtering
} else throw ex;
} Prevention
- Restrict WHERE clauses to AND/OR; express XOR and exotic boolean logic manually
- Put unsupported boolean expressions in an outer query over a Pinot subquery
- Review LOGICAL_BINARY_OPS_FILTER in your connector version before using new operators
- Favor simple conjunctive/disjunctive filter forms for best pushdown coverage
When it happens
Trigger: A CallExpression in a filter (WHERE/HAVING) resolves to a logical binary function not in LOGICAL_BINARY_OPS_FILTER — e.g. XOR, or a non-standard logical function the planner represents as a call with operator name outside the allowlist.
Common situations: Queries using XOR or exotic boolean operators in WHERE clauses, new Presto versions introducing different function names for logical ops, and third-party SQL generators emitting logical operators the connector allowlist does not cover.
Related errors
- CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION
- DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION
- PINOT_UNSUPPORTED_EXPRESSION
- PINOT_UNSUPPORTED_EXPRESSION
- PINOT_UNSUPPORTED_EXPRESSION
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/259cdf39ace91436.
Report an issue: GitHub.