{"record":{"id":"5a47dfa4838c99a3","repo":"apache/beam","slug":"operator-operatorname-is-not-supported-in-join-condition","errorCode":null,"errorMessage":"Operator ${operatorName} is not supported in join condition","messagePattern":"Operator (.+?) is not supported in join condition","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamJoinRel.java","lineNumber":182,"sourceCode":"  static List<Pair<RexNode, RexNode>> extractJoinRexNodes(RexNode condition) {\n    // it's a CROSS JOIN because: condition == true\n    // or it's a JOIN ON false because: condition == false\n    if (condition instanceof RexLiteral) {\n      throw new UnsupportedOperationException(\"CROSS JOIN, JOIN ON FALSE is not supported!\");\n    }\n\n    RexCall call = (RexCall) condition;\n    List<Pair<RexNode, RexNode>> pairs = new ArrayList<>();\n    if (\"AND\".equals(call.getOperator().getName())) {\n      List<RexNode> operands = call.getOperands();\n      for (RexNode rexNode : operands) {\n        Pair<RexNode, RexNode> pair = extractJoinPairOfRexNodes((RexCall) rexNode);\n        pairs.add(pair);\n      }\n    } else if (\"=\".equals(call.getOperator().getName())) {\n      pairs.add(extractJoinPairOfRexNodes(call));\n    } else {\n      throw new UnsupportedOperationException(\n          \"Operator \" + call.getOperator().getName() + \" is not supported in join condition\");\n    }\n\n    return pairs;\n  }\n\n  private static Pair<RexNode, RexNode> extractJoinPairOfRexNodes(RexCall rexCall) {\n    if (!rexCall.getOperator().getName().equals(\"=\")) {\n      throw new UnsupportedOperationException(\"Non equi-join is not supported\");\n    }\n\n    if (isIllegalJoinConjunctionClause(rexCall)) {\n      throw new UnsupportedOperationException(\n          \"Only support column reference or struct field access in conjunction clause\");\n    }\n\n    int leftIndex = getColumnIndex(rexCall.getOperands().get(0));\n    int rightIndex = getColumnIndex(rexCall.getOperands().get(1));","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamJoinRel.java#L164-L200","documentation":"extractJoinRexNodes only understands join conditions that are AND-combinations or plain '=' comparisons. Any other operator at the top of the condition tree (OR, <, >, LIKE, etc.) cannot be decomposed into equi-join pairs, so it throws UnsupportedOperationException.","triggerScenarios":"A JOIN whose ON clause uses a top-level operator other than AND or =, e.g. JOIN ON a.id < b.id or ON a.id = b.id OR a.type = b.type.","commonSituations":"Writing range joins or OR-combined join keys common in relational SQL; migrating analytical queries that assume full join-condition support.","solutions":["Rewrite the condition to a conjunction of equality predicates (AND of column = column)","Push non-equi predicates (ranges, ORs) into WHERE after the equi-join instead of the ON clause","Use a JOIN with UDF-based co-grouping or flatten to a cross join plus filter if semantics require it"],"exampleFix":"// before\nSELECT * FROM a JOIN b ON a.ts < b.ts;\n// after\nSELECT * FROM a JOIN b ON a.key = b.key WHERE a.ts < b.ts;","handlingStrategy":"validation","validationCode":"// Only AND of '=' comparisons allowed at the top level\nif (!(isAndCondition(joinCondition) || isEqualsCondition(joinCondition))) {\n  throw new IllegalArgumentException(\"Join condition must be AND of '=' comparisons\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  result = sqlEnv.sqlQuery(q).evaluate();\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"is not supported in join condition\")) {\n    q = pushNonEquiPredicatesToWhere(q);\n  } else throw e;\n}","preventionTips":["Use only AND + '=' in join conditions","Move OR/range predicates to WHERE after the join","Lint SQL before submission for non-AND top-level join operators"],"tags":["sql","join","operator","beam"],"backgroundTag":"unsupported-operation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}