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)