@Override
    public boolean isExecutable(HiveJoin join) {
      // Requirements: for SMB, sorted by their keys on both sides and bucketed.
      // Get key columns
      JoinPredicateInfo joinPredInfo = join.getJoinPredicateInfo();
      List<ImmutableIntList> joinKeysInChildren = new ArrayList<ImmutableIntList>();
      joinKeysInChildren.add(
              ImmutableIntList.copyOf(
                      joinPredInfo.getProjsFromLeftPartOfJoinKeysInChildSchema()));
      joinKeysInChildren.add(
              ImmutableIntList.copyOf(
                      joinPredInfo.getProjsFromRightPartOfJoinKeysInChildSchema()));

      final RelMetadataQuery mq = join.getCluster().getMetadataQuery();
      for (int i=0; i<join.getInputs().size(); i++) {
        RelNode input = join.getInputs().get(i);
        // Is smbJoin possible? We need correct order
        boolean orderFound;
        try {
          orderFound = join.getSortedInputs().get(i);
        } catch (CalciteSemanticException e) {
          LOG.trace("Not possible to do SMB Join ",e);
          return false;
        }
        if (!orderFound) {
          return false;
        }
        // Is smbJoin possible? We need correct bucketing
        RelDistribution distribution = mq.distribution(input);
        if (distribution.getType() != Type.HASH_DISTRIBUTED) {
          return false;
        }
        if (!distribution.getKeys().containsAll(joinKeysInChildren.get(i))) {
          return false;
        }
      }
      return true;
    }
SMB_JOIN is a Sort Merge Join. Each parallel computation handles one bucket.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/cost/HiveOnTezCostModel.java