{"record":{"id":"59ab5366cb72f98f","repo":"apache/flink","slug":"invalid-binary-comparison","errorCode":null,"errorMessage":"Invalid binary comparison.","messagePattern":"Invalid binary comparison\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"flink-formats/flink-orc/src/main/java/org/apache/flink/orc/OrcFilters.java","lineNumber":318,"sourceCode":"\n    private static String getColumnName(CallExpression comp) {\n        if (literalOnRight(comp)) {\n            return ((FieldReferenceExpression) comp.getChildren().get(0)).getName();\n        } else {\n            return ((FieldReferenceExpression) comp.getChildren().get(1)).getName();\n        }\n    }\n\n    private static boolean literalOnRight(CallExpression comp) {\n        if (comp.getChildren().size() == 1\n                && comp.getChildren().get(0) instanceof FieldReferenceExpression) {\n            return true;\n        } else if (isLit(comp.getChildren().get(0)) && isRef(comp.getChildren().get(1))) {\n            return false;\n        } else if (isRef(comp.getChildren().get(0)) && isLit(comp.getChildren().get(1))) {\n            return true;\n        } else {\n            throw new RuntimeException(\"Invalid binary comparison.\");\n        }\n    }\n\n    private static PredicateLeaf.Type getLiteralType(CallExpression comp) {\n        if (literalOnRight(comp)) {\n            return toOrcType(\n                    ((ValueLiteralExpression) comp.getChildren().get(1)).getOutputDataType());\n        } else {\n            return toOrcType(\n                    ((ValueLiteralExpression) comp.getChildren().get(0)).getOutputDataType());\n        }\n    }\n\n    private static Object toOrcObject(PredicateLeaf.Type litType, Object literalObj) {\n        switch (litType) {\n            case DATE:\n                if (literalObj instanceof LocalDate) {\n                    LocalDate localDate = (LocalDate) literalObj;","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-formats/flink-orc/src/main/java/org/apache/flink/orc/OrcFilters.java#L300-L336","documentation":"OrcFilters.literalOnRight inspects a binary comparison CallExpression to decide which side is the literal. It accepts (a) a single child that is a field reference (unary like NOT/IS_NULL), (b) literal-left/ref-right, or (c) ref-left/literal-right. Anything else — two literals, two references, or unsupported child types — throws RuntimeException('Invalid binary comparison').","triggerScenarios":"Calling OrcFilters or the ORC table predicate pushdown path with a comparison expression whose children are not exactly one FieldReferenceExpression and one ValueLiteralExpression (e.g. two columns compared, two constants, or resolved expressions of another type).","commonSituations":"Queries like SELECT * FROM t WHERE a = b (column-to-column) reaching the legacy OrcTableSource/OrcFilters API; older planner versions producing expressions the filter converter does not recognize; direct programmatic use of OrcFilters with unnormalized expressions.","solutions":["Push down only comparisons of a column against a literal; keep column-to-column predicates in Flink (do not pass them to OrcFilters).","When using the legacy OrcTableSource API, pre-simplify/normalize expressions before handing them to the filter builder.","Prefer the modern ORC filesystem connector (flink-orc with the FLIP-27 file source) whose predicate pushdown handles richer shapes."],"exampleFix":"// before\nExpression pred = $(\"a\").isEqual($(\"b\")); // column vs column\norcTableSource.getSchema().project().filters(pred);\n// after\nExpression pred = $(\"a\").isEqual(lit(42)); // column vs literal\n// column-to-column predicate stays in Flink, not pushed to ORC","handlingStrategy":"type-guard","validationCode":"// Only push down ref-vs-literal comparisons\nboolean pushable(CallExpression c) {\n    List<Expression> ch = c.getChildren();\n    if (ch.size() == 1) return ch.get(0) instanceof FieldReferenceExpression;\n    if (ch.size() != 2) return false;\n    return (ch.get(0) instanceof FieldReferenceExpression && ch.get(1) instanceof ValueLiteralExpression)\n        || (ch.get(0) instanceof ValueLiteralExpression && ch.get(1) instanceof FieldReferenceExpression);\n}","typeGuard":"static boolean isValidBinaryComparison(CallExpression c) {\n    return c.getChildren().size() == 1\n            ? c.getChildren().get(0) instanceof FieldReferenceExpression\n            : (isRef(c.getChildren().get(0)) && isLit(c.getChildren().get(1)))\n              || (isLit(c.getChildren().get(0)) && isRef(c.getChildren().get(1)));\n}","tryCatchPattern":null,"preventionTips":["Keep column-to-column predicates out of ORC pushdown lists.","Prefer the modern ORC filesystem connector over legacy OrcTableSource filter plumbing."],"tags":["flink","orc","predicate-pushdown","expression","filters"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}