@Override
    public ASTNode visitCall(RexCall call) {
      if (!deep) {
        return null;
      }

      SqlOperator op = call.getOperator();
      List<ASTNode> astNodeLst = new LinkedList<ASTNode>();
      switch (op.kind) {
      case EQUALS:
      case NOT_EQUALS:
      case LESS_THAN:
      case GREATER_THAN:
      case LESS_THAN_OR_EQUAL:
      case GREATER_THAN_OR_EQUAL:
        if (rexBuilder != null && RexUtil.isReferenceOrAccess(call.operands.get(1), true) &&
            RexUtil.isLiteral(call.operands.get(0), true)) {
          // Swap to get reference on the left side
          return visitCall((RexCall) RexUtil.invert(rexBuilder, call));
        } else {
          for (RexNode operand : call.operands) {
            astNodeLst.add(operand.accept(this));
          }
        }
        break;
      case IS_DISTINCT_FROM:
        for (RexNode operand : call.operands) {
          astNodeLst.add(operand.accept(this));
        }
        return SqlFunctionConverter.buildAST(SqlStdOperatorTable.NOT,
          Collections.singletonList(SqlFunctionConverter.buildAST(SqlStdOperatorTable.IS_NOT_DISTINCT_FROM, astNodeLst, call.getType())), call.getType());
      case CAST:
        assert(call.getOperands().size() == 1);
        astNodeLst.add(convertType(call.getType()));
        astNodeLst.add(call.getOperands().get(0).accept(this));
        break;
      case EXTRACT:
        // Extract on date: special handling since function in Hive does
        // include <time_unit>. Observe that <time_unit> information
        // is implicit in the function name, thus translation will
        // proceed correctly if we just ignore the <time_unit>
        astNodeLst.add(call.operands.get(1).accept(this));
        break;
      case FLOOR:
        if (call.operands.size() == 2) {
          // Floor on date: special handling since function in Hive does
          // include <time_unit>. Observe that <time_unit> information
          // is implicit in the function name, thus translation will
          // proceed correctly if we just ignore the <time_unit>
          astNodeLst.add(call.operands.get(0).accept(this));
          break;
        }
        // fall-through
      default:
        if (op.equals(HiveComponentAccess.COMPONENT_ACCESS)) {
          return call.operands.get(0).accept(this);
        }
        for (RexNode operand : call.operands) {
          astNodeLst.add(operand.accept(this));
        }
      }

      if (isFlat(call)) {
        return SqlFunctionConverter.buildAST(op, astNodeLst, 0);
      } else {
        return SqlFunctionConverter.buildAST(op, astNodeLst, call.getType());
      }
    }
Add PK-FK join information to the AST as a query hint
@param ast
@param join
@param swapSides whether the left and right input of the join is swapped
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/ASTConverter.java