public static HiveTableFunctionScan createUDTFForSetOp(RelOptCluster cluster, RelNode input)
      throws SemanticException {
    RelTraitSet traitSet = TraitsUtil.getDefaultTraitSet(cluster);

    List<RexNode> originalInputRefs = Lists.transform(input.getRowType().getFieldList(),
        new Function<RelDataTypeField, RexNode>() {
          @Override
          public RexNode apply(RelDataTypeField input) {
            return new RexInputRef(input.getIndex(), input.getType());
          }
        });
    ImmutableList.Builder<RelDataType> argTypeBldr = ImmutableList.<RelDataType> builder();
    for (int i = 0; i < originalInputRefs.size(); i++) {
      argTypeBldr.add(originalInputRefs.get(i).getType());
    }

    RelDataType retType = input.getRowType();

    String funcName = "replicate_rows";
    FunctionInfo fi = FunctionRegistry.getFunctionInfo(funcName);
    SqlOperator calciteOp = SqlFunctionConverter.getCalciteOperator(funcName, fi.getGenericUDTF(),
        argTypeBldr.build(), retType);

    // Hive UDTF only has a single input
    List<RelNode> list = new ArrayList<>();
    list.add(input);

    RexNode rexNode = cluster.getRexBuilder().makeCall(calciteOp, originalInputRefs);

    return HiveTableFunctionScan.create(cluster, traitSet, list, rexNode, null, retType, null);
  }
Check if the expression is usable for query materialization, returning the first failing expression.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveCalciteUtil.java