@Override
  public void onMatch(RelOptRuleCall call) {
    TableScan scan = call.rel(0);
    String tableName = scan.getTable().getQualifiedName().toString();
    for (RelOptMaterialization cte : call.getPlanner().getMaterializations()) {
      if (tableName.equals(cte.qualifiedTableName.toString()) && spools.add(tableName)) {
        RelOptTableImpl cteTable =
            RelOptTableImpl.create(null, scan.getRowType(), scan.getTable().getQualifiedName(), null);
        // The Spool types are not used at the moment so choice between LAZY/EAGER does not affect anything
        call.transformTo(HIVE_SPOOL_FACTORY.createTableSpool(cte.queryRel, Spool.Type.LAZY, Spool.Type.LAZY, cteTable));
      }
    }
  }
Track created spools to avoid introducing more than one.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/TableScanToSpoolRule.java