This is an automated email from the ASF dual-hosted git repository.

thomasrebele pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new bf070e440d [CALCITE-7650] Bytecode by JDK 11 is invalid due to 
Checkerframework annotations
bf070e440d is described below

commit bf070e440d88d551bbf82ea8f48c67857c014e8b
Author: Thomas Rebele <[email protected]>
AuthorDate: Fri Jul 10 17:09:01 2026 +0200

    [CALCITE-7650] Bytecode by JDK 11 is invalid due to Checkerframework 
annotations
---
 .../apache/calcite/adapter/clone/ArrayTable.java   |  15 +-
 .../calcite/adapter/enumerable/EnumUtils.java      |  60 ++++-
 .../enumerable/EnumerableInterpretable.java        |  62 ++++--
 .../apache/calcite/interpreter/Interpreter.java    |  18 +-
 .../org/apache/calcite/runtime/SqlFunctions.java   |  20 +-
 .../calcite/schema/impl/ListTransientTable.java    |  81 ++++---
 .../apache/calcite/sql2rel/SqlToRelConverter.java  |  61 +++---
 .../main/java/org/apache/calcite/util/Holder.java  |   2 +-
 .../org/apache/calcite/util/mapping/Mappings.java  |  27 ++-
 .../calcite/adapter/csv/CsvFilterableTable.java    |  28 ++-
 .../calcite/adapter/csv/CsvScannableTable.java     |  26 ++-
 .../adapter/csv/CsvStreamScannableTable.java       |  26 ++-
 .../org/apache/calcite/example/maze/MazeTable.java |  31 ++-
 .../calcite/adapter/file/JsonScannableTable.java   |  21 +-
 .../geode/simple/GeodeSimpleScannableTable.java    |  35 ++-
 .../calcite/adapter/kafka/KafkaStreamTable.java    |  57 +++--
 .../apache/calcite/linq4j/EnumerableDefaults.java  |  49 +++--
 .../calcite/adapter/os/FilesTableFunction.java     | 243 ++++++++++++---------
 .../adapter/os/GitCommitsTableFunction.java        | 179 ++++++++-------
 .../apache/calcite/adapter/tpcds/TpcdsSchema.java  |  67 +++---
 20 files changed, 680 insertions(+), 428 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/adapter/clone/ArrayTable.java 
b/core/src/main/java/org/apache/calcite/adapter/clone/ArrayTable.java
index 8400ac21d6..fabbe6ea8d 100644
--- a/core/src/main/java/org/apache/calcite/adapter/clone/ArrayTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/clone/ArrayTable.java
@@ -87,12 +87,15 @@ class ArrayTable extends AbstractQueryableTable implements 
ScannableTable {
   }
 
   @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        final Content content = supplier.get();
-        return content.arrayEnumerator();
-      }
-    };
+    return new ArrayTableEnumerable();
+  }
+
+  /** Enumerable for {@link ArrayTable}. */
+  private class ArrayTableEnumerable extends AbstractEnumerable<@Nullable 
Object[]> {
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      final Content content = supplier.get();
+      return content.arrayEnumerator();
+    }
   }
 
   @Override public <T> Queryable<T> asQueryable(final QueryProvider 
queryProvider,
diff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumUtils.java 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumUtils.java
index 129180e584..80c46ec3f9 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumUtils.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumUtils.java
@@ -1086,12 +1086,29 @@ static Expression tumblingWindowSelector(
   public static Enumerable<@Nullable Object[]> sessionize(
       Enumerator<@Nullable Object[]> inputEnumerator,
       int indexOfWatermarkedColumn, int indexOfKeyColumn, long gap) {
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        return new SessionizationEnumerator(inputEnumerator,
-            indexOfWatermarkedColumn, indexOfKeyColumn, gap);
-      }
-    };
+    return new SessionizeEnumerable(inputEnumerator, indexOfWatermarkedColumn, 
indexOfKeyColumn,
+        gap);
+  }
+
+  /** Enumerable for {@link #sessionize(Enumerator, int, int, long)}. */
+  private static class SessionizeEnumerable extends 
AbstractEnumerable<@Nullable Object[]> {
+    private final Enumerator<@Nullable Object[]> inputEnumerator;
+    private final int indexOfWatermarkedColumn;
+    private final int indexOfKeyColumn;
+    private final long gap;
+
+    SessionizeEnumerable(Enumerator<@Nullable Object[]> inputEnumerator,
+        int indexOfWatermarkedColumn, int indexOfKeyColumn, long gap) {
+      this.inputEnumerator = inputEnumerator;
+      this.indexOfWatermarkedColumn = indexOfWatermarkedColumn;
+      this.indexOfKeyColumn = indexOfKeyColumn;
+      this.gap = gap;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      return new SessionizationEnumerator(inputEnumerator,
+          indexOfWatermarkedColumn, indexOfKeyColumn, gap);
+    }
   }
 
   /** Enumerator that converts rows into sessions separated by gaps. */
@@ -1234,12 +1251,31 @@ private static Pair<Long, Long> computeInitWindow(long 
ts, long gap) {
   public static Enumerable<@Nullable Object[]> hopping(
       Enumerator<@Nullable Object[]> inputEnumerator,
       int indexOfWatermarkedColumn, long emitFrequency, long windowSize, long 
offset) {
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        return new HopEnumerator(inputEnumerator,
-            indexOfWatermarkedColumn, emitFrequency, windowSize, offset);
-      }
-    };
+    return new HoppingEnumerable(inputEnumerator, indexOfWatermarkedColumn, 
emitFrequency,
+        windowSize, offset);
+  }
+
+  /** Enumerable for {@link #hopping(Enumerator, int, long, long, long)}. */
+  private static class HoppingEnumerable extends AbstractEnumerable<@Nullable 
Object[]> {
+    private final Enumerator<@Nullable Object[]> inputEnumerator;
+    private final int indexOfWatermarkedColumn;
+    private final long emitFrequency;
+    private final long windowSize;
+    private final long offset;
+
+    HoppingEnumerable(Enumerator<@Nullable Object[]> inputEnumerator,
+        int indexOfWatermarkedColumn, long emitFrequency, long windowSize, 
long offset) {
+      this.inputEnumerator = inputEnumerator;
+      this.indexOfWatermarkedColumn = indexOfWatermarkedColumn;
+      this.emitFrequency = emitFrequency;
+      this.windowSize = windowSize;
+      this.offset = offset;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      return new HopEnumerator(inputEnumerator,
+          indexOfWatermarkedColumn, emitFrequency, windowSize, offset);
+    }
   }
 
   /** Enumerator that computes HOP. */
diff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableInterpretable.java
 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableInterpretable.java
index 5f32ab1c71..7ed858b754 100644
--- 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableInterpretable.java
+++ 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableInterpretable.java
@@ -205,32 +205,50 @@ static ArrayBindable box(final Bindable bindable) {
 
       @Override public Enumerable<@Nullable Object[]> bind(DataContext 
dataContext) {
         final Enumerable<?> enumerable = bindable.bind(dataContext);
-        return new AbstractEnumerable<@Nullable Object[]>() {
-          @Override public Enumerator<@Nullable Object[]> enumerator() {
-            final Enumerator<?> enumerator = enumerable.enumerator();
-            return new Enumerator<@Nullable Object[]>() {
-              @Override public @Nullable Object[] current() {
-                return new Object[] {enumerator.current()};
-              }
-
-              @Override public boolean moveNext() {
-                return enumerator.moveNext();
-              }
-
-              @Override public void reset() {
-                enumerator.reset();
-              }
-
-              @Override public void close() {
-                enumerator.close();
-              }
-            };
-          }
-        };
+        return new BoxEnumerable(enumerable);
       }
     };
   }
 
+  /** Enumerable for {@link #box(Bindable)}. */
+  private static class BoxEnumerable extends AbstractEnumerable<@Nullable 
Object[]> {
+    private final Enumerable<?> enumerable;
+
+    BoxEnumerable(Enumerable<?> enumerable) {
+      this.enumerable = enumerable;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      final Enumerator<?> enumerator = enumerable.enumerator();
+      return new BoxEnumerator(enumerator);
+    }
+  }
+
+  /** Enumerator for {@link #box(Bindable)}. */
+  private static class BoxEnumerator implements Enumerator<@Nullable Object[]> 
{
+    private final Enumerator<?> enumerator;
+
+    BoxEnumerator(Enumerator<?> enumerator) {
+      this.enumerator = enumerator;
+    }
+
+    @Override public @Nullable Object[] current() {
+      return new Object[] { enumerator.current()};
+    }
+
+    @Override public boolean moveNext() {
+      return enumerator.moveNext();
+    }
+
+    @Override public void reset() {
+      enumerator.reset();
+    }
+
+    @Override public void close() {
+      enumerator.close();
+    }
+  }
+
   /** Interpreter node that reads from an {@link Enumerable}.
    *
    * <p>From the interpreter's perspective, it is a leaf node. */
diff --git a/core/src/main/java/org/apache/calcite/interpreter/Interpreter.java 
b/core/src/main/java/org/apache/calcite/interpreter/Interpreter.java
index 6bd8bde4c1..8bc82646a7 100644
--- a/core/src/main/java/org/apache/calcite/interpreter/Interpreter.java
+++ b/core/src/main/java/org/apache/calcite/interpreter/Interpreter.java
@@ -118,11 +118,19 @@ private static RelNode optimize(RelNode rootRel) {
       rows = Linq4j.iterableEnumerator(queue);
     }
 
-    return new TransformedEnumerator<Row, @Nullable Object[]>(rows) {
-      @Override protected @Nullable Object[] transform(Row row) {
-        return row.getValues();
-      }
-    };
+    return new InterpreterEnumerator(rows);
+  }
+
+  /** Enumerator for {@link Interpreter}. */
+  private static class InterpreterEnumerator
+      extends TransformedEnumerator<Row, @Nullable Object[]> {
+    InterpreterEnumerator(Enumerator<Row> rows) {
+      super(rows);
+    }
+
+    @Override protected @Nullable Object[] transform(Row row) {
+      return row.getValues();
+    }
   }
 
   @SuppressWarnings("CatchAndPrintStackTrace")
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java 
b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index 5dfad1da34..ed6a3ba16f 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -222,11 +222,21 @@ public class SqlFunctions {
       enumerators.add(Linq4j.enumerator((List) list));
     }
     final Enumerator<List<@Nullable Object>> product = 
Linq4j.product(enumerators);
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        return Linq4j.transform(product, List::toArray);
-      }
-    };
+    return new ArrayCartesianProductEnumerable(product);
+  }
+
+  /** Enumerable for {@link #arrayCartesianProduct(Object[])}. */
+  private static class ArrayCartesianProductEnumerable
+      extends AbstractEnumerable<@Nullable Object[]> {
+    private final Enumerator<List<@Nullable Object>> product;
+
+    ArrayCartesianProductEnumerable(Enumerator<List<@Nullable Object>> 
product) {
+      this.product = product;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      return Linq4j.transform(product, List::toArray);
+    }
   }
 
   /** Holds, for each thread, a map from sequence name to sequence current
diff --git 
a/core/src/main/java/org/apache/calcite/schema/impl/ListTransientTable.java 
b/core/src/main/java/org/apache/calcite/schema/impl/ListTransientTable.java
index a80556ceef..f04c9372b7 100644
--- a/core/src/main/java/org/apache/calcite/schema/impl/ListTransientTable.java
+++ b/core/src/main/java/org/apache/calcite/schema/impl/ListTransientTable.java
@@ -93,38 +93,57 @@ public ListTransientTable(String name, RelDataType rowType) 
{
 
     final AtomicBoolean cancelFlag = 
DataContext.Variable.CANCEL_FLAG.get(root);
 
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        return new Enumerator<@Nullable Object[]>() {
-          @SuppressWarnings({"rawtypes", "unchecked"})
-          private final List list = new ArrayList(rows);
-          private int i = -1;
-
-          // TODO cleaner way to handle non-array objects?
-          @Override public Object[] current() {
-            Object current = list.get(i);
-            return current != null && current.getClass().isArray()
-                ? (Object[]) current
-                : new Object[]{current};
-          }
-
-          @Override public boolean moveNext() {
-            if (cancelFlag != null && cancelFlag.get()) {
-              return false;
-            }
-
-            return ++i < list.size();
-          }
-
-          @Override public void reset() {
-            i = -1;
-          }
-
-          @Override public void close() {
-          }
-        };
+    return new ListTransientTableEnumerable(cancelFlag);
+  }
+
+  /** Enumerable for {@link ListTransientTable}. */
+  private class ListTransientTableEnumerable extends 
AbstractEnumerable<@Nullable Object[]> {
+    private final @Nullable AtomicBoolean cancelFlag;
+
+    ListTransientTableEnumerable(@Nullable AtomicBoolean cancelFlag) {
+      this.cancelFlag = cancelFlag;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      return new ListTransientTableEnumerator(cancelFlag);
+    }
+  }
+
+  /** Enumerator for {@link ListTransientTable}. */
+  private class ListTransientTableEnumerator implements Enumerator<@Nullable 
Object[]> {
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private final List list;
+    private final @Nullable AtomicBoolean cancelFlag;
+    private int i;
+
+    ListTransientTableEnumerator(@Nullable AtomicBoolean cancelFlag) {
+      this.cancelFlag = cancelFlag;
+      list = new ArrayList(rows);
+      i = -1;
+    }
+
+    // TODO cleaner way to handle non-array objects?
+    @Override public Object[] current() {
+      Object current = list.get(i);
+      return current != null && current.getClass().isArray()
+          ? (Object[]) current
+          : new Object[]{current};
+    }
+
+    @Override public boolean moveNext() {
+      if (cancelFlag != null && cancelFlag.get()) {
+        return false;
       }
-    };
+
+      return ++i < list.size();
+    }
+
+    @Override public void reset() {
+      i = -1;
+    }
+
+    @Override public void close() {
+    }
   }
 
   @Override public Expression getExpression(SchemaPlus schema, String 
tableName,
diff --git 
a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java 
b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
index f8b661c53f..182ed7a254 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -2967,32 +2967,7 @@ protected void convertMatchRecognize(Blackboard bb,
     final Set<String> patternVarsSet = new HashSet<>();
     SqlNode pattern = matchRecognize.getPattern();
     final SqlBasicVisitor<@Nullable RexNode> patternVarVisitor =
-        new SqlBasicVisitor<@Nullable RexNode>() {
-          @Override public RexNode visit(SqlCall call) {
-            List<SqlNode> operands = call.getOperandList();
-            List<RexNode> newOperands = new ArrayList<>();
-            for (SqlNode node : operands) {
-              RexNode arg = requireNonNull(node.accept(this), node::toString);
-              newOperands.add(arg);
-            }
-            return rexBuilder.makeCall(call.getParserPosition(),
-              validator().getUnknownType(), call.getOperator(), newOperands);
-          }
-
-          @Override public RexNode visit(SqlIdentifier id) {
-            assert id.isSimple();
-            patternVarsSet.add(id.getSimple());
-            return rexBuilder.makeLiteral(id.getSimple());
-          }
-
-          @Override public RexNode visit(SqlLiteral literal) {
-            if (literal instanceof SqlNumericLiteral) {
-              return 
rexBuilder.makeExactLiteral(BigDecimal.valueOf(literal.intValue(true)));
-            } else {
-              return rexBuilder.makeLiteral(literal.booleanValue());
-            }
-          }
-        };
+        new PatternVarVisitor(patternVarsSet);
     final RexNode patternNode = pattern.accept(patternVarVisitor);
     if (patternNode == null) {
       throw new AssertionError("pattern is not found in " + pattern);
@@ -7124,4 +7099,38 @@ private class MeasureBlackboard extends Blackboard {
       return super.lookupMeasure(identifier);
     }
   }
+
+  /** Visitor for {@link #convertMatchRecognize(Blackboard, 
SqlMatchRecognize)}. */
+  private class PatternVarVisitor extends SqlBasicVisitor<@Nullable RexNode> {
+    private final Set<String> patternVarsSet;
+
+    PatternVarVisitor(Set<String> patternVarsSet) {
+      this.patternVarsSet = patternVarsSet;
+    }
+
+    @Override public RexNode visit(SqlCall call) {
+      List<SqlNode> operands = call.getOperandList();
+      List<RexNode> newOperands = new ArrayList<>();
+      for (SqlNode node : operands) {
+        RexNode arg = requireNonNull(node.accept(this), node::toString);
+        newOperands.add(arg);
+      }
+      return rexBuilder.makeCall(call.getParserPosition(),
+        validator().getUnknownType(), call.getOperator(), newOperands);
+    }
+
+    @Override public RexNode visit(SqlIdentifier id) {
+      assert id.isSimple();
+      patternVarsSet.add(id.getSimple());
+      return rexBuilder.makeLiteral(id.getSimple());
+    }
+
+    @Override public RexNode visit(SqlLiteral literal) {
+      if (literal instanceof SqlNumericLiteral) {
+        return 
rexBuilder.makeExactLiteral(BigDecimal.valueOf(literal.intValue(true)));
+      } else {
+        return rexBuilder.makeLiteral(literal.booleanValue());
+      }
+    }
+  }
 }
diff --git a/core/src/main/java/org/apache/calcite/util/Holder.java 
b/core/src/main/java/org/apache/calcite/util/Holder.java
index bc5567e8c0..78aedcd3ee 100644
--- a/core/src/main/java/org/apache/calcite/util/Holder.java
+++ b/core/src/main/java/org/apache/calcite/util/Holder.java
@@ -64,6 +64,6 @@ public static <E> Holder<E> of(E e) {
   /** Creates a holder containing null. */
   @SuppressWarnings("ConstantConditions")
   public static <E> Holder<@Nullable E> empty() {
-    return new Holder<@Nullable E>(null);
+    return new Holder<>(null);
   }
 }
diff --git a/core/src/main/java/org/apache/calcite/util/mapping/Mappings.java 
b/core/src/main/java/org/apache/calcite/util/mapping/Mappings.java
index 82a3c74039..0139473bc5 100644
--- a/core/src/main/java/org/apache/calcite/util/mapping/Mappings.java
+++ b/core/src/main/java/org/apache/calcite/util/mapping/Mappings.java
@@ -319,16 +319,25 @@ public static <T> List<T> permute(final List<T> list,
    */
   @CheckReturnValue
   public static List<@Nullable Integer> asList(final TargetMapping mapping) {
-    return new AbstractList<@Nullable Integer>() {
-      @Override public @Nullable Integer get(int source) {
-        int target = mapping.getTargetOpt(source);
-        return target < 0 ? null : target;
-      }
+    return new MappingsList(mapping);
+  }
 
-      @Override public int size() {
-        return mapping.getSourceCount();
-      }
-    };
+  /** List view of a {@link TargetMapping}. */
+  private static class MappingsList extends AbstractList<@Nullable Integer> {
+    private final TargetMapping mapping;
+
+    MappingsList(TargetMapping mapping) {
+      this.mapping = mapping;
+    }
+
+    @Override public @Nullable Integer get(int source) {
+      int target = mapping.getTargetOpt(source);
+      return target < 0 ? null : target;
+    }
+
+    @Override public int size() {
+      return mapping.getSourceCount();
+    }
   }
 
   /**
diff --git 
a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvFilterableTable.java
 
b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvFilterableTable.java
index ee621740f9..212aff0ce5 100644
--- 
a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvFilterableTable.java
+++ 
b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvFilterableTable.java
@@ -63,12 +63,28 @@ public CsvFilterableTable(Source source,
     filters.removeIf(filter -> addFilter(filter, filterValues));
     final List<Integer> fields = ImmutableIntList.identity(fieldTypes.size());
     final AtomicBoolean cancelFlag = 
DataContext.Variable.CANCEL_FLAG.get(root);
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        return new CsvEnumerator<>(source, cancelFlag, false, filterValues,
-            CsvEnumerator.arrayConverter(fieldTypes, fields, false), ',');
-      }
-    };
+    return new CsvFilterableTableEnumerable(cancelFlag, filterValues, 
fieldTypes, fields);
+  }
+
+  /** Enumerable for {@link CsvFilterableTable}. */
+  private class CsvFilterableTableEnumerable extends 
AbstractEnumerable<@Nullable Object[]> {
+    private final AtomicBoolean cancelFlag;
+    private final @Nullable String[] filterValues;
+    private final List<RelDataType> fieldTypes;
+    private final List<Integer> fields;
+
+    CsvFilterableTableEnumerable(AtomicBoolean cancelFlag, @Nullable String[] 
filterValues,
+        List<RelDataType> fieldTypes, List<Integer> fields) {
+      this.cancelFlag = cancelFlag;
+      this.filterValues = filterValues;
+      this.fieldTypes = fieldTypes;
+      this.fields = fields;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      return new CsvEnumerator<>(source, cancelFlag, false, filterValues,
+          CsvEnumerator.arrayConverter(fieldTypes, fields, false), ',');
+    }
   }
 
   private static boolean addFilter(RexNode filter, @Nullable Object[] 
filterValues) {
diff --git 
a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvScannableTable.java
 
b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvScannableTable.java
index 836af81373..046825bd35 100644
--- 
a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvScannableTable.java
+++ 
b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvScannableTable.java
@@ -55,11 +55,25 @@ public class CsvScannableTable extends CsvTable
     final List<RelDataType> fieldTypes = getFieldTypes(typeFactory);
     final List<Integer> fields = ImmutableIntList.identity(fieldTypes.size());
     final AtomicBoolean cancelFlag = 
DataContext.Variable.CANCEL_FLAG.get(root);
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        return new CsvEnumerator<>(source, cancelFlag, false, null,
-            CsvEnumerator.arrayConverter(fieldTypes, fields, false), ',');
-      }
-    };
+    return new CsvScannableTableEnumerable(cancelFlag, fieldTypes, fields);
+  }
+
+  /** Enumerable for {@link CsvScannableTable}. */
+  private class CsvScannableTableEnumerable extends 
AbstractEnumerable<@Nullable Object[]> {
+    private final AtomicBoolean cancelFlag;
+    private final List<RelDataType> fieldTypes;
+    private final List<Integer> fields;
+
+    CsvScannableTableEnumerable(AtomicBoolean cancelFlag, List<RelDataType> 
fieldTypes,
+        List<Integer> fields) {
+      this.cancelFlag = cancelFlag;
+      this.fieldTypes = fieldTypes;
+      this.fields = fields;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      return new CsvEnumerator<>(source, cancelFlag, false, null,
+          CsvEnumerator.arrayConverter(fieldTypes, fields, false), ',');
+    }
   }
 }
diff --git 
a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvStreamScannableTable.java
 
b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvStreamScannableTable.java
index 7c0d574cc7..98ab6a03bc 100644
--- 
a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvStreamScannableTable.java
+++ 
b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvStreamScannableTable.java
@@ -62,12 +62,26 @@ public class CsvStreamScannableTable extends 
CsvScannableTable
     final List<RelDataType> fieldTypes = getFieldTypes(typeFactory);
     final List<Integer> fields = ImmutableIntList.identity(fieldTypes.size());
     final AtomicBoolean cancelFlag = 
DataContext.Variable.CANCEL_FLAG.get(root);
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        return new CsvEnumerator<>(source, cancelFlag, true, null,
-            CsvEnumerator.arrayConverter(fieldTypes, fields, true), ',');
-      }
-    };
+    return new CsvStreamScannableTableEnumerable(cancelFlag, fieldTypes, 
fields);
+  }
+
+  /** Enumerable for {@link CsvStreamScannableTable}. */
+  private class CsvStreamScannableTableEnumerable extends 
AbstractEnumerable<@Nullable Object[]> {
+    private final AtomicBoolean cancelFlag;
+    private final List<RelDataType> fieldTypes;
+    private final List<Integer> fields;
+
+    CsvStreamScannableTableEnumerable(AtomicBoolean cancelFlag, 
List<RelDataType> fieldTypes,
+        List<Integer> fields) {
+      this.cancelFlag = cancelFlag;
+      this.fieldTypes = fieldTypes;
+      this.fields = fields;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      return new CsvEnumerator<>(source, cancelFlag, true, null,
+          CsvEnumerator.arrayConverter(fieldTypes, fields, true), ',');
+    }
   }
 
   @Override public Table stream() {
diff --git 
a/example/function/src/main/java/org/apache/calcite/example/maze/MazeTable.java 
b/example/function/src/main/java/org/apache/calcite/example/maze/MazeTable.java
index 0818cc0a74..1068bf25cb 100644
--- 
a/example/function/src/main/java/org/apache/calcite/example/maze/MazeTable.java
+++ 
b/example/function/src/main/java/org/apache/calcite/example/maze/MazeTable.java
@@ -95,17 +95,26 @@ public static ScannableTable solve(int width, int height, 
int seed) {
     if (Maze.DEBUG) {
       maze.print(pw, true);
     }
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        final Set<Integer> solutionSet;
-        if (solution) {
-          solutionSet = maze.solve(0, 0);
-        } else {
-          solutionSet = null;
-        }
-        return Linq4j.transform(maze.enumerator(solutionSet),
-            s -> new Object[] {s});
+    return new MazeTableEnumerable(maze);
+  }
+
+  /** Enumerable for {@link MazeTable}. */
+  private class MazeTableEnumerable extends AbstractEnumerable<@Nullable 
Object[]> {
+    private final Maze maze;
+
+    MazeTableEnumerable(Maze maze) {
+      this.maze = maze;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      final Set<Integer> solutionSet;
+      if (solution) {
+        solutionSet = maze.solve(0, 0);
+      } else {
+        solutionSet = null;
       }
-    };
+      return Linq4j.transform(maze.enumerator(solutionSet),
+          s -> new Object[] {s});
+    }
   }
 }
diff --git 
a/file/src/main/java/org/apache/calcite/adapter/file/JsonScannableTable.java 
b/file/src/main/java/org/apache/calcite/adapter/file/JsonScannableTable.java
index 8f9d2bde29..f0f2373963 100644
--- a/file/src/main/java/org/apache/calcite/adapter/file/JsonScannableTable.java
+++ b/file/src/main/java/org/apache/calcite/adapter/file/JsonScannableTable.java
@@ -46,11 +46,20 @@ public JsonScannableTable(Source source) {
   }
 
   @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        JavaTypeFactory typeFactory = root.getTypeFactory();
-        return new JsonEnumerator(getDataList(typeFactory));
-      }
-    };
+    return new JsonScannableTableEnumerable(root);
+  }
+
+  /** Enumerable for {@link JsonScannableTable}. */
+  private class JsonScannableTableEnumerable extends 
AbstractEnumerable<@Nullable Object[]> {
+    private final DataContext root;
+
+    JsonScannableTableEnumerable(DataContext root) {
+      this.root = root;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      JavaTypeFactory typeFactory = root.getTypeFactory();
+      return new JsonEnumerator(getDataList(typeFactory));
+    }
   }
 }
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/simple/GeodeSimpleScannableTable.java
 
b/geode/src/main/java/org/apache/calcite/adapter/geode/simple/GeodeSimpleScannableTable.java
index f48698c7c6..1594b30e27 100644
--- 
a/geode/src/main/java/org/apache/calcite/adapter/geode/simple/GeodeSimpleScannableTable.java
+++ 
b/geode/src/main/java/org/apache/calcite/adapter/geode/simple/GeodeSimpleScannableTable.java
@@ -58,18 +58,29 @@ public GeodeSimpleScannableTable(String regionName, 
RelDataType relDataType,
   }
 
   @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        return new GeodeSimpleEnumerator<@Nullable Object[]>(clientCache, 
regionName) {
-          @Override public @Nullable Object[] convert(Object obj) {
-            Object values = convertToRowValues(relDataType.getFieldList(), 
obj);
-            if (values instanceof Object[]) {
-              return (Object[]) values;
-            }
-            return new Object[]{values};
-          }
-        };
+    return new GeodeSimpleScannableTableEnumerable();
+  }
+
+  /** Enumerable for {@link GeodeSimpleScannableTable}. */
+  private class GeodeSimpleScannableTableEnumerable extends 
AbstractEnumerable<@Nullable Object[]> {
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      return new GeodeSimpleScannableTableEnumerator();
+    }
+  }
+
+  /** Enumerator for {@link GeodeSimpleScannableTable}. */
+  private class GeodeSimpleScannableTableEnumerator
+      extends GeodeSimpleEnumerator<@Nullable Object[]> {
+    GeodeSimpleScannableTableEnumerator() {
+      super(GeodeSimpleScannableTable.this.clientCache, 
GeodeSimpleScannableTable.this.regionName);
+    }
+
+    @Override public @Nullable Object[] convert(Object obj) {
+      Object values = convertToRowValues(relDataType.getFieldList(), obj);
+      if (values instanceof Object[]) {
+        return (Object[]) values;
       }
-    };
+      return new Object[]{values};
+    }
   }
 }
diff --git 
a/kafka/src/main/java/org/apache/calcite/adapter/kafka/KafkaStreamTable.java 
b/kafka/src/main/java/org/apache/calcite/adapter/kafka/KafkaStreamTable.java
index e432eb8039..f73941c941 100644
--- a/kafka/src/main/java/org/apache/calcite/adapter/kafka/KafkaStreamTable.java
+++ b/kafka/src/main/java/org/apache/calcite/adapter/kafka/KafkaStreamTable.java
@@ -60,31 +60,40 @@ public class KafkaStreamTable implements ScannableTable, 
StreamableTable {
 
   @Override public Enumerable<@Nullable Object[]> scan(final DataContext root) 
{
     final AtomicBoolean cancelFlag = 
DataContext.Variable.CANCEL_FLAG.get(root);
-    return new AbstractEnumerable<@Nullable Object[]>() {
-      @Override public Enumerator<@Nullable Object[]> enumerator() {
-        if (tableOptions.getConsumer() != null) {
-          return new KafkaMessageEnumerator(tableOptions.getConsumer(),
-              tableOptions.getRowConverter(), cancelFlag);
-        }
-
-        Properties consumerConfig = new Properties();
-        consumerConfig.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
-            tableOptions.getBootstrapServers());
-        // by default it's <byte[], byte[]>
-        consumerConfig.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
-            "org.apache.kafka.common.serialization.ByteArrayDeserializer");
-        consumerConfig.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
-            "org.apache.kafka.common.serialization.ByteArrayDeserializer");
-
-        if (tableOptions.getConsumerParams() != null) {
-          consumerConfig.putAll(tableOptions.getConsumerParams());
-        }
-        Consumer consumer = new KafkaConsumer<>(consumerConfig);
-        
consumer.subscribe(Collections.singletonList(tableOptions.getTopicName()));
-
-        return new KafkaMessageEnumerator(consumer, 
tableOptions.getRowConverter(), cancelFlag);
+    return new KafkaStreamTableEnumerable(cancelFlag);
+  }
+
+  /** Enumerable for {@link KafkaStreamTable}. */
+  private class KafkaStreamTableEnumerable extends 
AbstractEnumerable<@Nullable Object[]> {
+    private final AtomicBoolean cancelFlag;
+
+    KafkaStreamTableEnumerable(AtomicBoolean cancelFlag) {
+      this.cancelFlag = cancelFlag;
+    }
+
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      if (tableOptions.getConsumer() != null) {
+        return new KafkaMessageEnumerator(tableOptions.getConsumer(),
+            tableOptions.getRowConverter(), cancelFlag);
       }
-    };
+
+      Properties consumerConfig = new Properties();
+      consumerConfig.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
+          tableOptions.getBootstrapServers());
+      // by default it's <byte[], byte[]>
+      consumerConfig.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
+          "org.apache.kafka.common.serialization.ByteArrayDeserializer");
+      consumerConfig.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
+          "org.apache.kafka.common.serialization.ByteArrayDeserializer");
+
+      if (tableOptions.getConsumerParams() != null) {
+        consumerConfig.putAll(tableOptions.getConsumerParams());
+      }
+      Consumer consumer = new KafkaConsumer<>(consumerConfig);
+      
consumer.subscribe(Collections.singletonList(tableOptions.getTopicName()));
+
+      return new KafkaMessageEnumerator(consumer, 
tableOptions.getRowConverter(), cancelFlag);
+    }
   }
 
   @Override public RelDataType getRowType(final RelDataTypeFactory 
typeFactory) {
diff --git 
a/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java 
b/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
index 0ff4afddb6..0eca4b6d52 100644
--- a/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
+++ b/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
@@ -4879,32 +4879,35 @@ protected WrapMap(Function0<Map<Wrapped<K>, V>> 
mapProvider, EqualityComparer<K>
     }
 
     @Override public Set<Entry<@KeyFor("this") K, V>> entrySet() {
-      return new AbstractSet<Entry<@KeyFor("this") K, V>>() {
-        @SuppressWarnings("override.return.invalid")
-        @Override public Iterator<Entry<K, V>> iterator() {
-          final Iterator<Entry<Wrapped<K>, V>> iterator =
-              map.entrySet().iterator();
-
-          return new Iterator<Entry<K, V>>() {
-            @Override public boolean hasNext() {
-              return iterator.hasNext();
-            }
+      return new WrapMapEntrySet();
+    }
 
-            @Override public Entry<K, V> next() {
-              Entry<Wrapped<K>, V> next = iterator.next();
-              return new SimpleEntry<>(next.getKey().element, next.getValue());
-            }
+    /** EntrySet for {@link WrapMap}. */
+    private class WrapMapEntrySet extends AbstractSet<Entry<@KeyFor("this") K, 
V>> {
+      @SuppressWarnings("override.return.invalid")
+      @Override public Iterator<Entry<K, V>> iterator() {
+        final Iterator<Entry<Wrapped<K>, V>> iterator =
+            map.entrySet().iterator();
 
-            @Override public void remove() {
-              iterator.remove();
-            }
-          };
-        }
+        return new Iterator<Entry<K, V>>() {
+          @Override public boolean hasNext() {
+            return iterator.hasNext();
+          }
 
-        @Override public int size() {
-          return map.size();
-        }
-      };
+          @Override public Entry<K, V> next() {
+            Entry<Wrapped<K>, V> next = iterator.next();
+            return new SimpleEntry<>(next.getKey().element, next.getValue());
+          }
+
+          @Override public void remove() {
+            iterator.remove();
+          }
+        };
+      }
+
+      @Override public int size() {
+        return map.size();
+      }
     }
 
     @SuppressWarnings("contracts.conditional.postcondition.not.satisfied")
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/FilesTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/FilesTableFunction.java
index 3df9498c35..cd7ca9e8b8 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/FilesTableFunction.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/FilesTableFunction.java
@@ -217,121 +217,148 @@ private boolean isGnuStat() {
         default:
           enumerable = sourceLinux();
         }
-        return new AbstractEnumerable<@Nullable Object[]>() {
-          @Override public Enumerator<@Nullable Object[]> enumerator() {
-            final Enumerator<String> e = enumerable.enumerator();
-            return new Enumerator<@Nullable Object[]>() {
-              @Nullable Object @Nullable [] current;
+        return new FilesTableFunctionEnumerable(enumerable, fieldNames, 
osName);
+      }
+    };
+  }
 
-              @Override public Object[] current() {
-                return requireNonNull(current, "current");
-              }
+  /** Enumerable for {@link FilesTableFunction}. */
+  private static class FilesTableFunctionEnumerable extends 
AbstractEnumerable<@Nullable Object[]> {
+    private final Enumerable<String> enumerable;
+    private final List<String> fieldNames;
+    private final String osName;
 
-              @Override public boolean moveNext() {
-                current = new Object[fieldNames.size()];
-                for (int i = 0; i < current.length; i++) {
-                  if (!e.moveNext()) {
-                    return false;
-                  }
-                  final String v = e.current();
-                  try {
-                    current[i] = field(fieldNames.get(i), v);
-                  } catch (RuntimeException e) {
-                    throw new RuntimeException("while parsing value ["
-                        + v + "] of field [" + fieldNames.get(i)
-                        + "] in line [" + Arrays.toString(current) + "]", e);
-                  }
-                }
-                switch (osName) {
-                case "Mac OS X":
-                  // post-process fields: compute filename, dir_name, depth 
from path
-                  String path = requireNonNull((String) current[14]);
-                  if (".".equals(path)) {
-                    current[14] = path = "";
-                    current[3] = 0; // depth
-                  } else if (path.startsWith("./")) {
-                    current[14] = path = path.substring(2);
-                    current[3] = count(path, '/') + 1; // depth
-                  } else {
-                    current[3] = count(path, '/'); // depth
-                  }
-                  final int slash = path.lastIndexOf('/');
-                  if (slash >= 0) {
-                    current[5] = path.substring(slash + 1); // filename
-                    current[9] = path.substring(0, slash); // dir_name
-                  } else {
-                    current[5] = path; // filename
-                    current[9] = ""; // dir_name
-                  }
+    FilesTableFunctionEnumerable(Enumerable<String> enumerable, List<String> 
fieldNames,
+        String osName) {
+      this.enumerable = enumerable;
+      this.fieldNames = fieldNames;
+      this.osName = osName;
+    }
 
-                  // detect output format: BSD outputs single chars, GNU 
outputs words
-                  final String type = requireNonNull((String) current[19]);
-                  if (type.length() > 1) {
-                    // GNU stat outputs descriptive types like "regular file", 
"directory"
-                    current[19] = type.contains("directory") ? "d"
-                        : type.contains("regular") ? "f"
-                        : type.contains("symbolic") ? "l"
-                        : type.contains("block") ? "b"
-                        : type.contains("character") ? "c"
-                        : type.contains("fifo") ? "p"
-                        : type.contains("socket") ? "s"
-                        : "?";
-                  } else {
-                    // BSD stat outputs single characters: "/" "*" "@" or ""
-                    current[19] = "/".equals(type) ? "d"
-                        : "".equals(type) || "*".equals(type) ? "f"
-                        : "@".equals(type) ? "l"
-                        : type;
-                  }
-                  break;
-                default:
-                  break;
-                }
-                return true;
-              }
+    @Override public Enumerator<@Nullable Object[]> enumerator() {
+      final Enumerator<String> e = enumerable.enumerator();
+      return new FilesTableFunctionEnumerator(fieldNames, e, osName);
+    }
+  }
 
-              private int count(String s, char c) {
-                int n = 0;
-                for (int i = 0, len = s.length(); i < len; i++) {
-                  if (s.charAt(i) == c) {
-                    ++n;
-                  }
-                }
-                return n;
-              }
+  /** Enumerator for {@link FilesTableFunction}. */
+  private static class FilesTableFunctionEnumerator implements 
Enumerator<@Nullable Object[]> {
+    private final List<String> fieldNames;
+    private final Enumerator<String> e;
+    private final String osName;
+    @Nullable Object @Nullable [] current;
 
-              @Override public void reset() {
-                throw new UnsupportedOperationException();
-              }
+    FilesTableFunctionEnumerator(List<String> fieldNames, Enumerator<String> e,
+        String osName) {
+      this.fieldNames = fieldNames;
+      this.e = e;
+      this.osName = osName;
+    }
 
-              @Override public void close() {
-                e.close();
-              }
+    @Override public Object[] current() {
+      return requireNonNull(current, "current");
+    }
 
-              private Object field(String field, String value) {
-                switch (field) {
-                case "block_count":
-                case "depth":
-                case "device":
-                case "gid":
-                case "uid":
-                case "hard":
-                  return Integer.valueOf(value);
-                case "inode":
-                case "size":
-                  return Long.valueOf(value);
-                case "access_time":
-                case "change_time":
-                case "mod_time":
-                  return new BigDecimal(value).multiply(THOUSAND).longValue();
-                default:
-                  return value;
-                }
-              }
-            };
-          }
-        };
+    @Override public boolean moveNext() {
+      current = new Object[fieldNames.size()];
+      for (int i = 0; i < current.length; i++) {
+        if (!e.moveNext()) {
+          return false;
+        }
+        final String v = e.current();
+        try {
+          current[i] = field(fieldNames.get(i), v);
+        } catch (RuntimeException e) {
+          throw new RuntimeException("while parsing value ["
+              + v + "] of field [" + fieldNames.get(i)
+              + "] in line [" + Arrays.toString(current) + "]", e);
+        }
       }
-    };
+      switch (osName) {
+      case "Mac OS X":
+        // post-process fields: compute filename, dir_name, depth from path
+        String path = requireNonNull((String) current[14]);
+        if (".".equals(path)) {
+          current[14] = path = "";
+          current[3] = 0; // depth
+        } else if (path.startsWith("./")) {
+          current[14] = path = path.substring(2);
+          current[3] = count(path, '/') + 1; // depth
+        } else {
+          current[3] = count(path, '/'); // depth
+        }
+        final int slash = path.lastIndexOf('/');
+        if (slash >= 0) {
+          current[5] = path.substring(slash + 1); // filename
+          current[9] = path.substring(0, slash); // dir_name
+        } else {
+          current[5] = path; // filename
+          current[9] = ""; // dir_name
+        }
+
+        // detect output format: BSD outputs single chars, GNU outputs words
+        final String type = requireNonNull((String) current[19]);
+        if (type.length() > 1) {
+          // GNU stat outputs descriptive types like "regular file", 
"directory"
+          current[19] = type.contains("directory") ? "d"
+              : type.contains("regular") ? "f"
+              : type.contains("symbolic") ? "l"
+              : type.contains("block") ? "b"
+              : type.contains("character") ? "c"
+              : type.contains("fifo") ? "p"
+              : type.contains("socket") ? "s"
+              : "?";
+        } else {
+          // BSD stat outputs single characters: "/" "*" "@" or ""
+          current[19] = "/".equals(type) ? "d"
+              : "".equals(type) || "*".equals(type) ? "f"
+              : "@".equals(type) ? "l"
+              : type;
+        }
+        break;
+      default:
+        break;
+      }
+      return true;
+    }
+
+    private int count(String s, char c) {
+      int n = 0;
+      for (int i = 0, len = s.length(); i < len; i++) {
+        if (s.charAt(i) == c) {
+          ++n;
+        }
+      }
+      return n;
+    }
+
+    @Override public void reset() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override public void close() {
+      e.close();
+    }
+
+    private Object field(String field, String value) {
+      switch (field) {
+      case "block_count":
+      case "depth":
+      case "device":
+      case "gid":
+      case "uid":
+      case "hard":
+        return Integer.valueOf(value);
+      case "inode":
+      case "size":
+        return Long.valueOf(value);
+      case "access_time":
+      case "change_time":
+      case "mod_time":
+        return new BigDecimal(value).multiply(THOUSAND).longValue();
+      default:
+        return value;
+      }
+    }
   }
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/GitCommitsTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/GitCommitsTableFunction.java
index 0f31e6763c..2e58957291 100644
--- 
a/plus/src/main/java/org/apache/calcite/adapter/os/GitCommitsTableFunction.java
+++ 
b/plus/src/main/java/org/apache/calcite/adapter/os/GitCommitsTableFunction.java
@@ -51,91 +51,110 @@ public static ScannableTable eval(boolean b) {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
         final Enumerable<String> enumerable =
             Processes.processLines("git", "log", "--pretty=raw");
-        return new AbstractEnumerable<@Nullable Object[]>() {
-          @Override public Enumerator<@Nullable Object[]> enumerator() {
-            final Enumerator<String> e = enumerable.enumerator();
-            return new Enumerator<@Nullable Object[]>() {
-              private @Nullable Object @Nullable [] objects;
-              private final StringBuilder b = new StringBuilder();
-
-              @Override public @Nullable Object[] current() {
-                if (objects == null) {
-                  throw new NoSuchElementException();
-                }
-                return objects;
-              }
+        return new GitCommitsTableFunctionEnumerable(enumerable);
+      }
 
-              @Override public boolean moveNext() {
-                if (!e.moveNext()) {
-                  objects = null;
-                  return false;
-                }
-                objects = new Object[9];
-                for (;;) {
-                  final String line = e.current();
-                  if (line.isEmpty()) {
-                    break; // next line will be start of comments
-                  }
-                  if (line.startsWith("commit ")) {
-                    objects[0] = line.substring("commit ".length());
-                  } else if (line.startsWith("tree ")) {
-                    objects[1] = line.substring("tree ".length());
-                  } else if (line.startsWith("parent ")) {
-                    if (objects[2] == null) {
-                      objects[2] = line.substring("parent ".length());
-                    } else {
-                      objects[3] = line.substring("parent ".length());
-                    }
-                  } else if (line.startsWith("author ")) {
-                    objects[4] =
-                        line.substring("author ".length(),
-                            line.length() - TS_OFF.length() - 1);
-                    objects[5] =
-                        parseLong(
-                            line.substring(line.length() - TS_OFF.length(),
-                            line.length() - OFF.length() - 1)) * 1000;
-                  } else if (line.startsWith("committer ")) {
-                    objects[6] =
-                        line.substring("committer ".length(),
-                            line.length() - TS_OFF.length() - 1);
-                    objects[7] =
-                        parseLong(
-                            line.substring(line.length() - TS_OFF.length(),
-                            line.length() - OFF.length() - 1)) * 1000;
-                  }
-                  if (!e.moveNext()) {
-                    // We have a row, and it's the last because input is empty
-                    return true;
-                  }
-                }
-                for (;;) {
-                  if (!e.moveNext()) {
-                    // We have a row, and it's the last because input is empty
-                    objects[8] = b.toString();
-                    b.setLength(0);
-                    return true;
-                  }
-                  final String line = e.current();
-                  if (line.isEmpty()) {
-                    // We're seeing the empty line at the end of message
-                    objects[8] = b.toString();
-                    b.setLength(0);
-                    return true;
-                  }
-                  b.append(line.substring("    ".length())).append("\n");
-                }
-              }
+      /** Enumerable for {@link GitCommitsTableFunction}. */
+      class GitCommitsTableFunctionEnumerable
+          extends AbstractEnumerable<@Nullable Object[]> {
+        private final Enumerable<String> enumerable;
 
-              @Override public void reset() {
-                throw new UnsupportedOperationException();
-              }
+        GitCommitsTableFunctionEnumerable(Enumerable<String> enumerable) {
+          this.enumerable = enumerable;
+        }
+
+        @Override public Enumerator<@Nullable Object[]> enumerator() {
+          final Enumerator<String> e = enumerable.enumerator();
+          return new GitCommitsTableFunctionEnumerator(e);
+        }
+      }
+
+      /** Enumerator for {@link GitCommitsTableFunction}. */
+      class GitCommitsTableFunctionEnumerator implements Enumerator<@Nullable 
Object[]> {
+        private final Enumerator<String> e;
+        private @Nullable Object @Nullable [] objects;
+        private final StringBuilder b;
 
-              @Override public void close() {
-                e.close();
+        GitCommitsTableFunctionEnumerator(Enumerator<String> e) {
+          this.e = e;
+          b = new StringBuilder();
+        }
+
+        @Override public @Nullable Object[] current() {
+          if (objects == null) {
+            throw new NoSuchElementException();
+          }
+          return objects;
+        }
+
+        @Override public boolean moveNext() {
+          if (!e.moveNext()) {
+            objects = null;
+            return false;
+          }
+          objects = new Object[9];
+          for (;;) {
+            final String line = e.current();
+            if (line.isEmpty()) {
+              break; // next line will be start of comments
+            }
+            if (line.startsWith("commit ")) {
+              objects[0] = line.substring("commit ".length());
+            } else if (line.startsWith("tree ")) {
+              objects[1] = line.substring("tree ".length());
+            } else if (line.startsWith("parent ")) {
+              if (objects[2] == null) {
+                objects[2] = line.substring("parent ".length());
+              } else {
+                objects[3] = line.substring("parent ".length());
               }
-            };
+            } else if (line.startsWith("author ")) {
+              objects[4] =
+                  line.substring("author ".length(),
+                      line.length() - TS_OFF.length() - 1);
+              objects[5] =
+                  parseLong(
+                      line.substring(line.length() - TS_OFF.length(),
+                          line.length() - OFF.length() - 1)) * 1000;
+            } else if (line.startsWith("committer ")) {
+              objects[6] =
+                  line.substring("committer ".length(),
+                      line.length() - TS_OFF.length() - 1);
+              objects[7] =
+                  parseLong(
+                      line.substring(line.length() - TS_OFF.length(),
+                          line.length() - OFF.length() - 1)) * 1000;
+            }
+            if (!e.moveNext()) {
+              // We have a row, and it's the last because input is empty
+              return true;
+            }
           }
-        };
+          for (;;) {
+            if (!e.moveNext()) {
+              // We have a row, and it's the last because input is empty
+              objects[8] = b.toString();
+              b.setLength(0);
+              return true;
+            }
+            final String line = e.current();
+            if (line.isEmpty()) {
+              // We're seeing the empty line at the end of message
+              objects[8] = b.toString();
+              b.setLength(0);
+              return true;
+            }
+            b.append(line.substring("    ".length())).append("\n");
+          }
+        }
+
+        @Override public void reset() {
+          throw new UnsupportedOperationException();
+        }
+
+        @Override public void close() {
+          e.close();
+        }
       }
 
       @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/tpcds/TpcdsSchema.java 
b/plus/src/main/java/org/apache/calcite/adapter/tpcds/TpcdsSchema.java
index 548c20f8c2..20ae7d3145 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/tpcds/TpcdsSchema.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/tpcds/TpcdsSchema.java
@@ -158,36 +158,45 @@ private class TpcdsQueryableTable<E extends 
com.teradata.tpcds.Table>
     @Override public <T> Queryable<T> asQueryable(final QueryProvider 
queryProvider,
         final SchemaPlus schema, final String tableName) {
       //noinspection unchecked
-      return (Queryable) new AbstractTableQueryable<@Nullable 
Object[]>(queryProvider,
-          schema, this, tableName) {
-        @Override public Enumerator<@Nullable Object[]> enumerator() {
-          final Session session =
-              Session.getDefaultSession()
-                  .withTable(tpcdsTable)
-                  .withScale(scaleFactor);
-          final Results results = Results.constructResults(tpcdsTable, 
session);
-          return Linq4j.asEnumerable(results)
-              .selectMany(
-                  new Function1<List<List<@Nullable String>>, 
Enumerable<@Nullable Object[]>>() {
-                    final Column[] columns = tpcdsTable.getColumns();
-
-                    @Override public Enumerable<@Nullable Object[]> apply(
-                        List<List<@Nullable String>> inRows) {
-                      final List<@Nullable Object[]> rows = new ArrayList<>();
-                      for (List<@Nullable String> strings : inRows) {
-                        final @Nullable Object[] values = new 
Object[columns.length];
-                        for (int i = 0; i < strings.size(); i++) {
-                          values[i] = convert(strings.get(i), columns[i]);
-                        }
-                        rows.add(values);
-                      }
-                      return Linq4j.asEnumerable(rows);
-                    }
-
-                  })
-              .enumerator();
+      return (Queryable) new TpcdsSchemaQueryable(queryProvider, schema, 
tableName);
+    }
+
+    /** Queryable for {@link TpcdsSchema}. */
+    private class TpcdsSchemaQueryable extends 
AbstractTableQueryable<@Nullable Object[]> {
+      TpcdsSchemaQueryable(QueryProvider queryProvider, SchemaPlus schema,
+          String tableName) {
+        super(queryProvider, schema, TpcdsQueryableTable.this, tableName);
+      }
+
+      @Override public Enumerator<@Nullable Object[]> enumerator() {
+        final Session session =
+            Session.getDefaultSession()
+                .withTable(tpcdsTable)
+                .withScale(scaleFactor);
+        final Results results = Results.constructResults(tpcdsTable, session);
+        return Linq4j.asEnumerable(results)
+            .selectMany(new TpcdsSchemaSelector())
+            .enumerator();
+      }
+    }
+
+    /** Selector for {@link TpcdsSchema}. */
+    private class TpcdsSchemaSelector
+        implements Function1<List<List<@Nullable String>>, 
Enumerable<@Nullable Object[]>> {
+      final Column[] columns = tpcdsTable.getColumns();
+
+      @Override public Enumerable<@Nullable Object[]> apply(
+          List<List<@Nullable String>> inRows) {
+        final List<@Nullable Object[]> rows = new ArrayList<>();
+        for (List<@Nullable String> strings : inRows) {
+          final @Nullable Object[] values = new Object[columns.length];
+          for (int i = 0; i < strings.size(); i++) {
+            values[i] = convert(strings.get(i), columns[i]);
+          }
+          rows.add(values);
         }
-      };
+        return Linq4j.asEnumerable(rows);
+      }
     }
 
     @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {

Reply via email to