private static Expression propagate()

in x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PropagateEquals.java [56:189]


    private static Expression propagate(And and, LogicalOptimizerContext ctx) {
        List<Range> ranges = new ArrayList<>();
        // Only equalities, not-equalities and inequalities with a foldable .right are extracted separately;
        // the others go into the general 'exps'.
        // TODO: In 105217, this should change to EsqlBinaryComparison, but it doesn't exist in this branch yet
        List<BinaryComparison> equals = new ArrayList<>();
        List<NotEquals> notEquals = new ArrayList<>();
        List<BinaryComparison> inequalities = new ArrayList<>();
        List<Expression> exps = new ArrayList<>();

        boolean changed = false;

        for (Expression ex : Predicates.splitAnd(and)) {
            if (ex instanceof Range) {
                ranges.add((Range) ex);
            } else if (ex instanceof Equals otherEq) {
                // equals on different values evaluate to FALSE
                // ignore date/time fields as equality comparison might actually be a range check
                if (otherEq.right().foldable() && DataType.isDateTime(otherEq.left().dataType()) == false) {
                    for (BinaryComparison eq : equals) {
                        if (otherEq.left().semanticEquals(eq.left())) {
                            Integer comp = BinaryComparison.compare(eq.right().fold(ctx.foldCtx()), otherEq.right().fold(ctx.foldCtx()));
                            if (comp != null) {
                                // var cannot be equal to two different values at the same time
                                if (comp != 0) {
                                    return new Literal(and.source(), Boolean.FALSE, DataType.BOOLEAN);
                                }
                            }
                        }
                    }
                    equals.add(otherEq);
                } else {
                    exps.add(otherEq);
                }
            } else if (ex instanceof GreaterThan
                || ex instanceof GreaterThanOrEqual
                || ex instanceof LessThan
                || ex instanceof LessThanOrEqual) {
                    BinaryComparison bc = (BinaryComparison) ex;
                    if (bc.right().foldable()) {
                        inequalities.add(bc);
                    } else {
                        exps.add(ex);
                    }
                } else if (ex instanceof NotEquals otherNotEq) {
                    if (otherNotEq.right().foldable()) {
                        notEquals.add(otherNotEq);
                    } else {
                        exps.add(ex);
                    }
                } else {
                    exps.add(ex);
                }
        }

        // check
        for (BinaryComparison eq : equals) {
            Object eqValue = eq.right().fold(ctx.foldCtx());

            for (Iterator<Range> iterator = ranges.iterator(); iterator.hasNext();) {
                Range range = iterator.next();

                if (range.value().semanticEquals(eq.left())) {
                    // if equals is outside the interval, evaluate the whole expression to FALSE
                    if (range.lower().foldable()) {
                        Integer compare = BinaryComparison.compare(range.lower().fold(ctx.foldCtx()), eqValue);
                        if (compare != null && (
                        // eq outside the lower boundary
                        compare > 0 ||
                        // eq matches the boundary but should not be included
                            (compare == 0 && range.includeLower() == false))) {
                            return new Literal(and.source(), Boolean.FALSE, DataType.BOOLEAN);
                        }
                    }
                    if (range.upper().foldable()) {
                        Integer compare = BinaryComparison.compare(range.upper().fold(ctx.foldCtx()), eqValue);
                        if (compare != null && (
                        // eq outside the upper boundary
                        compare < 0 ||
                        // eq matches the boundary but should not be included
                            (compare == 0 && range.includeUpper() == false))) {
                            return new Literal(and.source(), Boolean.FALSE, DataType.BOOLEAN);
                        }
                    }

                    // it's in the range and thus, remove it
                    iterator.remove();
                    changed = true;
                }
            }

            // evaluate all NotEquals against the Equal
            for (Iterator<NotEquals> iter = notEquals.iterator(); iter.hasNext();) {
                NotEquals neq = iter.next();
                if (eq.left().semanticEquals(neq.left())) {
                    Integer comp = BinaryComparison.compare(eqValue, neq.right().fold(ctx.foldCtx()));
                    if (comp != null) {
                        if (comp == 0) { // clashing and conflicting: a = 1 AND a != 1
                            return new Literal(and.source(), Boolean.FALSE, DataType.BOOLEAN);
                        } else { // clashing and redundant: a = 1 AND a != 2
                            iter.remove();
                            changed = true;
                        }
                    }
                }
            }

            // evaluate all inequalities against the Equal
            for (Iterator<BinaryComparison> iter = inequalities.iterator(); iter.hasNext();) {
                BinaryComparison bc = iter.next();
                if (eq.left().semanticEquals(bc.left())) {
                    Integer compare = BinaryComparison.compare(eqValue, bc.right().fold(ctx.foldCtx()));
                    if (compare != null) {
                        if (bc instanceof LessThan || bc instanceof LessThanOrEqual) { // a = 2 AND a </<= ?
                            if ((compare == 0 && bc instanceof LessThan) || // a = 2 AND a < 2
                                0 < compare) { // a = 2 AND a </<= 1
                                return new Literal(and.source(), Boolean.FALSE, DataType.BOOLEAN);
                            }
                        } else if (bc instanceof GreaterThan || bc instanceof GreaterThanOrEqual) { // a = 2 AND a >/>= ?
                            if ((compare == 0 && bc instanceof GreaterThan) || // a = 2 AND a > 2
                                compare < 0) { // a = 2 AND a >/>= 3
                                return new Literal(and.source(), Boolean.FALSE, DataType.BOOLEAN);
                            }
                        }

                        iter.remove();
                        changed = true;
                    }
                }
            }
        }

        return changed ? Predicates.combineAnd(CollectionUtils.combine(exps, equals, notEquals, inequalities, ranges)) : and;
    }