prestodb/presto · warning · PrestoException

CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION

CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION

Error message

 is not supported in ClickHouse filter

What it means

ClickHouseFilterExpressionConverter.handleLogicalBinary() only supports logical binary operators in LOGICAL_BINARY_OPS_FILTER (AND/OR). When the converter visits a logical binary CallExpression with an operator outside that set, it throws CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION telling the optimizer this filter cannot be translated to ClickHouse SQL.

Source

Thrown at presto-clickhouse/src/main/java/com/facebook/presto/plugin/clickhouse/optimization/ClickHouseFilterExpressionConverter.java:90

            SpecialFormExpression specialForm,
            boolean isWhitelist,
            Function<VariableReferenceExpression, Selection> context)
    {
        return derived(format("(%s %s (%s))",
                specialForm.getArguments().get(0).accept(this, context).getDefinition(),
                isWhitelist ? "IN" : "NOT IN",
                specialForm.getArguments().subList(1, specialForm.getArguments().size()).stream()
                        .map(argument -> argument.accept(this, context).getDefinition())
                        .collect(Collectors.joining(", "))));
    }

    private ClickHouseColumnExpression handleLogicalBinary(
            String operator,
            CallExpression call,
            Function<VariableReferenceExpression, Selection> context)
    {
        if (!LOGICAL_BINARY_OPS_FILTER.contains(operator)) {
            throw new PrestoException(CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION, operator + " is not supported in ClickHouse filter");
        }
        List<RowExpression> arguments = call.getArguments();
        if (arguments.size() == 2) {
            return derived(format(
                    "(%s %s %s)",
                    arguments.get(0).accept(this, context).getDefinition(),
                    operator,
                    arguments.get(1).accept(this, context).getDefinition()));
        }
        throw new PrestoException(CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION, "Unknown logical binary: " + call);
    }

    private ClickHouseColumnExpression handleBetween(
            CallExpression between,
            Function<VariableReferenceExpression, Selection> context)
    {
        if (between.getArguments().size() == 3) {
            RowExpression value = between.getArguments().get(0);

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Rewrite the filter using AND/OR (e.g. XOR(a,b) → (a OR b) AND NOT (a AND b))
  2. Restructure the query so the unsupported logical expression is computed after the pushed-down filter (e.g. in an outer query)
  3. Disable filter pushdown for this catalog/query so the predicate is evaluated locally
  4. Upgrade the connector for a wider supported-operator set

Example fix

// before
SELECT * FROM ch.db.t WHERE a XOR b;
// after
SELECT * FROM ch.db.t WHERE (a OR b) AND NOT (a AND b);
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-check filter operators before pushdown
Set<String> supportedLogicalOps = Set.of("AND", "OR");
if (isLogicalBinary(call) && !supportedLogicalOps.contains(operatorOf(call).toUpperCase())) {
    log.info("Operator " + operatorOf(call) + " not pushable to ClickHouse; will evaluate locally");
}

Type guard

boolean isClickHousePushableLogicalOp(String operator) {
    return Set.of("AND", "OR").contains(operator.toUpperCase(Locale.ENGLISH));
}

Try / catch

try {
    return expressionConverter.convert(filter);
} catch (PrestoException e) {
    if (e.getErrorCode().getCode() == CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION.toErrorCode().getCode()) {
        return Optional.empty(); // leave the filter unpushed; evaluate locally
    }
    throw e;
}

Prevention

When it happens

Trigger: A WHERE clause containing a logical binary expression not in the supported set (e.g. XOR, or an unexpected logical function) that the optimizer attempts to push down to ClickHouse.

Common situations: Queries using XOR or exotic logical functions in filters; planner rewriting expressions into logical calls the converter does not recognize; complex boolean filters produced by view expansion.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/0770b1cb29b05164. Report an issue: GitHub.