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

hyuan 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 69f9e87  [CALCITE-3204] Implement jps command for OS adapter (Qianjin 
Xu)
69f9e87 is described below

commit 69f9e877c436b6d74fdc712b5bf71819dc090796
Author: XuQianJin-Stars <[email protected]>
AuthorDate: Sat Jul 20 20:25:20 2019 +0800

    [CALCITE-3204] Implement jps command for OS adapter (Qianjin Xu)
    
    Close #1325
---
 .../apache/calcite/adapter/csv/JsonEnumerator.java | 90 +++++++++++++++++++++-
 .../org/apache/calcite/adapter/csv/JsonTable.java  | 69 ++---------------
 .../calcite/adapter/os/JpsTableFunction.java       | 81 +++++++++++++++++++
 .../org/apache/calcite/adapter/os/SqlShell.java    |  2 +
 .../apache/calcite/adapter/os/OsAdapterTest.java   | 14 ++++
 site/_docs/os_adapter.md                           | 16 ++++
 6 files changed, 209 insertions(+), 63 deletions(-)

diff --git 
a/example/csv/src/main/java/org/apache/calcite/adapter/csv/JsonEnumerator.java 
b/example/csv/src/main/java/org/apache/calcite/adapter/csv/JsonEnumerator.java
index fbb5b61..9a7dddb 100644
--- 
a/example/csv/src/main/java/org/apache/calcite/adapter/csv/JsonEnumerator.java
+++ 
b/example/csv/src/main/java/org/apache/calcite/adapter/csv/JsonEnumerator.java
@@ -18,6 +18,14 @@ package org.apache.calcite.adapter.csv;
 
 import org.apache.calcite.linq4j.Enumerator;
 import org.apache.calcite.linq4j.Linq4j;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.util.Pair;
+import org.apache.calcite.util.Source;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -26,7 +34,7 @@ import java.util.List;
 import java.util.Map;
 
 /**
- * Enumerator that reads from a JSON file.
+ * Enumerator that reads from a Object List.
  */
 public class JsonEnumerator implements Enumerator<Object[]> {
 
@@ -48,6 +56,66 @@ public class JsonEnumerator implements Enumerator<Object[]> {
     enumerator = Linq4j.enumerator(objs);
   }
 
+  /** Deduces the names and types of a table's columns by reading the first 
line
+   * of a JSON file. */
+  static JsonDataConverter deduceRowType(RelDataTypeFactory typeFactory, 
Source source) {
+    final ObjectMapper objectMapper = new ObjectMapper();
+    List<Object> list = new ArrayList<>();
+    LinkedHashMap<String, Object> jsonFieldMap = new LinkedHashMap<>(1);
+    Object jsonObj = null;
+    try {
+      objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, 
true)
+          .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
+          .configure(JsonParser.Feature.ALLOW_COMMENTS, true);
+      if (source.file().exists() && source.file().length() > 0) {
+        if ("file".equals(source.protocol())) {
+          //noinspection unchecked
+          jsonObj = objectMapper.readValue(source.file(), Object.class);
+        } else {
+          //noinspection unchecked
+          jsonObj = objectMapper.readValue(source.url(), Object.class);
+        }
+      }
+    } catch (MismatchedInputException e) {
+      if (!e.getMessage().contains("No content")) {
+        throw new RuntimeException(e);
+      }
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+
+    if (jsonObj == null) {
+      list = new ArrayList<>();
+      jsonFieldMap.put("EmptyFileHasNoColumns", Boolean.TRUE);
+    } else if (jsonObj instanceof Collection) {
+      //noinspection unchecked
+      list = (List<Object>) jsonObj;
+      //noinspection unchecked
+      jsonFieldMap = (LinkedHashMap) (list.get(0));
+    } else if (jsonObj instanceof Map) {
+      //noinspection unchecked
+      jsonFieldMap = (LinkedHashMap) jsonObj;
+      //noinspection unchecked
+      list = new ArrayList(((LinkedHashMap) jsonObj).values());
+    } else {
+      jsonFieldMap.put("line", jsonObj);
+      list = new ArrayList<>();
+      list.add(0, jsonObj);
+    }
+
+    final List<RelDataType> types = new 
ArrayList<RelDataType>(jsonFieldMap.size());
+    final List<String> names = new ArrayList<String>(jsonFieldMap.size());
+
+    for (Object key : jsonFieldMap.keySet()) {
+      final RelDataType type = 
typeFactory.createJavaType(jsonFieldMap.get(key).getClass());
+      names.add(key.toString());
+      types.add(type);
+    }
+
+    RelDataType relDataType = typeFactory.createStructType(Pair.zip(names, 
types));
+    return new JsonDataConverter(relDataType, list);
+  }
+
   public Object[] current() {
     return enumerator.current();
   }
@@ -64,6 +132,26 @@ public class JsonEnumerator implements Enumerator<Object[]> 
{
     enumerator.close();
   }
 
+  /**
+   * Json data and relDataType Converter.
+   */
+  static class JsonDataConverter {
+    private final RelDataType relDataType;
+    private final List<Object> dataList;
+
+    private JsonDataConverter(RelDataType relDataType, List<Object> dataList) {
+      this.relDataType = relDataType;
+      this.dataList = dataList;
+    }
+
+    RelDataType getRelDataType() {
+      return relDataType;
+    }
+
+    List<Object> getDataList() {
+      return dataList;
+    }
+  }
 }
 
 // End JsonEnumerator.java
diff --git 
a/example/csv/src/main/java/org/apache/calcite/adapter/csv/JsonTable.java 
b/example/csv/src/main/java/org/apache/calcite/adapter/csv/JsonTable.java
index d73a2eb..9f11494 100644
--- a/example/csv/src/main/java/org/apache/calcite/adapter/csv/JsonTable.java
+++ b/example/csv/src/main/java/org/apache/calcite/adapter/csv/JsonTable.java
@@ -16,87 +16,32 @@
  */
 package org.apache.calcite.adapter.csv;
 
+import org.apache.calcite.adapter.csv.JsonEnumerator.JsonDataConverter;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.schema.Statistic;
 import org.apache.calcite.schema.Statistics;
 import org.apache.calcite.schema.impl.AbstractTable;
-import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Source;
 
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.exc.MismatchedInputException;
-
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 
 /**
  * Table based on a JSON file.
  */
 public class JsonTable extends AbstractTable {
-  private final ObjectMapper objectMapper = new ObjectMapper();
-  protected final List<Object> list;
-
-  private LinkedHashMap<String, Object> jsonFieldMap = new LinkedHashMap<>(1);
+  private final Source source;
+  protected List<Object> list = new ArrayList<>();
 
   public JsonTable(Source source) {
-    Object jsonObj = null;
-    try {
-      objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, 
true)
-          .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
-          .configure(JsonParser.Feature.ALLOW_COMMENTS, true);
-      if (source.file().exists() && source.file().length() > 0) {
-        if ("file".equals(source.protocol())) {
-          //noinspection unchecked
-          jsonObj = objectMapper.readValue(source.file(), Object.class);
-        } else {
-          //noinspection unchecked
-          jsonObj = objectMapper.readValue(source.url(), Object.class);
-        }
-      }
-    } catch (MismatchedInputException e) {
-      if (!e.getMessage().contains("No content")) {
-        throw new RuntimeException(e);
-      }
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-
-    if (jsonObj == null) {
-      list = new ArrayList<>();
-      jsonFieldMap.put("EmptyFileHasNoColumns", Boolean.TRUE);
-    } else if (jsonObj instanceof Collection) {
-      //noinspection unchecked
-      list = (List<Object>) jsonObj;
-      //noinspection unchecked
-      jsonFieldMap = (LinkedHashMap) (list.get(0));
-    } else if (jsonObj instanceof Map) {
-      //noinspection unchecked
-      jsonFieldMap = (LinkedHashMap) jsonObj;
-      //noinspection unchecked
-      list = new ArrayList(((LinkedHashMap) jsonObj).values());
-    } else {
-      jsonFieldMap.put("line", jsonObj);
-      list = new ArrayList<>();
-      list.add(0, jsonObj);
-    }
+    this.source = source;
   }
 
   public RelDataType getRowType(RelDataTypeFactory typeFactory) {
-    final List<RelDataType> types = new ArrayList<RelDataType>();
-    final List<String> names = new ArrayList<String>();
-
-    for (Object obj : jsonFieldMap.keySet()) {
-      final RelDataType type = 
typeFactory.createJavaType(jsonFieldMap.get(obj).getClass());
-      names.add(obj.toString());
-      types.add(type);
-    }
-
-    return typeFactory.createStructType(Pair.zip(names, types));
+    JsonDataConverter jsonDataConverter = 
JsonEnumerator.deduceRowType(typeFactory, source);
+    list = jsonDataConverter.getDataList();
+    return jsonDataConverter.getRelDataType();
   }
 
   public Statistic getStatistic() {
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/JpsTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/JpsTableFunction.java
new file mode 100644
index 0000000..0682a99
--- /dev/null
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/JpsTableFunction.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.adapter.os;
+
+import org.apache.calcite.DataContext;
+import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.schema.ScannableTable;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.Statistic;
+import org.apache.calcite.schema.Statistics;
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.util.ImmutableBitSet;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Table function that executes the OS "jps" ("Java Virtual Machine Process
+ * Status Tool") command to list all java processes of a user.
+ */
+public class JpsTableFunction {
+  private JpsTableFunction() {
+  }
+
+  public static ScannableTable eval(boolean b) {
+    return new ScannableTable() {
+      public Enumerable<Object[]> scan(DataContext root) {
+        return Processes.processLines("jps", "-mlvV")
+            .select(a0 -> {
+              final String[] fields = a0.split(" ");
+              return new Object[]{Long.valueOf(fields[0]), fields[1]};
+            });
+      }
+
+      public RelDataType getRowType(RelDataTypeFactory typeFactory) {
+        return typeFactory.builder()
+            .add("pid", SqlTypeName.BIGINT)
+            .add("info", SqlTypeName.VARCHAR)
+            .build();
+      }
+
+      public Statistic getStatistic() {
+        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
+      }
+
+      public Schema.TableType getJdbcTableType() {
+        return Schema.TableType.TABLE;
+      }
+
+      public boolean isRolledUp(String column) {
+        return false;
+      }
+
+      public boolean rolledUpColumnValidInsideAgg(String column, SqlCall call,
+          SqlNode parent, CalciteConnectionConfig config) {
+        return true;
+      }
+    };
+  }
+
+}
+
+// End JpsTableFunction.java
diff --git a/plus/src/main/java/org/apache/calcite/adapter/os/SqlShell.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/SqlShell.java
index c9d928c..2dd28af 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/SqlShell.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/SqlShell.java
@@ -75,6 +75,7 @@ public class SqlShell {
             + "from table(\"du\"(true))");
     addView(b, "files", "select * from table(\"files\"('.'))");
     addView(b, "git_commits", "select * from table(\"git_commits\"(true))");
+    addView(b, "jps", "select * from table(\"jps\"(true))");
     addView(b, "ps", "select * from table(\"ps\"(true))");
     addView(b, "stdin", "select * from table(\"stdin\"(true))");
     addView(b, "vmstat", "select * from table(\"vmstat\"(true))");
@@ -83,6 +84,7 @@ public class SqlShell {
     addFunction(b, "du", DuTableFunction.class);
     addFunction(b, "files", FilesTableFunction.class);
     addFunction(b, "git_commits", GitCommitsTableFunction.class);
+    addFunction(b, "jps", JpsTableFunction.class);
     addFunction(b, "ps", PsTableFunction.class);
     addFunction(b, "stdin", StdinTableFunction.class);
     addFunction(b, "vmstat", VmstatTableFunction.class);
diff --git 
a/plus/src/test/java/org/apache/calcite/adapter/os/OsAdapterTest.java 
b/plus/src/test/java/org/apache/calcite/adapter/os/OsAdapterTest.java
index 826ffae..363545a 100644
--- a/plus/src/test/java/org/apache/calcite/adapter/os/OsAdapterTest.java
+++ b/plus/src/test/java/org/apache/calcite/adapter/os/OsAdapterTest.java
@@ -207,6 +207,20 @@ public class OsAdapterTest {
         "author=Julian Hyde <[email protected]>");
   }
 
+  @Test public void testJps() {
+    final String q = "select pid, info from jps";
+    sql(q).returns(r -> {
+      try {
+        assertThat(r.next(), is(true));
+        assertThat(r.getString(1), notNullValue());
+        assertThat(r.getString(2), notNullValue());
+        assertThat(r.wasNull(), is(false));
+      } catch (SQLException e) {
+        throw TestUtil.rethrow(e);
+      }
+    });
+  }
+
   @Test public void testVmstat() {
     Assume.assumeFalse("Skip: the 'files' table does not work on Windows",
         isWindows());
diff --git a/site/_docs/os_adapter.md b/site/_docs/os_adapter.md
index c04dae9..4575a6a 100644
--- a/site/_docs/os_adapter.md
+++ b/site/_docs/os_adapter.md
@@ -242,6 +242,22 @@ $ ./sqlsh -o mysql select min\(size_k\), max\(size_k\) 
from du
 
 {% endhighlight %}
 
+## Example: jps
+
+provides a display of all current java process pids In `sqlsh`:
+
+{% highlight bash %}
+$ ./sqlsh select distinct jps.\`pid\`, jps.\`info\` from jps
++--------+---------------------+
+| pid    |  info               |
++--------+---------------------+
+|  49457 | RemoteMavenServer   |
+|  48326 | KotlinCompileDaemon |
++--------+---------------------+
+(1 row)
+
+{% endhighlight %}
+
 Format options:
 
 * spaced - spaces between fields (the default)

Reply via email to