{"record":{"id":"223e72841f5e5238","repo":"prestodb/presto","slug":"pinot-unsupported-expression-223e72","errorCode":"PINOT_UNSUPPORTED_EXPRESSION","errorMessage":"Pinot does not support lambda ","messagePattern":"Pinot does not support lambda ","errorType":"error_code","errorClass":"PinotException","httpStatus":null,"severity":"error","filePath":"presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/query/PinotProjectExpressionConverter.java","lineNumber":94,"sourceCode":"        this.standardFunctionResolution = requireNonNull(standardFunctionResolution, \"standardFunctionResolution is null\");\n        this.session = requireNonNull(session, \"session is null\");\n    }\n\n    @Override\n    public PinotExpression visitVariableReference(\n            VariableReferenceExpression reference,\n            Map<VariableReferenceExpression, Selection> context)\n    {\n        Selection input = requireNonNull(context.get(reference), format(\"Input column %s does not exist in the input\", reference));\n        return new PinotExpression(input.getDefinition(), input.getOrigin());\n    }\n\n    @Override\n    public PinotExpression visitLambda(\n            LambdaDefinitionExpression lambda,\n            Map<VariableReferenceExpression, Selection> context)\n    {\n        throw new PinotException(PINOT_UNSUPPORTED_EXPRESSION, Optional.empty(), \"Pinot does not support lambda \" + lambda);\n    }\n\n    protected boolean isImplicitCast(Type inputType, Type resultType)\n    {\n        if (typeManager.canCoerce(inputType, resultType)) {\n            return true;\n        }\n        return resultType.getTypeSignature().getBase().equals(StandardTypes.TIMESTAMP) && TIME_EQUIVALENT_TYPES.contains(inputType.getTypeSignature().getBase());\n    }\n    protected PinotExpression handleArithmeticExpression(\n            CallExpression expression,\n            OperatorType operatorType,\n            Map<VariableReferenceExpression, PinotQueryGeneratorContext.Selection> context)\n    {\n        List<RowExpression> arguments = expression.getArguments();\n        if (arguments.size() == 2) {\n            PinotExpression left = arguments.get(0).accept(this, context);\n            PinotExpression right = arguments.get(1).accept(this, context);","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/query/PinotProjectExpressionConverter.java#L76-L112","documentation":"PinotProjectExpressionConverter.visitLambda unconditionally throws PINOT_UNSUPPORTED_EXPRESSION because Pinot's query language has no lambda expression support. Any projected expression containing a LambdaDefinitionExpression (e.g. from higher-order functions like filter, transform, any_match) cannot be translated and pushdown of that projection fails.","triggerScenarios":"A SELECT (or filter/project expression being pushed down) contains a higher-order function that the Presto planner represents as a LambdaDefinitionExpression, e.g. any_match(arr, x -> x > 0), transform(arr, x -> x * 2), filter(arr, x -> x IS NOT NULL).","commonSituations":"Querying Pinot tables that contain array/map columns and applying lambda-based array functions in SELECT; recent Presto versions compile many array functions through lambdas, hitting this path even when the function looks ordinary.","solutions":["Rewrite the query without higher-order/lambda functions — use flat scalar expressions or UNNEST instead of transform/filter/any_match","Move the lambda-based computation outside the Pinot scan (compute it in an enclosing projection after the connector returns raw columns)","If the lambda must be evaluated, extract the raw array column from Pinot and perform the lambda logic in a separate Presto-side step","Contribute lambda-to-Pinot-expression support in visitLambda if Pinot gains equivalent functions"],"exampleFix":"// before\nSELECT transform(scores, x -> x * 2) AS doubled FROM pinot_table\n// after\nSELECT scores FROM pinot_table -- then compute transform(...) in an outer Presto query","handlingStrategy":"validation","validationCode":"// Reject lambda-based higher-order functions before querying Pinot:\njava.util.regex.Pattern LAMBDA_FNS = Pattern.compile(\n    \"(?i)(any_match|all_match|none_match|filter|transform|reduce|zip_with|map_filter|map_transform)\\\\s*\\\\(\");\nboolean isPushdownSafeProjection(String selectExpr) {\n    return !LAMBDA_FNS.matcher(selectExpr).find();\n}","typeGuard":null,"tryCatchPattern":"try {\n    result = queryPinot(sql);\n} catch (PinotException e) {\n    if (String.valueOf(e.getMessage()).startsWith(\"Pinot does not support lambda\")) {\n        // rewrite query without lambda / compute in Presto, then retry once\n    } else { throw e; }\n}","preventionTips":["Never use higher-order functions (transform/filter/any_match/reduce) in SELECT over Pinot tables","Use UNNEST or scalar expressions instead of lambdas for array processing","Push only raw columns down and do lambda logic in outer Presto queries","Keep array/map processing in application code or ingestion transforms"],"tags":["pinot","lambda","unsupported-expression","pushdown"],"backgroundTag":"pinot-unsupported-expression-pushdown","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}