@Override
  public void onMatch(RelOptRuleCall call) {
    RexBuilder rexBuilder = call.builder().getRexBuilder();
    final HiveUnion union = call.rel(0);
    if (!union.all) {
      return;
    }
    List<RelNode> inputs = new ArrayList<RelNode>();
    List<Project> projects = new ArrayList<>();
    List<HiveTableFunctionScan> inlineTables = new ArrayList<>();

    for (RelNode input : union.getInputs()) {
      input = HiveRelDecorrelator.stripHep(input);

      if (isPlainProject(input)) {
        projects.add((Project) input);
        continue;
      }

      if (isInlineTableOperand(input)) {
        inlineTables.add((HiveTableFunctionScan) input);
        continue;
      }
      inputs.add(input);
    }

    if (projects.size() + inlineTables.size() <= 1) {
      // nothing to do
      return;
    }

    RowStorage newRows = new RowStorage();
    for (HiveTableFunctionScan rel : inlineTables) {
      // inline(array(row1,row2,...))
      RexCall rex = (RexCall) ((RexCall) rel.getCall()).operands.get(0);
      for (RexNode row : rex.operands) {
        if (!(row.getType() instanceof RelRecordType)) {
          return;
        }
        newRows.addRow(row);
      }
    }

    for (Project proj : projects) {
      RexNode row = rexBuilder.makeCall(SqlStdOperatorTable.ROW, proj.getProjects());
      if (!(row.getType() instanceof RelRecordType)) {
        return;
      }
      newRows.addRow(row);
    }

    if (newRows.keySet().size() + inputs.size() == union.getInputs().size()) {
      // nothing to do
      return;
    }

    if (dummyTable == null) {
      LOG.warn("Unexpected; rule would match - but dummyTable is not available");
      return;
    }

    for (RelRecordType type : newRows.keySet()) {
      List<RexNode> rows = newRows.get(type);

      RelDataType arrayType = rexBuilder.getTypeFactory().createArrayType(type, -1);
      try {
        SqlOperator inlineFn =
            SqlFunctionConverter.getCalciteFn("inline", Collections.singletonList(arrayType), type, true, false);
        SqlOperator arrayFn =
            SqlFunctionConverter.getCalciteFn("array", Collections.nCopies(rows.size(), type), arrayType, true, false);

        RexNode expr = rexBuilder.makeCall(arrayFn, rows);
        expr = rexBuilder.makeCall(inlineFn, expr);

        RelNode newInlineTable = buildTableFunctionScan(expr, union.getCluster());

        inputs.add(newInlineTable);

      } catch (CalciteSemanticException e) {
        LOG.debug("Conversion failed with exception", e);
        return;
      }
    }

    if (inputs.size() > 1) {
      HiveUnion newUnion = (HiveUnion) union.copy(union.getTraitSet(), inputs, true);
      call.transformTo(newUnion);
    } else {
      call.transformTo(inputs.get(0));
    }
  }
Transforms SELECTS of literals under UNION ALL into inline table scans.

This rule processes plain projects and inline tables below UNION ALL nodes.

<pre>
SELECT 1
UNION ALL
SELECT 2
UNION ALL
[...]
</pre>

<pre>
HiveUnion(all=true)
 HiveProject(_o__c0=[1])
  HiveTableScan(table=[[_dummy_database, _dummy_table]], table:alias=[_dummy_table])
 HiveProject(_o__c0=[2])
  HiveTableScan(table=[[_dummy_database, _dummy_table]], table:alias=[_dummy_table])
 [...]
</pre>

will be transformed into
<pre>
HiveUnion(all=true)
 HiveProject(EXPR$0=[$0])
  HiveTableFunctionScan(invocation=[inline(ARRAY(ROW(1), ROW(2)))], rowType=[RecordType(INTEGER EXPR$0)])
   HiveTableScan(table=[[_dummy_database, _dummy_table]], table:alias=[_dummy_table])
 [...]
</pre>
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveUnionSimpleSelectsToInlineTableRule.java