apache/flink · error · RuntimeException

Invalid binary comparison.

Error message

Invalid binary comparison.

What it means

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').

Source

Thrown at flink-formats/flink-orc/src/main/java/org/apache/flink/orc/OrcFilters.java:318

    private static String getColumnName(CallExpression comp) {
        if (literalOnRight(comp)) {
            return ((FieldReferenceExpression) comp.getChildren().get(0)).getName();
        } else {
            return ((FieldReferenceExpression) comp.getChildren().get(1)).getName();
        }
    }

    private static boolean literalOnRight(CallExpression comp) {
        if (comp.getChildren().size() == 1
                && comp.getChildren().get(0) instanceof FieldReferenceExpression) {
            return true;
        } else if (isLit(comp.getChildren().get(0)) && isRef(comp.getChildren().get(1))) {
            return false;
        } else if (isRef(comp.getChildren().get(0)) && isLit(comp.getChildren().get(1))) {
            return true;
        } else {
            throw new RuntimeException("Invalid binary comparison.");
        }
    }

    private static PredicateLeaf.Type getLiteralType(CallExpression comp) {
        if (literalOnRight(comp)) {
            return toOrcType(
                    ((ValueLiteralExpression) comp.getChildren().get(1)).getOutputDataType());
        } else {
            return toOrcType(
                    ((ValueLiteralExpression) comp.getChildren().get(0)).getOutputDataType());
        }
    }

    private static Object toOrcObject(PredicateLeaf.Type litType, Object literalObj) {
        switch (litType) {
            case DATE:
                if (literalObj instanceof LocalDate) {
                    LocalDate localDate = (LocalDate) literalObj;

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Push down only comparisons of a column against a literal; keep column-to-column predicates in Flink (do not pass them to OrcFilters).
  2. When using the legacy OrcTableSource API, pre-simplify/normalize expressions before handing them to the filter builder.
  3. Prefer the modern ORC filesystem connector (flink-orc with the FLIP-27 file source) whose predicate pushdown handles richer shapes.

Example fix

// before
Expression pred = $("a").isEqual($("b")); // column vs column
orcTableSource.getSchema().project().filters(pred);
// after
Expression pred = $("a").isEqual(lit(42)); // column vs literal
// column-to-column predicate stays in Flink, not pushed to ORC
Defensive patterns

Strategy: type-guard

Validate before calling

// Only push down ref-vs-literal comparisons
boolean pushable(CallExpression c) {
    List<Expression> ch = c.getChildren();
    if (ch.size() == 1) return ch.get(0) instanceof FieldReferenceExpression;
    if (ch.size() != 2) return false;
    return (ch.get(0) instanceof FieldReferenceExpression && ch.get(1) instanceof ValueLiteralExpression)
        || (ch.get(0) instanceof ValueLiteralExpression && ch.get(1) instanceof FieldReferenceExpression);
}

Type guard

static boolean isValidBinaryComparison(CallExpression c) {
    return c.getChildren().size() == 1
            ? c.getChildren().get(0) instanceof FieldReferenceExpression
            : (isRef(c.getChildren().get(0)) && isLit(c.getChildren().get(1)))
              || (isLit(c.getChildren().get(0)) && isRef(c.getChildren().get(1)));
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/59ab5366cb72f98f. Report an issue: GitHub.