{"record":{"id":"53cc850e83185a0c","repo":"prestodb/presto","slug":"generic-internal-error-53cc85","errorCode":"GENERIC_INTERNAL_ERROR","errorMessage":"all inequality expressions for inference must be < or <=","messagePattern":"all inequality expressions for inference must be < or <=","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/planner/InequalityInference.java","lineNumber":71,"sourceCode":"import static java.util.Objects.requireNonNull;\nimport static java.util.stream.Collectors.toList;\n\npublic class InequalityInference\n{\n    // inequalityExpressions include the inequalities from the current join predicate\n    // and those inherited from the join's parent\n    private final Set<RowExpression> inequalityExpressions;\n    private final FunctionAndTypeManager functionAndTypeManager;\n    private final ExpressionEquivalence expressionEquivalence;\n    // 'outerVariables' is the variable set projected from the outer input for left or right join,\n    // or EMPTY if the join is an inner join\n    private final Optional<Collection<VariableReferenceExpression>> outerVariables;\n\n    public InequalityInference(Set<RowExpression> inequalityExpressions, FunctionAndTypeManager functionAndTypeManager, ExpressionEquivalence expressionEquivalence, Optional<Collection<VariableReferenceExpression>> outerVariables)\n    {\n        if (inequalityExpressions.stream()\n                .anyMatch(e -> !isOperation(e, LESS_THAN, functionAndTypeManager) && !isOperation(e, LESS_THAN_OR_EQUAL, functionAndTypeManager))) {\n            throw new PrestoException(GENERIC_INTERNAL_ERROR, \"all inequality expressions for inference must be < or <=\");\n        }\n        this.inequalityExpressions = requireNonNull(inequalityExpressions, \"inequalityExpressions is null\");\n        this.functionAndTypeManager = requireNonNull(functionAndTypeManager, \"functionAndTypeManager is null\");\n        this.expressionEquivalence = requireNonNull(expressionEquivalence, \"expressionEquivalence is null\");\n        this.outerVariables = requireNonNull(outerVariables, \"outerVariables is null\");\n    }\n\n    // Basic idea is to pairwise compare each predicate with all other predicates.\n    // Since any inferred predicates may trigger other inferences, keep comparing until no new predicates are generated\n    public Set<RowExpression> inferInequalities()\n    {\n        if (inequalityExpressions.size() < 2) {\n            return ImmutableSet.of();\n        }\n\n        Set<RowExpression> allInferredInequalities = new HashSet<>();\n        Set<RowExpression> inequalitiesInferredInCurrentTraversal = new HashSet<>(inequalityExpressions);\n        Set<Set<RowExpression>> exploredCombinations = new HashSet();","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/planner/InequalityInference.java#L53-L89","documentation":"InequalityInference's constructor throws GENERIC_INTERNAL_ERROR if any supplied inequality expression is not < or <=. The class only implements inference over less-than style predicates, so other operators indicate an internal bug or misuse.","triggerScenarios":"Constructing InequalityInference (e.g. from join or predicate-pushdown optimizers) with expressions containing >, >=, or non-inequality predicates.","commonSituations":"Engine-internal: an optimizer passed unnormalized inequalities (e.g. > instead of flipped <) into the inference. Users cannot trigger it directly; it usually signals a bug.","solutions":["Upgrade Presto; check for a fixed bug in the relevant optimizer rule.","Work around by rewriting query predicates so inequality join conditions are written with < or <=.","File an issue with the query and plan."],"exampleFix":"// before\nJOIN b ON a.x > b.x\n// after\nJOIN b ON b.x < a.x","handlingStrategy":"validation","validationCode":"boolean allLessThan = inequalities.stream().allMatch(e -> isOperation(e, LESS_THAN, ftm) || isOperation(e, LESS_THAN_OR_EQUAL, ftm)); if (!allLessThan) { throw new IllegalArgumentException(\"only < or <= supported\"); }","typeGuard":"boolean isSupportedInequality(RowExpression e, FunctionAndTypeManager m) { return isOperation(e, LESS_THAN, m) || isOperation(e, LESS_THAN_OR_EQUAL, m); }","tryCatchPattern":"try { new InequalityInference(exprs, ftm, equiv, outer); } catch (PrestoException e) { if (e.getErrorCode() == StandardErrorCode.GENERIC_INTERNAL_ERROR.toErrorCode()) { /* normalize > to < and retry */ } else { throw e; } }","preventionTips":["Normalize all > and >= to flipped < and <= before building the inference","Only feed inequalities from the intended optimizer call sites","Add unit tests asserting operator precondition"],"tags":["internal-error","optimizer","inequality-inference"],"backgroundTag":"internal-invariant-violation","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"}