{"record":{"id":"379cd19ba0b95ae6","repo":"prestodb/presto","slug":"druid-pushdown-unsupported-expression-379cd1","errorCode":"DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION","errorMessage":"${operator} is not supported in Druid filter","messagePattern":"(.+?) is not supported in Druid filter","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-druid/src/main/java/com/facebook/presto/druid/DruidFilterExpressionConverter.java","lineNumber":90,"sourceCode":"            SpecialFormExpression specialForm,\n            boolean isWhitelist,\n            Function<VariableReferenceExpression, Selection> context)\n    {\n        return derived(format(\"(%s %s (%s))\",\n                specialForm.getArguments().get(0).accept(this, context).getDefinition(),\n                isWhitelist ? \"IN\" : \"NOT IN\",\n                specialForm.getArguments().subList(1, specialForm.getArguments().size()).stream()\n                        .map(argument -> argument.accept(this, context).getDefinition())\n                        .collect(Collectors.joining(\", \"))));\n    }\n\n    private DruidExpression handleLogicalBinary(\n            String operator,\n            CallExpression call,\n            Function<VariableReferenceExpression, Selection> context)\n    {\n        if (!LOGICAL_BINARY_OPS_FILTER.contains(operator)) {\n            throw new PrestoException(DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION, operator + \" is not supported in Druid filter\");\n        }\n        List<RowExpression> arguments = call.getArguments();\n        if (arguments.size() == 2) {\n            return derived(format(\n                    \"(%s %s %s)\",\n                    arguments.get(0).accept(this, context).getDefinition(),\n                    operator,\n                    arguments.get(1).accept(this, context).getDefinition()));\n        }\n        throw new PrestoException(DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION, \"Unknown logical binary: \" + call);\n    }\n\n    private DruidExpression handleBetween(\n            CallExpression between,\n            Function<VariableReferenceExpression, Selection> context)\n    {\n        if (between.getArguments().size() == 3) {\n            RowExpression value = between.getArguments().get(0);","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-druid/src/main/java/com/facebook/presto/druid/DruidFilterExpressionConverter.java#L72-L108","documentation":"When converting a Presto filter expression for pushdown to Druid, a logical binary operator (AND/OR/NOT family) was encountered whose operator name is not in LOGICAL_BINARY_OPS_FILTER. DruidFilterExpressionConverter only pushes down operators it can translate to Druid filter syntax, so it throws DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION.","triggerScenarios":"visitCall dispatches a CallExpression with an OperatorType flagged as a comparison/logical binary whose operator string (e.g. some non-standard logical op) is not contained in LOGICAL_BINARY_OPS_FILTER when handleLogicalBinary is invoked.","commonSituations":"Queries using operators the Druid connector cannot push down (e.g. IS DISTINCT FROM-style or exotic logical operators in WHERE clauses); the predicate then needs to be evaluated in Presto instead.","solutions":["Rewrite the WHERE predicate using plain AND/OR comparisons that Druid supports","Drop the unsupported operator from the query so the filter is not pushed down","Check LOGICAL_BINARY_OPS_FILTER in DruidFilterExpressionConverter to see which operators are accepted","Upgrade the Presto/Druid connector — supported operator sets have expanded across versions"],"exampleFix":"-- before\nSELECT * FROM druid_table WHERE a IS DISTINCT FROM b;\n-- after\nSELECT * FROM druid_table WHERE a != b OR (a IS NULL AND b IS NULL);","handlingStrategy":"validation","validationCode":"// Keep WHERE predicates limited to AND/OR over comparison operators\n// Avoid: IS DISTINCT FROM and other non-standard logical operators in Druid queries","typeGuard":null,"tryCatchPattern":"try {\n    runQuery(sql);\n} catch (PrestoException e) {\n    if (e.getErrorCode().getCode() == DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION.toErrorCode().getCode()) {\n        log.warn(\"Filter not pushable to Druid, rewriting: {}\", e.getMessage());\n        runQuery(rewritePredicate(sql));\n    } else { throw e; }\n}","preventionTips":["Use only AND/OR and standard comparison operators in Druid WHERE clauses","Check LOGICAL_BINARY_OPS_FILTER in the connector source for the supported set","Keep connector and Presto server versions aligned"],"tags":["druid","pushdown","sql","predicate"],"backgroundTag":"pushdown-unsupported-expression","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"}