sql/src/main/java/org/apache/druid/sql/calcite/rule/DruidJoinRule.java
/**
   * If this condition is an AND of some combination of (1) literals; (2) equality conditions of the form
   * {@code f(LeftRel) = RightColumn}, then return a {@link ConditionAnalysis}.
   */
If this condition is an AND of some combination of (1) literals; (2) equality conditions of the form
f(LeftRel) = RightColumn, then return a  ConditionAnalysis.
If this condition is an AND of some combination of ( 1 ) literals ; ( 2 ) equality conditions of the form f ( LeftRel ) = RightColumn then return a ConditionAnalysis .
private Optional<ConditionAnalysis> analyzeCondition(
      final RexNode condition,
      final RelDataType leftRowType,
      DruidRel<?> right
  )
  {
    final List<RexNode> subConditions = decomposeAnd(condition);
    final List<Pair<RexNode, RexInputRef>> equalitySubConditions = new ArrayList<>();
    final List<RexLiteral> literalSubConditions = new ArrayList<>();
    final int numLeftFields = leftRowType.getFieldCount();
    final Set<RexInputRef> rightColumns = new HashSet<>();
    for (RexNode subCondition : subConditions) {
      if (RexUtil.isLiteral(subCondition, true)) {
        if (subCondition.isA(SqlKind.CAST)) {
          RexCall call = (RexCall) subCondition;
          if (call.getType().getSqlTypeName().equals(call.getOperands().get(0).getType().getSqlTypeName())) {
            literalSubConditions.add((RexLiteral) call.getOperands().get(0));
          } else {
            return Optional.empty();
          }
        } else {
          literalSubConditions.add((RexLiteral) subCondition);
        }
        continue;
      }
      if (!subCondition.isA(SqlKind.EQUALS)) {
        plannerContext.setPlanningError("SQL requires a join with '%s' condition that is not supported.",
            subCondition.getKind());
        return Optional.empty();
      }
      final List<RexNode> operands = ((RexCall) subCondition).getOperands();
      Preconditions.checkState(operands.size() == 2, "Expected 2 operands, got[%,d]", operands.size());
      if (isLeftExpression(operands.get(0), numLeftFields) && isRightInputRef(operands.get(1), numLeftFields)) {
        equalitySubConditions.add(Pair.of(operands.get(0), (RexInputRef) operands.get(1)));
        rightColumns.add((RexInputRef) operands.get(1));
      } else if (isRightInputRef(operands.get(0), numLeftFields)
                 && isLeftExpression(operands.get(1), numLeftFields)) {
        equalitySubConditions.add(Pair.of(operands.get(1), (RexInputRef) operands.get(0)));
        rightColumns.add((RexInputRef) operands.get(0));
      } else {
        plannerContext.setPlanningError("SQL is resulting in a join that has unsupported operand types.");
        return Optional.empty();
      }
    }
    if (right != null && !DruidJoinQueryRel.computeRightRequiresSubquery(DruidJoinQueryRel.getSomeDruidChild(right))
        && right instanceof DruidQueryRel) {
      DruidQueryRel druidQueryRel = (DruidQueryRel) right;
      if (druidQueryRel.getDruidTable().getDataSource() instanceof LookupDataSource) {
        long distinctRightColumns = rightColumns.stream().map(RexSlot::getIndex).distinct().count();
        if (distinctRightColumns > 1) {
          plannerContext.setPlanningError("SQL is resulting in a join involving lookup where value column is used in the condition.");
          return Optional.empty();
        }
      }
    }
    return Optional.of(new ConditionAnalysis(numLeftFields, equalitySubConditions, literalSubConditions));
  }
private Optional < ConditionAnalysis > analyzeCondition ( final RexNode condition , final RelDataType leftRowType , DruidRel < ? > right ) { final List < RexNode > subConditions = decomposeAnd ( condition ) ; final List < Pair < RexNode , RexInputRef > > equalitySubConditions = new ArrayList < > ( ) ; final List < RexLiteral > literalSubConditions = new ArrayList < > ( ) ; final int numLeftFields = leftRowType . getFieldCount ( ) ; final Set < RexInputRef > rightColumns = new HashSet < > ( ) ; for ( RexNode subCondition : subConditions ) { if ( RexUtil . isLiteral ( subCondition , true ) ) { if ( subCondition . isA ( SqlKind . CAST ) ) { RexCall call = ( RexCall ) subCondition ; if ( call . getType ( ) . getSqlTypeName ( ) . equals ( call . getOperands ( ) . get ( 0 ) . getType ( ) . getSqlTypeName ( ) ) ) { literalSubConditions . add ( ( RexLiteral ) call . getOperands ( ) . get ( 0 ) ) ; } else { return Optional . empty ( ) ; } } else { literalSubConditions . add ( ( RexLiteral ) subCondition ) ; } continue ; } if ( ! subCondition . isA ( SqlKind . EQUALS ) ) { plannerContext . setPlanningError ( "SQL requires a join with '%s' condition that is not supported." , subCondition . getKind ( ) ) ; return Optional . empty ( ) ; } final List < RexNode > operands = ( ( RexCall ) subCondition ) . getOperands ( ) ; Preconditions . checkState ( operands . size ( ) == 2 , "Expected 2 operands, got[%,d]" , operands . size ( ) ) ; if ( isLeftExpression ( operands . get ( 0 ) , numLeftFields ) && isRightInputRef ( operands . get ( 1 ) , numLeftFields ) ) { equalitySubConditions . add ( Pair . of ( operands . get ( 0 ) , ( RexInputRef ) operands . get ( 1 ) ) ) ; rightColumns . add ( ( RexInputRef ) operands . get ( 1 ) ) ; } else if ( isRightInputRef ( operands . get ( 0 ) , numLeftFields ) && isLeftExpression ( operands . get ( 1 ) , numLeftFields ) ) { equalitySubConditions . add ( Pair . of ( operands . get ( 1 ) , ( RexInputRef ) operands . get ( 0 ) ) ) ; rightColumns . add ( ( RexInputRef ) operands . get ( 0 ) ) ; } else { plannerContext . setPlanningError ( "SQL is resulting in a join that has unsupported operand types." ) ; return Optional . empty ( ) ; } } if ( right != null && ! DruidJoinQueryRel . computeRightRequiresSubquery ( DruidJoinQueryRel . getSomeDruidChild ( right ) ) && right instanceof DruidQueryRel ) { DruidQueryRel druidQueryRel = ( DruidQueryRel ) right ; if ( druidQueryRel . getDruidTable ( ) . getDataSource ( ) instanceof LookupDataSource ) { long distinctRightColumns = rightColumns . stream ( ) . map ( RexSlot :: getIndex ) . distinct ( ) . count ( ) ; if ( distinctRightColumns > 1 ) { plannerContext . setPlanningError ( "SQL is resulting in a join involving lookup where value column is used in the condition." ) ; return Optional . empty ( ) ; } } } return Optional . of ( new ConditionAnalysis ( numLeftFields , equalitySubConditions , literalSubConditions ) ) ; }
If this condition is an AND of some combination of (1) literals; (2) equality conditions of the form
 {@code f(LeftRel) = RightColumn}, then return a {@link ConditionAnalysis}.
If this condition is an AND of some combination of ( 1 ) literals ; ( 2 ) equality conditions of the form { @code f ( LeftRel ) = RightColumn } then return a { @link ConditionAnalysis } .
// This is CAST(literal) which is always OK. // We know that this is CAST(literal) as it passed the check from RexUtil.isLiteral // We have to verify the types of the cast here, because if the underlying literal and the cast output type // are different, then skipping the cast might change the meaning of the subcondition. // If the types are the same, unwrap the cast and use the underlying literal. // If the types are not the same, return Optional.empty() indicating the condition is not supported. // Literals are always OK. // If it's not EQUALS, it's not supported. // Cannot handle this condition. // if the the right side requires a subquery, then even lookup will transformed to a QueryDataSource // thereby allowing join conditions on both k and v columns of the lookup // it means that the join's right side is lookup and the join condition contains both key and value columns of lookup. // currently, the lookup datasource in the native engine doesn't support using value column in the join condition.