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

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


The following commit(s) were added to refs/heads/master by this push:
     new 32babcb90 [CALCITE-5079] Update code demo of tutorial
32babcb90 is described below

commit 32babcb90aa5940bdd75760021abab6459a9cca4
Author: Ada Wang <wang4lun...@gmail.com>
AuthorDate: Fri Apr 1 14:29:47 2022 +0800

    [CALCITE-5079] Update code demo of tutorial
---
 site/_docs/tutorial.md | 81 ++++++++++++++++++++++++++++----------------------
 1 file changed, 45 insertions(+), 36 deletions(-)

diff --git a/site/_docs/tutorial.md b/site/_docs/tutorial.md
index 5eefce347..7b509bd62 100644
--- a/site/_docs/tutorial.md
+++ b/site/_docs/tutorial.md
@@ -197,17 +197,21 @@ schema, passing in the <code>directory</code> argument 
from the model file:
 {% highlight java %}
 public Schema create(SchemaPlus parentSchema, String name,
     Map<String, Object> operand) {
-  String directory = (String) operand.get("directory");
+  final String directory = (String) operand.get("directory");
+  final File base =
+      (File) operand.get(ModelHandler.ExtraOperand.BASE_DIRECTORY.camelName);
+  File directoryFile = new File(directory);
+  if (base != null && !directoryFile.isAbsolute()) {
+    directoryFile = new File(base, directory);
+  }
   String flavorName = (String) operand.get("flavor");
   CsvTable.Flavor flavor;
   if (flavorName == null) {
     flavor = CsvTable.Flavor.SCANNABLE;
   } else {
-    flavor = CsvTable.Flavor.valueOf(flavorName.toUpperCase());
+    flavor = CsvTable.Flavor.valueOf(flavorName.toUpperCase(Locale.ROOT));
   }
-  return new CsvSchema(
-      new File(directory),
-      flavor);
+  return new CsvSchema(directoryFile, flavor);
 }
 {% endhighlight %}
 
@@ -230,17 +234,15 @@ Here is the relevant code from <code>CsvSchema</code>, 
overriding the
 method in the <code>AbstractSchema</code> base class.
 
 {% highlight java %}
-protected Map<String, Table> getTableMap() {
+private Map<String, Table> createTableMap() {
   // Look for files in the directory ending in ".csv", ".csv.gz", ".json",
   // ".json.gz".
-  File[] files = directoryFile.listFiles(
-      new FilenameFilter() {
-        public boolean accept(File dir, String name) {
-          final String nameSansGz = trim(name, ".gz");
-          return nameSansGz.endsWith(".csv")
-              || nameSansGz.endsWith(".json");
-        }
-      });
+  final Source baseSource = Sources.of(directoryFile);
+  File[] files = directoryFile.listFiles((dir, name) -> {
+    final String nameSansGz = trim(name, ".gz");
+    return nameSansGz.endsWith(".csv")
+        || nameSansGz.endsWith(".json");
+  });
   if (files == null) {
     System.out.println("directory " + directoryFile + " not found");
     files = new File[0];
@@ -248,31 +250,33 @@ protected Map<String, Table> getTableMap() {
   // Build a map from table name to table; each file becomes a table.
   final ImmutableMap.Builder<String, Table> builder = ImmutableMap.builder();
   for (File file : files) {
-    String tableName = trim(file.getName(), ".gz");
-    final String tableNameSansJson = trimOrNull(tableName, ".json");
-    if (tableNameSansJson != null) {
-      JsonTable table = new JsonTable(file);
-      builder.put(tableNameSansJson, table);
-      continue;
+    Source source = Sources.of(file);
+    Source sourceSansGz = source.trim(".gz");
+    final Source sourceSansJson = sourceSansGz.trimOrNull(".json");
+    if (sourceSansJson != null) {
+      final Table table = new JsonScannableTable(source);
+      builder.put(sourceSansJson.relative(baseSource).path(), table);
+    }
+    final Source sourceSansCsv = sourceSansGz.trimOrNull(".csv");
+    if (sourceSansCsv != null) {
+      final Table table = createTable(source);
+      builder.put(sourceSansCsv.relative(baseSource).path(), table);
     }
-    tableName = trim(tableName, ".csv");
-    final Table table = createTable(file);
-    builder.put(tableName, table);
   }
   return builder.build();
 }
 
 /** Creates different sub-type of table based on the "flavor" attribute. */
-private Table createTable(File file) {
+private Table createTable(Source source) {
   switch (flavor) {
   case TRANSLATABLE:
-    return new CsvTranslatableTable(file, null);
+    return new CsvTranslatableTable(source, null);
   case SCANNABLE:
-    return new CsvScannableTable(file, null);
+    return new CsvScannableTable(source, null);
   case FILTERABLE:
-    return new CsvFilterableTable(file, null);
+    return new CsvFilterableTable(source, null);
   default:
-    throw new AssertionError("Unknown flavor " + flavor);
+    throw new AssertionError("Unknown flavor " + this.flavor);
   }
 }
 {% endhighlight %}
@@ -413,12 +417,14 @@ passing in the <code>file</code> argument from the model 
file:
 
 {% highlight java %}
 public CsvTable create(SchemaPlus schema, String name,
-    Map<String, Object> map, RelDataType rowType) {
-  String fileName = (String) map.get("file");
-  final File file = new File(fileName);
+    Map<String, Object> operand, @Nullable RelDataType rowType) {
+  String fileName = (String) operand.get("file");
+  final File base =
+      (File) operand.get(ModelHandler.ExtraOperand.BASE_DIRECTORY.camelName);
+  final Source source = Sources.file(base, fileName);
   final RelProtoDataType protoRowType =
       rowType != null ? RelDataTypeImpl.proto(rowType) : null;
-  return new CsvScannableTable(file, protoRowType);
+  return new CsvScannableTable(source, protoRowType);
 }
 {% endhighlight %}
 
@@ -519,6 +525,7 @@ Here is the rule in its entirety:
 {% highlight java %}
 public class CsvProjectTableScanRule
     extends RelRule<CsvProjectTableScanRule.Config> {
+
   /** Creates a CsvProjectTableScanRule. */
   protected CsvProjectTableScanRule(Config config) {
     super(config);
@@ -540,7 +547,7 @@ public class CsvProjectTableScanRule
             fields));
   }
 
-  private int[] getProjectFields(List<RexNode> exps) {
+  private static int[] getProjectFields(List<RexNode> exps) {
     final int[] fields = new int[exps.size()];
     for (int i = 0; i < exps.size(); i++) {
       final RexNode exp = exps.get(i);
@@ -554,17 +561,19 @@ public class CsvProjectTableScanRule
   }
 
   /** Rule configuration. */
+  @Value.Immutable(singleton = false)
   public interface Config extends RelRule.Config {
-    Config DEFAULT = EMPTY
+    Config DEFAULT = ImmutableCsvProjectTableScanRule.Config.builder()
         .withOperandSupplier(b0 ->
             b0.operand(LogicalProject.class).oneInput(b1 ->
                 b1.operand(CsvTableScan.class).noInputs()))
-        .as(Config.class);
+        .build();
 
     @Override default CsvProjectTableScanRule toRule() {
       return new CsvProjectTableScanRule(this);
     }
-}
+  }
+} 
 {% endhighlight %}
 
 The default instance of the rule resides in the `CsvRules` holder class:

Reply via email to