@Override
  public boolean matches(RelOptRuleCall call) {
    final HiveTableFunctionScan tableFunctionScanRel = call.rel(0);

    if (!(tableFunctionScanRel.getCall() instanceof RexCall)) {
      return false;
    }

    RexCall udtfCall = (RexCall) tableFunctionScanRel.getCall();
    if (udtfCall.getOperator() != SqlStdOperatorTable.LATERAL) {
      return false;
    }

    RexCall inlineCall = (RexCall) udtfCall.getOperands().get(0);
    if (!FunctionRegistry.INLINE_FUNC_NAME.equalsIgnoreCase(inlineCall.getOperator().getName())) {
      return false;
    }

    Preconditions.checkState(!inlineCall.getOperands().isEmpty());
    RexNode operand = inlineCall.getOperands().get(0);
    if (!(operand instanceof RexCall)) {
      return false;
    }
    RexCall firstOperand = (RexCall) operand;
    if (!FunctionRegistry.ARRAY_FUNC_NAME.equalsIgnoreCase(firstOperand.getOperator().getName())) {
      return false;
    }
    Preconditions.checkState(!firstOperand.getOperands().isEmpty());
    int numStructParams = firstOperand.getOperands().get(0).getType().getFieldCount();

    if (tableFunctionScanRel.getRowType().getFieldCount() == numStructParams) {
      return false;
    }

    return true;
  }
This rule optimizes the inline udtf in a HiveTableFunctionScan when it
has an array of structures. The RelNode for a HiveTableFunctionScan places
the input references as the first elements in the return type followed by
the udtf return value which represents the items in the generated table. Take the
case where the base (input) table has col1, and the inline function is represented by:
inline(array( struct1(col2, col3), struct2(col2, col3), struct3(col2, col3), etc...)),
...and the return value for the table scan node is (col1, col2, col3). In this case,
the same col1 value is joined with the structures within the inline array for the
col2 and col3 values.

The optimization is to put the "col1" value within the inline array, resulting in
in the new structure:
inline(array(struct1(col1, col2, col3), struct2(col1, col2, col3), ...)
By doing this, we avoid creating a lateral view join operator and a lateral view forward
operator at runtime.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveOptimizeInlineArrayTableFunctionRule.java