prestodb/presto · error · PrestoException

CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION

CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION

Error message

ClickHouse does not support lambda: 

What it means

ClickHouseProjectExpressionConverter.visitLambda unconditionally throws CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION because lambda expressions (LambdaDefinitionExpression, e.g. from higher-order functions like filter, transform, all_match) cannot be translated into ClickHouse SQL by this connector. Any projection containing a lambda is therefore not pushable.

Source

Thrown at presto-clickhouse/src/main/java/com/facebook/presto/plugin/clickhouse/optimization/ClickHouseProjectExpressionConverter.java:75

        this.typeManager = requireNonNull(typeManager, "type manager");
        this.standardFunctionResolution = requireNonNull(standardFunctionResolution, "standardFunctionResolution is null");
    }

    @Override
    public ClickHouseColumnExpression visitVariableReference(
            VariableReferenceExpression reference,
            Map<VariableReferenceExpression, Selection> context)
    {
        Selection input = requireNonNull(context.get(reference), format("Input column %s does not exist in the input", reference));
        return new ClickHouseColumnExpression(input.getDefinition(), input.getOrigin());
    }

    @Override
    public ClickHouseColumnExpression visitLambda(
            LambdaDefinitionExpression lambda,
            Map<VariableReferenceExpression, Selection> context)
    {
        throw new PrestoException(CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION, "ClickHouse does not support lambda: " + lambda);
    }

    protected boolean isImplicitCast(Type inputType, Type resultType)
    {
        if (typeManager.canCoerce(inputType, resultType)) {
            return true;
        }
        return resultType.getTypeSignature().getBase().equals(TIMESTAMP) && TIME_EQUIVALENT_TYPES.contains(inputType.getTypeSignature().getBase());
    }

    private ClickHouseColumnExpression handleCast(
            CallExpression cast,
            Map<VariableReferenceExpression, Selection> context)
    {
        if (cast.getArguments().size() == 1) {
            RowExpression input = cast.getArguments().get(0);
            Type expectedType = cast.getType();
            if (isImplicitCast(input.getType(), expectedType)) {

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Rewrite the query so higher-order/lambda expressions are computed outside the pushed-down projection (inner query returning raw columns, lambda applied in an outer Presto-side step)
  2. Avoid higher-order functions over ClickHouse columns; use plain scalar functions that the connector supports
  3. Materialize the lambda result as a stored ClickHouse column instead of computing it at query time

Example fix

// before (lambda pushed down)
SELECT transform(tags, x -> upper(x)) AS t FROM ch_events;
// after (lambda applied outside pushdown)
SELECT transform(tags, x -> upper(x)) AS t FROM (SELECT tags FROM ch_events) -- conversion restricted to inner projection
Defensive patterns

Strategy: validation

Validate before calling

// Java-side check before relying on pushdown
boolean containsLambda(RowExpression expr) {
    if (expr instanceof LambdaDefinitionExpression) return true;
    for (RowExpression arg : ((CallExpression) expr).getArguments()) {
        if (containsLambda(arg)) return true;
    }
    return false;
}

Type guard

boolean isLambda(RowExpression e) { return e instanceof LambdaDefinitionExpression; }

Try / catch

try {
    return projectConverter.convert(expression);
} catch (PrestoException e) {
    if (e.getErrorCode() == CLICKHOUSE_PUSHDOWN_UNSUPPORTED_EXPRESSION.toErrorCode()) {
        return Optional.empty(); // evaluate without pushdown
    }
    throw e;
}

Prevention

When it happens

Trigger: A projection (SELECT list) or computed expression pushed to ClickHouse that contains a higher-order function producing a LambdaDefinitionExpression, e.g. transform(arr, x -> x + 1) or filter(a, x -> x > 0).

Common situations: Users SELECTing array/map higher-order function results directly from a ClickHouse table in a query that also tries to push down projections; commonly hit with ARRAY/ MAP typed columns.

Related errors


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