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

jhyde 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 48b79228d3 [CALCITE-3329] Implement osquery for OS adapter
48b79228d3 is described below

commit 48b79228d3fab7a9f1a1aa1c1146b682139419f0
Author: Forward Xu <[email protected]>
AuthorDate: Wed Jul 14 19:43:25 2021 +0800

    [CALCITE-3329] Implement osquery for OS adapter
    
    After this commit, the 'sqlsh' command has new tables
    cpu_info, cpu_time, interface_addresses, interface_details,
    java_info, memory_info, mounts, os_version, system_info.
    
    Add Forward Xu to .mailmap file (Julian Hyde).
    
    Document new tables in OS adapter (Julian Hyde).
    
    Close apache/calcite#3585
---
 .mailmap                                           |   6 +-
 bom/build.gradle.kts                               |  13 +-
 gradle.properties                                  |   5 +-
 plus/build.gradle.kts                              |  11 +
 .../adapter/os/AbstractBaseScannableTable.java     |  55 +++++
 ...ableFunction.java => CpuInfoTableFunction.java} |  60 ++---
 ...ableFunction.java => CpuTimeTableFunction.java} |  59 ++---
 .../apache/calcite/adapter/os/DuTableFunction.java |  32 +--
 .../calcite/adapter/os/FilesTableFunction.java     |  33 +--
 .../adapter/os/GitCommitsTableFunction.java        |  28 +--
 ...n.java => InterfaceAddressesTableFunction.java} |  56 ++---
 ...ion.java => InterfaceDetailsTableFunction.java} |  64 +++---
 .../calcite/adapter/os/JavaInfoTableFunction.java  |  71 ++++++
 .../calcite/adapter/os/JpsTableFunction.java       |  33 +--
 ...eFunction.java => MemoryInfoTableFunction.java} |  59 ++---
 ...TableFunction.java => MountsTableFunction.java} |  57 ++---
 .../org/apache/calcite/adapter/os/OsQuery.java     |  70 ++++++
 .../org/apache/calcite/adapter/os/OsQueryType.java |  82 +++++++
 ...leFunction.java => OsVersionTableFunction.java} |  56 ++---
 .../apache/calcite/adapter/os/PsTableFunction.java |  33 +--
 .../org/apache/calcite/adapter/os/SqlShell.java    |  18 ++
 .../calcite/adapter/os/StdinTableFunction.java     |  34 +--
 ...eFunction.java => SystemInfoTableFunction.java} |  69 +++---
 .../calcite/adapter/os/VmstatTableFunction.java    |  30 +--
 .../calcite/adapter/utils/OsQueryTableUtil.java    | 250 +++++++++++++++++++++
 .../calcite/adapter/utils/package-info.java}       |  23 +-
 .../apache/calcite/adapter/os/OsAdapterTest.java   |  97 ++++++--
 site/_docs/os_adapter.md                           |  13 +-
 28 files changed, 858 insertions(+), 559 deletions(-)

diff --git a/.mailmap b/.mailmap
index 2024f7e1e1..061550ae5f 100644
--- a/.mailmap
+++ b/.mailmap
@@ -47,7 +47,10 @@ Feng Zhu <[email protected]> # DonnyZone at github
 Feng Zhu <[email protected]>
 Feng Zhu <[email protected]>
 Feng Zhu <[email protected]>
-ForwardXu <[email protected]>
+Forward Xu <[email protected]>
+Forward Xu <[email protected]>
+Forward Xu <[email protected]> # aka XuQianJin-Stars, Qianjin Xu
+Forward Xu <[email protected]>
 Godfrey He <[email protected]>
 Hequn Cheng <[email protected]>
 Hong Shen (沈洪) <[email protected]>
@@ -102,7 +105,6 @@ Peng Wang <[email protected]>
 pengzhiwei <[email protected]>
 Praveen Kumar <[email protected]>
 Qi Yu (余启) <[email protected]>
-Qianjin Xu <[email protected]>
 Rafay Qureshi <[email protected]>
 Ruben Quesada Lopez <[email protected]>
 Rui Wang <[email protected]>
diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts
index 58aa51a84c..79fb7cc56b 100644
--- a/bom/build.gradle.kts
+++ b/bom/build.gradle.kts
@@ -51,16 +51,13 @@ dependencies {
         // runtime means "the dependency is only for runtime, not for 
compilation"
         // In other words, marking dependency as "runtime" would avoid 
accidental
         // dependency on it during compilation
+        apiv("cn.hutool:hutool-all")
         apiv("com.alibaba.database:innodb-java-reader")
         apiv("com.beust:jcommander")
-        apiv("org.checkerframework:checker-qual", "checkerframework")
         apiv("com.datastax.oss:java-driver-core", "cassandra-java-driver-core")
-        apiv("org.locationtech.jts:jts-core")
-        apiv("org.locationtech.jts.io:jts-io-common")
-        apiv("org.locationtech.proj4j:proj4j")
-        apiv("org.locationtech.proj4j:proj4j-epsg", "proj4j")
         apiv("com.fasterxml.jackson.core:jackson-databind")
         apiv("com.github.kstyrc:embedded-redis")
+        apiv("com.github.oshi:oshi-core")
         apiv("com.github.stephenc.jcip:jcip-annotations")
         apiv("com.google.errorprone:error_prone_annotations", "errorprone")
         apiv("com.google.errorprone:error_prone_type_annotations", 
"errorprone")
@@ -75,6 +72,11 @@ dependencies {
         apiv("com.yahoo.datasketches:sketches-core")
         apiv("commons-codec:commons-codec")
         apiv("commons-io:commons-io")
+        apiv("org.checkerframework:checker-qual", "checkerframework")
+        apiv("org.locationtech.jts:jts-core")
+        apiv("org.locationtech.jts.io:jts-io-common")
+        apiv("org.locationtech.proj4j:proj4j")
+        apiv("org.locationtech.proj4j:proj4j-epsg", "proj4j")
         apiv("de.bwaldvogel:mongo-java-server", "mongo-java-server")
         apiv("de.bwaldvogel:mongo-java-server-core", "mongo-java-server")
         apiv("de.bwaldvogel:mongo-java-server-memory-backend", 
"mongo-java-server")
@@ -93,6 +95,7 @@ dependencies {
         apiv("net.hydromatic:sql-logic-test")
         apiv("net.hydromatic:tpcds", "hydromatic.tpcds")
         apiv("net.java.dev.jna:jna")
+        apiv("net.java.dev.jna:jna-platform")
         apiv("net.sf.opencsv:opencsv")
         apiv("org.apache.calcite.avatica:avatica-core", "calcite.avatica")
         apiv("org.apache.calcite.avatica:avatica-server", "calcite.avatica")
diff --git a/gradle.properties b/gradle.properties
index cda90d717d..0442aee596 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -117,6 +117,7 @@ hamcrest.version=2.1
 hsqldb.version=2.7.2
 httpclient.version=4.5.9
 httpcore.version=4.4.11
+hutool-all.version=5.8.23
 hydromatic.tpcds.version=0.4
 immutables.version=2.8.8
 innodb-java-reader.version=1.0.10
@@ -129,7 +130,8 @@ jcommander.version=1.72
 jedis.version=3.3.0
 jetty.version=9.4.46.v20220331
 jmh.version=1.12
-jna.version=5.7.0
+jna.version=5.14.0
+jna-platform.version=5.14.0
 joda-time.version=2.8.1
 json-path.version=2.8.0
 jsr305.version=3.0.2
@@ -147,6 +149,7 @@ mysql-connector-java.version=5.1.20
 natty.version=0.13
 ojdbc8.version=19.3.0.0
 opencsv.version=2.3
+oshi-core.version=6.4.9
 pig.version=0.16.0
 pigunit.version=0.16.0
 postgresql.version=9.3-1102-jdbc41
diff --git a/plus/build.gradle.kts b/plus/build.gradle.kts
index fc696a4497..63fa9fcabd 100644
--- a/plus/build.gradle.kts
+++ b/plus/build.gradle.kts
@@ -23,9 +23,20 @@ dependencies {
 
     implementation("com.google.guava:guava")
     implementation("com.teradata.tpcds:tpcds")
+    implementation("cn.hutool:hutool-all")
     implementation("io.prestosql.tpch:tpch")
     implementation("net.hydromatic:chinook-data-hsqldb")
     implementation("net.hydromatic:tpcds")
+    implementation("net.java.dev.jna:jna")
+    implementation("net.java.dev.jna:jna-platform")
+
+    implementation("com.github.oshi:oshi-core") {
+        exclude("log4j", "log4j")
+            .because("log4j is already present in the classpath")
+        exclude("org.slf4j", "slf4j-api")
+            .because("slf4j is already present in the classpath")
+    }
+
     implementation("org.apache.calcite.avatica:avatica-server")
     implementation("org.hsqldb:hsqldb::jdk8")
 
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/AbstractBaseScannableTable.java
 
b/plus/src/main/java/org/apache/calcite/adapter/os/AbstractBaseScannableTable.java
new file mode 100644
index 0000000000..9f1bb186b1
--- /dev/null
+++ 
b/plus/src/main/java/org/apache/calcite/adapter/os/AbstractBaseScannableTable.java
@@ -0,0 +1,55 @@
+/*
+ * 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.config.CalciteConnectionConfig;
+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.util.ImmutableBitSet;
+
+import com.google.common.collect.ImmutableList;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+/**
+ * Abstract base class for implementations of OS table functions.
+ */
+abstract class AbstractBaseScannableTable implements ScannableTable {
+  protected AbstractBaseScannableTable() {
+  }
+
+  @Override public Statistic getStatistic() {
+    return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
+  }
+
+  @Override public Schema.TableType getJdbcTableType() {
+    return Schema.TableType.TABLE;
+  }
+
+  @Override public boolean isRolledUp(String column) {
+    return false;
+  }
+
+  @Override public boolean rolledUpColumnValidInsideAgg(String column, SqlCall 
call,
+      @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
+    return true;
+  }
+}
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/CpuInfoTableFunction.java
similarity index 51%
copy from plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
copy to 
plus/src/main/java/org/apache/calcite/adapter/os/CpuInfoTableFunction.java
index 75bdc29ba5..a42d897a39 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/CpuInfoTableFunction.java
@@ -17,64 +17,46 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 /**
- * Table function that executes the OS "du" ("disk usage") command
- * to compute file sizes.
+ * Table function that executes the OS "cpu_info".
  */
-public class DuTableFunction {
-  private DuTableFunction() {}
+public class CpuInfoTableFunction {
+  private CpuInfoTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        return Processes.processLines("du", "-ak")
-            .select(a0 -> {
-              final String[] fields = a0.split("\t");
-              return new Object[] {Long.valueOf(fields[0]), fields[1]};
-            });
+        return new AbstractEnumerable<Object[]>() {
+          @Override public Enumerator<Object[]> enumerator() {
+            return new OsQuery("cpu_info");
+          }
+        };
       }
 
       @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
         return typeFactory.builder()
-            .add("size_k", SqlTypeName.BIGINT)
-            .add("path", SqlTypeName.VARCHAR)
+            .add("device_id", SqlTypeName.VARCHAR)
+            .add("model", SqlTypeName.VARCHAR)
+            .add("manufacturer", SqlTypeName.VARCHAR)
+            .add("number_of_cores", SqlTypeName.INTEGER)
+            .add("logical_processors", SqlTypeName.INTEGER)
+            .add("address_width", SqlTypeName.INTEGER)
+            .add("max_clock_speed", SqlTypeName.BIGINT)
+            .add("socket_designation", SqlTypeName.INTEGER)
+            .add("cpu_load", SqlTypeName.DOUBLE)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/CpuTimeTableFunction.java
similarity index 51%
copy from plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
copy to 
plus/src/main/java/org/apache/calcite/adapter/os/CpuTimeTableFunction.java
index 75bdc29ba5..e76ececcaf 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/CpuTimeTableFunction.java
@@ -17,64 +17,45 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 /**
- * Table function that executes the OS "du" ("disk usage") command
- * to compute file sizes.
+ * Table function that executes the OS "cpu_info".
  */
-public class DuTableFunction {
-  private DuTableFunction() {}
+public class CpuTimeTableFunction {
+  private CpuTimeTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        return Processes.processLines("du", "-ak")
-            .select(a0 -> {
-              final String[] fields = a0.split("\t");
-              return new Object[] {Long.valueOf(fields[0]), fields[1]};
-            });
+        return new AbstractEnumerable<Object[]>() {
+          @Override public Enumerator<Object[]> enumerator() {
+            return new OsQuery("cpu_time");
+          }
+        };
       }
 
       @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
         return typeFactory.builder()
-            .add("size_k", SqlTypeName.BIGINT)
-            .add("path", SqlTypeName.VARCHAR)
+            .add("idle", SqlTypeName.BIGINT)
+            .add("nice", SqlTypeName.BIGINT)
+            .add("irq", SqlTypeName.BIGINT)
+            .add("soft_irq", SqlTypeName.BIGINT)
+            .add("steal", SqlTypeName.BIGINT)
+            .add("system", SqlTypeName.BIGINT)
+            .add("user", SqlTypeName.BIGINT)
+            .add("io_wait", SqlTypeName.BIGINT)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
index 75bdc29ba5..f1847bfab7 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
@@ -17,20 +17,11 @@
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
@@ -39,10 +30,11 @@ import org.checkerframework.checker.nullness.qual.Nullable;
  * to compute file sizes.
  */
 public class DuTableFunction {
-  private DuTableFunction() {}
+  private DuTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
         return Processes.processLines("du", "-ak")
             .select(a0 -> {
@@ -57,24 +49,6 @@ public class DuTableFunction {
             .add("path", SqlTypeName.VARCHAR)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
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 c09c9f52f8..694b3ccbeb 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
@@ -18,20 +18,13 @@ package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
-import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.Enumerator;
 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 org.apache.calcite.util.Util;
 
 import com.google.common.collect.ImmutableList;
@@ -52,15 +45,17 @@ public class FilesTableFunction {
 
   private static final BigDecimal THOUSAND = BigDecimal.valueOf(1000L);
 
-  private FilesTableFunction() {}
+  private FilesTableFunction() {
+  }
 
-  /** Evaluates the function.
+  /**
+   * Evaluates the function.
    *
    * @param path Directory in which to start the search. Typically '.'
    * @return Table that can be inspected, planned, and evaluated
    */
   public static ScannableTable eval(final String path) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
         return typeFactory.builder()
             .add("access_time", SqlTypeName.TIMESTAMP) // %A@ sec since epoch
@@ -267,24 +262,6 @@ public class FilesTableFunction {
           }
         };
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
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 28aa4fd538..282117a88f 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
@@ -17,22 +17,13 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.Enumerator;
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
@@ -54,7 +45,7 @@ public class GitCommitsTableFunction {
   private GitCommitsTableFunction() {}
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
         final Enumerable<String> enumerable =
             Processes.processLines("git", "log", "--pretty=raw");
@@ -158,23 +149,6 @@ public class GitCommitsTableFunction {
             .add("message", SqlTypeName.VARCHAR)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(0)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/InterfaceAddressesTableFunction.java
similarity index 51%
copy from plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
copy to 
plus/src/main/java/org/apache/calcite/adapter/os/InterfaceAddressesTableFunction.java
index 75bdc29ba5..6c566fc34e 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
+++ 
b/plus/src/main/java/org/apache/calcite/adapter/os/InterfaceAddressesTableFunction.java
@@ -17,64 +17,42 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 /**
- * Table function that executes the OS "du" ("disk usage") command
- * to compute file sizes.
+ * Table function that executes the OS "interface_addresses".
  */
-public class DuTableFunction {
-  private DuTableFunction() {}
+public class InterfaceAddressesTableFunction {
+  private InterfaceAddressesTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        return Processes.processLines("du", "-ak")
-            .select(a0 -> {
-              final String[] fields = a0.split("\t");
-              return new Object[] {Long.valueOf(fields[0]), fields[1]};
-            });
+        return new AbstractEnumerable<Object[]>() {
+          @Override public Enumerator<Object[]> enumerator() {
+            return new OsQuery("interface_addresses");
+          }
+        };
       }
 
       @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
         return typeFactory.builder()
-            .add("size_k", SqlTypeName.BIGINT)
-            .add("path", SqlTypeName.VARCHAR)
+            .add("name", SqlTypeName.VARCHAR)
+            .add("ipv4_address", SqlTypeName.VARCHAR)
+            .add("ipv6_address", SqlTypeName.VARCHAR)
+            .add("mac", SqlTypeName.VARCHAR)
+            .add("status", SqlTypeName.VARCHAR)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/InterfaceDetailsTableFunction.java
similarity index 51%
copy from plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
copy to 
plus/src/main/java/org/apache/calcite/adapter/os/InterfaceDetailsTableFunction.java
index 75bdc29ba5..507e8ab2c9 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
+++ 
b/plus/src/main/java/org/apache/calcite/adapter/os/InterfaceDetailsTableFunction.java
@@ -17,64 +17,50 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 /**
- * Table function that executes the OS "du" ("disk usage") command
- * to compute file sizes.
+ * Table function that executes the OS "interface_details".
  */
-public class DuTableFunction {
-  private DuTableFunction() {}
+public class InterfaceDetailsTableFunction {
+  private InterfaceDetailsTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        return Processes.processLines("du", "-ak")
-            .select(a0 -> {
-              final String[] fields = a0.split("\t");
-              return new Object[] {Long.valueOf(fields[0]), fields[1]};
-            });
+        return new AbstractEnumerable<Object[]>() {
+          @Override public Enumerator<Object[]> enumerator() {
+            return new OsQuery("interface_details");
+          }
+        };
       }
 
       @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
         return typeFactory.builder()
-            .add("size_k", SqlTypeName.BIGINT)
-            .add("path", SqlTypeName.VARCHAR)
+            .add("device_name", SqlTypeName.VARCHAR)
+            .add("mac", SqlTypeName.VARCHAR)
+            .add("is_virtual", SqlTypeName.VARCHAR)
+            .add("mtu", SqlTypeName.BIGINT)
+            .add("speed", SqlTypeName.BIGINT)
+            .add("i_packets", SqlTypeName.BIGINT)
+            .add("o_packets", SqlTypeName.BIGINT)
+            .add("i_bytes", SqlTypeName.BIGINT)
+            .add("o_bytes", SqlTypeName.BIGINT)
+            .add("i_errors", SqlTypeName.BIGINT)
+            .add("o_errors", SqlTypeName.BIGINT)
+            .add("i_drops", SqlTypeName.BIGINT)
+            .add("collisions", SqlTypeName.BIGINT)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/JavaInfoTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/JavaInfoTableFunction.java
new file mode 100644
index 0000000000..adacb0b5c3
--- /dev/null
+++ 
b/plus/src/main/java/org/apache/calcite/adapter/os/JavaInfoTableFunction.java
@@ -0,0 +1,71 @@
+/*
+ * 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.linq4j.AbstractEnumerable;
+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.schema.ScannableTable;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+/**
+ * Table function that executes the OS "java_info".
+ */
+public class JavaInfoTableFunction {
+  private JavaInfoTableFunction() {
+  }
+
+  public static ScannableTable eval(boolean b) {
+    return new AbstractBaseScannableTable() {
+      @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
+        return new AbstractEnumerable<Object[]>() {
+          @Override public Enumerator<Object[]> enumerator() {
+            return new OsQuery("java_info");
+          }
+        };
+      }
+
+      @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
+        return typeFactory.builder()
+            .add("java_version", SqlTypeName.VARCHAR)
+            .add("java_vendor", SqlTypeName.VARCHAR)
+            .add("java_vendor_url", SqlTypeName.VARCHAR)
+            .add("java_home", SqlTypeName.VARCHAR)
+            .add("java_vm_specification_version", SqlTypeName.VARCHAR)
+            .add("java_vm_specification_vendor", SqlTypeName.VARCHAR)
+            .add("java_vm_specification_name", SqlTypeName.VARCHAR)
+            .add("java_vm_version", SqlTypeName.VARCHAR)
+            .add("java_vm_vendor", SqlTypeName.VARCHAR)
+            .add("java_vm_name", SqlTypeName.VARCHAR)
+            .add("java_specification_version", SqlTypeName.VARCHAR)
+            .add("java_specification_vender", SqlTypeName.VARCHAR)
+            .add("java_specification_name", SqlTypeName.VARCHAR)
+            .add("java_class_version", SqlTypeName.VARCHAR)
+            .add("java_class_path", SqlTypeName.VARCHAR)
+            .add("java_io_tmpdir", SqlTypeName.VARCHAR)
+            .add("java_ext_dirs", SqlTypeName.VARCHAR)
+            .add("java_library_path", SqlTypeName.VARCHAR)
+            .build();
+      }
+    };
+  }
+}
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
index 60d98230e5..1d4ae1c2c5 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/JpsTableFunction.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/JpsTableFunction.java
@@ -17,20 +17,11 @@
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
@@ -43,11 +34,9 @@ public class JpsTableFunction {
   }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        // https://github.com/eclipse/openj9/issues/11036
-        // openj9 jps doesn't handle multiple flags in one argument
-        return Processes.processLines("jps", "-m", "-l", "-v")
+        return Processes.processLines("jps", "-mlvV")
             .select(a0 -> {
               final String[] fields = a0.split(" ");
               return new Object[]{Long.valueOf(fields[0]), fields[1]};
@@ -60,24 +49,6 @@ public class JpsTableFunction {
             .add("info", SqlTypeName.VARCHAR)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/MemoryInfoTableFunction.java
similarity index 51%
copy from plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
copy to 
plus/src/main/java/org/apache/calcite/adapter/os/MemoryInfoTableFunction.java
index 75bdc29ba5..5047f3f885 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
+++ 
b/plus/src/main/java/org/apache/calcite/adapter/os/MemoryInfoTableFunction.java
@@ -17,64 +17,45 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 /**
- * Table function that executes the OS "du" ("disk usage") command
- * to compute file sizes.
+ * Table function that executes the OS "memory_info".
  */
-public class DuTableFunction {
-  private DuTableFunction() {}
+public class MemoryInfoTableFunction {
+  private MemoryInfoTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        return Processes.processLines("du", "-ak")
-            .select(a0 -> {
-              final String[] fields = a0.split("\t");
-              return new Object[] {Long.valueOf(fields[0]), fields[1]};
-            });
+        return new AbstractEnumerable<Object[]>() {
+          @Override public Enumerator<Object[]> enumerator() {
+            return new OsQuery("memory_info");
+          }
+        };
       }
 
       @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
         return typeFactory.builder()
-            .add("size_k", SqlTypeName.BIGINT)
-            .add("path", SqlTypeName.VARCHAR)
+            .add("mem_total", SqlTypeName.DOUBLE)
+            .add("mem_used", SqlTypeName.DOUBLE)
+            .add("mem_free", SqlTypeName.DOUBLE)
+            .add("swap_total", SqlTypeName.DOUBLE)
+            .add("swap_used", SqlTypeName.DOUBLE)
+            .add("swap_free", SqlTypeName.DOUBLE)
+            .add("swap_pages_in", SqlTypeName.DOUBLE)
+            .add("swap_pages_out", SqlTypeName.DOUBLE)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/MountsTableFunction.java
similarity index 53%
copy from plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
copy to 
plus/src/main/java/org/apache/calcite/adapter/os/MountsTableFunction.java
index 75bdc29ba5..3beb4b230e 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/MountsTableFunction.java
@@ -17,64 +17,45 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 /**
- * Table function that executes the OS "du" ("disk usage") command
- * to compute file sizes.
+ * Table function that executes the OS "mounts".
  */
-public class DuTableFunction {
-  private DuTableFunction() {}
+public class MountsTableFunction {
+  private MountsTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        return Processes.processLines("du", "-ak")
-            .select(a0 -> {
-              final String[] fields = a0.split("\t");
-              return new Object[] {Long.valueOf(fields[0]), fields[1]};
-            });
+        return new AbstractEnumerable<Object[]>() {
+          @Override public Enumerator<Object[]> enumerator() {
+            return new OsQuery("mounts");
+          }
+        };
       }
 
       @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
         return typeFactory.builder()
-            .add("size_k", SqlTypeName.BIGINT)
+            .add("name", SqlTypeName.VARCHAR)
+            .add("volume", SqlTypeName.VARCHAR)
+            .add("size", SqlTypeName.VARCHAR)
+            .add("used", SqlTypeName.VARCHAR)
+            .add("avail", SqlTypeName.VARCHAR)
+            .add("iused", SqlTypeName.VARCHAR)
+            .add("ifree", SqlTypeName.VARCHAR)
             .add("path", SqlTypeName.VARCHAR)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
diff --git a/plus/src/main/java/org/apache/calcite/adapter/os/OsQuery.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/OsQuery.java
new file mode 100644
index 0000000000..83c01811df
--- /dev/null
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/OsQuery.java
@@ -0,0 +1,70 @@
+/*
+ * 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.linq4j.Enumerator;
+import org.apache.calcite.linq4j.Linq4j;
+import org.apache.calcite.util.trace.CalciteTrace;
+
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Enumerator that reads from OS's System.
+ */
+public class OsQuery implements Enumerator<Object[]> {
+  private static final Logger LOGGER = CalciteTrace.getParserTracer();
+
+  private final Enumerator<Object[]> enumerator;
+
+  public OsQuery(String type) {
+    this.enumerator = Linq4j.enumerator(eval(type));
+  }
+
+  public Enumerator<Object[]> getEnumerator() {
+    return enumerator;
+  }
+
+  @Override public Object[] current() {
+    return enumerator.current();
+  }
+
+  @Override public boolean moveNext() {
+    return enumerator.moveNext();
+  }
+
+  @Override public void reset() {
+    enumerator.reset();
+  }
+
+  @Override public void close() {
+    enumerator.close();
+  }
+
+  public List<Object[]> eval(String type) {
+    OsQueryType queryType = OsQueryType.valueOf(type.toUpperCase(Locale.ROOT));
+    try {
+      return queryType.getInfo();
+    } catch (Exception e) {
+      LOGGER.error("Failed to get result's info", e);
+      return new ArrayList<>();
+    }
+  }
+}
diff --git a/plus/src/main/java/org/apache/calcite/adapter/os/OsQueryType.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/OsQueryType.java
new file mode 100644
index 0000000000..3534da06bb
--- /dev/null
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/OsQueryType.java
@@ -0,0 +1,82 @@
+/*
+ * 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 java.util.List;
+
+import static org.apache.calcite.adapter.utils.OsQueryTableUtil.getCpuInfo;
+import static org.apache.calcite.adapter.utils.OsQueryTableUtil.getCpuTimeInfo;
+import static 
org.apache.calcite.adapter.utils.OsQueryTableUtil.getInterfaceAddressesInfo;
+import static 
org.apache.calcite.adapter.utils.OsQueryTableUtil.getInterfaceDetailsInfo;
+import static org.apache.calcite.adapter.utils.OsQueryTableUtil.getJavaInfo;
+import static org.apache.calcite.adapter.utils.OsQueryTableUtil.getMemoryInfo;
+import static org.apache.calcite.adapter.utils.OsQueryTableUtil.getMountsInfo;
+import static 
org.apache.calcite.adapter.utils.OsQueryTableUtil.getOsVersionInfo;
+import static org.apache.calcite.adapter.utils.OsQueryTableUtil.getSystemInfo;
+
+/**
+ * Get system enumeration information.
+ */
+public enum OsQueryType {
+  SYSTEM_INFO {
+    @Override public List<Object[]> getInfo() {
+      return getSystemInfo();
+    }
+  },
+  JAVA_INFO {
+    @Override public List<Object[]> getInfo() {
+      return getJavaInfo();
+    }
+  },
+  OS_VERSION {
+    @Override public List<Object[]> getInfo() {
+      return getOsVersionInfo();
+    }
+  },
+  MEMORY_INFO {
+    @Override public List<Object[]> getInfo() {
+      return getMemoryInfo();
+    }
+  },
+  CPU_INFO {
+    @Override public List<Object[]> getInfo() {
+      return getCpuInfo();
+    }
+  },
+  CPU_TIME {
+    @Override public List<Object[]> getInfo() {
+      return getCpuTimeInfo();
+    }
+  },
+  INTERFACE_ADDRESSES {
+    @Override public List<Object[]> getInfo() {
+      return getInterfaceAddressesInfo();
+    }
+  },
+  INTERFACE_DETAILS {
+    @Override public List<Object[]> getInfo() {
+      return getInterfaceDetailsInfo();
+    }
+  },
+  MOUNTS {
+    @Override public List<Object[]> getInfo() {
+      return getMountsInfo();
+    }
+  };
+
+  public abstract List<Object[]> getInfo();
+}
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/OsVersionTableFunction.java
similarity index 51%
copy from plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
copy to 
plus/src/main/java/org/apache/calcite/adapter/os/OsVersionTableFunction.java
index 75bdc29ba5..961e89597b 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
+++ 
b/plus/src/main/java/org/apache/calcite/adapter/os/OsVersionTableFunction.java
@@ -17,64 +17,42 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 /**
- * Table function that executes the OS "du" ("disk usage") command
- * to compute file sizes.
+ * Table function that executes the OS "os_version".
  */
-public class DuTableFunction {
-  private DuTableFunction() {}
+public class OsVersionTableFunction {
+  private OsVersionTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        return Processes.processLines("du", "-ak")
-            .select(a0 -> {
-              final String[] fields = a0.split("\t");
-              return new Object[] {Long.valueOf(fields[0]), fields[1]};
-            });
+        return new AbstractEnumerable<Object[]>() {
+          @Override public Enumerator<Object[]> enumerator() {
+            return new OsQuery("os_version");
+          }
+        };
       }
 
       @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
         return typeFactory.builder()
-            .add("size_k", SqlTypeName.BIGINT)
-            .add("path", SqlTypeName.VARCHAR)
+            .add("name", SqlTypeName.VARCHAR)
+            .add("version", SqlTypeName.VARCHAR)
+            .add("build", SqlTypeName.VARCHAR)
+            .add("code_name", SqlTypeName.VARCHAR)
+            .add("install_date", SqlTypeName.BIGINT)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/PsTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/PsTableFunction.java
index d84f836c56..8c829877b2 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/PsTableFunction.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/PsTableFunction.java
@@ -17,21 +17,13 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.adapter.java.JavaTypeFactory;
 import org.apache.calcite.avatica.util.TimeUnit;
-import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.function.Function1;
 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 org.apache.calcite.util.Util;
 
 import com.google.common.collect.ImmutableList;
@@ -52,13 +44,13 @@ public class PsTableFunction {
   private static final Pattern HOUR_MINUTE_SECOND_PATTERN =
       Pattern.compile("([0-9]+):([0-9]+)\\.([0-9]+)");
 
-  private PsTableFunction() {}
+  private PsTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        JavaTypeFactory typeFactory = root.getTypeFactory();
-        final RelDataType rowType = getRowType(typeFactory);
+        final RelDataType rowType = getRowType(root.getTypeFactory());
         final List<String> fieldNames =
             ImmutableList.copyOf(rowType.getFieldNames());
         final String[] args;
@@ -161,23 +153,6 @@ public class PsTableFunction {
             .add("command", SqlTypeName.VARCHAR)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
 }
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 fa4c497616..295b43678d 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
@@ -81,6 +81,15 @@ public class SqlShell {
     addView(b, "ps", "select * from table(\"ps\"(true))");
     addView(b, "stdin", "select * from table(\"stdin\"(true))");
     addView(b, "vmstat", "select * from table(\"vmstat\"(true))");
+    addView(b, "system_info", "select * from table(\"system_info\"(true))");
+    addView(b, "java_info", "select * from table(\"java_info\"(true))");
+    addView(b, "os_version", "select * from table(\"os_version\"(true))");
+    addView(b, "memory_info", "select * from table(\"memory_info\"(true))");
+    addView(b, "cpu_info", "select * from table(\"cpu_info\"(true))");
+    addView(b, "cpu_time", "select * from table(\"cpu_time\"(true))");
+    addView(b, "interface_details", "select * from 
table(\"interface_details\"(true))");
+    addView(b, "interface_addresses", "select * from 
table(\"interface_addresses\"(true))");
+    addView(b, "mounts", "select * from table(\"mounts\"(true))");
     b.append("       } ],\n")
         .append("       functions: [ {\n");
     addFunction(b, "du", DuTableFunction.class);
@@ -90,6 +99,15 @@ public class SqlShell {
     addFunction(b, "ps", PsTableFunction.class);
     addFunction(b, "stdin", StdinTableFunction.class);
     addFunction(b, "vmstat", VmstatTableFunction.class);
+    addFunction(b, "system_info", SystemInfoTableFunction.class);
+    addFunction(b, "java_info", JavaInfoTableFunction.class);
+    addFunction(b, "os_version", OsVersionTableFunction.class);
+    addFunction(b, "memory_info", MemoryInfoTableFunction.class);
+    addFunction(b, "cpu_info", CpuInfoTableFunction.class);
+    addFunction(b, "cpu_time", CpuTimeTableFunction.class);
+    addFunction(b, "interface_details", InterfaceDetailsTableFunction.class);
+    addFunction(b, "interface_addresses", 
InterfaceAddressesTableFunction.class);
+    addFunction(b, "mounts", MountsTableFunction.class);
     b.append("       } ]\n")
         .append("     }\n")
         .append("   ]\n")
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/StdinTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/StdinTableFunction.java
index 624b078534..493bccbe99 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/StdinTableFunction.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/StdinTableFunction.java
@@ -17,22 +17,13 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.Enumerator;
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
@@ -48,16 +39,18 @@ import java.util.NoSuchElementException;
  */
 public class StdinTableFunction {
 
-  private StdinTableFunction() {}
+  private StdinTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
-      @Override public Enumerable<Object[]> scan(DataContext root) {
+    return new AbstractBaseScannableTable() {
+      @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
         final InputStream is = DataContext.Variable.STDIN.get(root);
         return new AbstractEnumerable<Object[]>() {
           final InputStreamReader in =
               new InputStreamReader(is, StandardCharsets.UTF_8);
           final BufferedReader br = new BufferedReader(in);
+
           @Override public Enumerator<Object[]> enumerator() {
             return new Enumerator<Object[]>() {
               @Nullable String line;
@@ -102,23 +95,6 @@ public class StdinTableFunction {
             .add("line", SqlTypeName.VARCHAR)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/SystemInfoTableFunction.java
similarity index 50%
copy from plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
copy to 
plus/src/main/java/org/apache/calcite/adapter/os/SystemInfoTableFunction.java
index 75bdc29ba5..36e4064548 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/DuTableFunction.java
+++ 
b/plus/src/main/java/org/apache/calcite/adapter/os/SystemInfoTableFunction.java
@@ -17,64 +17,55 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
 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;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 /**
- * Table function that executes the OS "du" ("disk usage") command
- * to compute file sizes.
+ * Table function that executes the OS "system_info".
  */
-public class DuTableFunction {
-  private DuTableFunction() {}
+public class SystemInfoTableFunction {
+  private SystemInfoTableFunction() {
+  }
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        return Processes.processLines("du", "-ak")
-            .select(a0 -> {
-              final String[] fields = a0.split("\t");
-              return new Object[] {Long.valueOf(fields[0]), fields[1]};
-            });
+        return new AbstractEnumerable<Object[]>() {
+          @Override public Enumerator<Object[]> enumerator() {
+            return new OsQuery("system_info");
+          }
+        };
       }
 
       @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
         return typeFactory.builder()
-            .add("size_k", SqlTypeName.BIGINT)
-            .add("path", SqlTypeName.VARCHAR)
+            .add("hostname", SqlTypeName.VARCHAR)
+            .add("uuid", SqlTypeName.VARCHAR)
+            .add("cpu_type", SqlTypeName.VARCHAR)
+            .add("cpu_vendor", SqlTypeName.VARCHAR)
+            .add("cpu_model", SqlTypeName.VARCHAR)
+            .add("cpu_physical_cores", SqlTypeName.INTEGER)
+            .add("cpu_logical_cores", SqlTypeName.INTEGER)
+            .add("cpu_sockets", SqlTypeName.INTEGER)
+            .add("physical_memory", SqlTypeName.BIGINT)
+            .add("hardware_vendor", SqlTypeName.VARCHAR)
+            .add("hardware_model", SqlTypeName.VARCHAR)
+            .add("hardware_version", SqlTypeName.VARCHAR)
+            .add("hardware_serial", SqlTypeName.VARCHAR)
+            .add("board_vendor", SqlTypeName.VARCHAR)
+            .add("board_model", SqlTypeName.VARCHAR)
+            .add("board_version", SqlTypeName.VARCHAR)
+            .add("board_serial", SqlTypeName.VARCHAR)
+            .add("computer_name", SqlTypeName.VARCHAR)
             .build();
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
-
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/os/VmstatTableFunction.java 
b/plus/src/main/java/org/apache/calcite/adapter/os/VmstatTableFunction.java
index ecfda06ef3..424166941c 100644
--- a/plus/src/main/java/org/apache/calcite/adapter/os/VmstatTableFunction.java
+++ b/plus/src/main/java/org/apache/calcite/adapter/os/VmstatTableFunction.java
@@ -17,20 +17,12 @@
 package org.apache.calcite.adapter.os;
 
 import org.apache.calcite.DataContext;
-import org.apache.calcite.adapter.java.JavaTypeFactory;
-import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.function.Function1;
 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 org.apache.calcite.util.Util;
 
 import com.google.common.collect.ImmutableList;
@@ -48,10 +40,9 @@ public class VmstatTableFunction {
   private VmstatTableFunction() {}
 
   public static ScannableTable eval(boolean b) {
-    return new ScannableTable() {
+    return new AbstractBaseScannableTable() {
       @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
-        JavaTypeFactory typeFactory = root.getTypeFactory();
-        final RelDataType rowType = getRowType(typeFactory);
+        final RelDataType rowType = getRowType(root.getTypeFactory());
         final List<String> fieldNames =
             ImmutableList.copyOf(rowType.getFieldNames());
         final String[] args;
@@ -152,23 +143,6 @@ public class VmstatTableFunction {
               .build();
         }
       }
-
-      @Override public Statistic getStatistic() {
-        return Statistics.of(1000d, ImmutableList.of(ImmutableBitSet.of(1)));
-      }
-
-      @Override public Schema.TableType getJdbcTableType() {
-        return Schema.TableType.TABLE;
-      }
-
-      @Override public boolean isRolledUp(String column) {
-        return false;
-      }
-
-      @Override public boolean rolledUpColumnValidInsideAgg(String column, 
SqlCall call,
-          @Nullable SqlNode parent, @Nullable CalciteConnectionConfig config) {
-        return true;
-      }
     };
   }
 }
diff --git 
a/plus/src/main/java/org/apache/calcite/adapter/utils/OsQueryTableUtil.java 
b/plus/src/main/java/org/apache/calcite/adapter/utils/OsQueryTableUtil.java
new file mode 100644
index 0000000000..9b55830d82
--- /dev/null
+++ b/plus/src/main/java/org/apache/calcite/adapter/utils/OsQueryTableUtil.java
@@ -0,0 +1,250 @@
+/*
+ * 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.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+
+import cn.hutool.system.oshi.CpuTicks;
+import cn.hutool.system.oshi.OshiUtil;
+import oshi.hardware.CentralProcessor;
+import oshi.hardware.GlobalMemory;
+import oshi.hardware.NetworkIF;
+import oshi.hardware.VirtualMemory;
+import oshi.software.os.FileSystem;
+import oshi.software.os.OSFileStore;
+import oshi.software.os.OperatingSystem;
+
+/**
+ * Used to put OS query related func.
+ */
+public class OsQueryTableUtil {
+  private static final String IP_ADDRESS_SEPARATOR = "; ";
+
+  private OsQueryTableUtil() {
+  }
+
+  public static List<Object[]> getSystemInfo() {
+    final List<Object[]> list = new ArrayList<>();
+    Object[] objects = {
+        OshiUtil.getOs().getNetworkParams().getHostName(),
+        OshiUtil.getSystem().getSerialNumber(),
+        
OshiUtil.getProcessor().getProcessorIdentifier().getMicroarchitecture(),
+        OshiUtil.getProcessor().getProcessorIdentifier().getVendor(),
+        OshiUtil.getProcessor().getProcessorIdentifier().getModel(),
+        OshiUtil.getProcessor().getPhysicalProcessorCount(),
+        OshiUtil.getProcessor().getLogicalProcessorCount(),
+        OshiUtil.getProcessor().getPhysicalPackageCount(),
+        OshiUtil.getMemory().getTotal(),
+        
OshiUtil.getHardware().getComputerSystem().getFirmware().getManufacturer(),
+        OshiUtil.getHardware().getComputerSystem().getModel(),
+        OshiUtil.getHardware().getComputerSystem().getFirmware().getVersion(),
+        OshiUtil.getHardware().getComputerSystem().getSerialNumber(),
+        
OshiUtil.getHardware().getComputerSystem().getBaseboard().getManufacturer(),
+        OshiUtil.getHardware().getComputerSystem().getBaseboard().getModel(),
+        OshiUtil.getHardware().getComputerSystem().getBaseboard().getVersion(),
+        
OshiUtil.getHardware().getComputerSystem().getBaseboard().getSerialNumber(),
+        OshiUtil.getOs().getNetworkParams().getDomainName()
+    };
+    list.add(objects);
+    return list;
+  }
+
+  public static List<Object[]> getJavaInfo() {
+    final List<Object[]> list = new ArrayList<>();
+    final Properties props = System.getProperties();
+    final Object[] objects = {
+        props.getProperty("java.version"),
+        props.getProperty("java.vendor"),
+        props.getProperty("java.vendor.url"),
+        props.getProperty("java.home"),
+        props.getProperty("java.vm.specification.version"),
+        props.getProperty("java.vm.specification.vendor"),
+        props.getProperty("java.vm.specification.name"),
+        props.getProperty("java.vm.version"),
+        props.getProperty("java.vm.vendor"),
+        props.getProperty("java.vm.name"),
+        props.getProperty("java.specification.version"),
+        props.getProperty("java.specification.vender"),
+        props.getProperty("java.specification.name"),
+        props.getProperty("java.class.version"),
+        props.getProperty("java.class.path"),
+        props.getProperty("java.io.tmpdir"),
+        props.getProperty("java.ext.dirs"),
+        props.getProperty("java.library.path")
+    };
+    list.add(objects);
+    return list;
+  }
+
+  public static List<Object[]> getOsVersionInfo() {
+    final List<Object[]> list = new ArrayList<>();
+    OperatingSystem os = OshiUtil.getOs();
+    final Object[] objects = {
+        os.getVersionInfo().toString(),
+        os.getVersionInfo().getCodeName(),
+        os.getVersionInfo().getBuildNumber(),
+        os.getVersionInfo().getCodeName(),
+        os.getSystemBootTime()
+    };
+    list.add(objects);
+    return list;
+  }
+
+  public static List<Object[]> getMemoryInfo() {
+    GlobalMemory memory = OshiUtil.getMemory();
+    VirtualMemory virtualMemory = memory.getVirtualMemory();
+
+    final List<Object[]> list = new ArrayList<>();
+    final Object[] objects = {
+        getNetFileSizeDescription(memory.getTotal()),
+        getNetFileSizeDescription(memory.getAvailable()),
+        getNetFileSizeDescription(memory.getTotal() - memory.getAvailable()),
+        getNetFileSizeDescription(virtualMemory.getSwapTotal()),
+        getNetFileSizeDescription(virtualMemory.getSwapUsed()),
+        getNetFileSizeDescription(virtualMemory.getSwapTotal() - 
virtualMemory.getSwapUsed()),
+        getNetFileSizeDescription(virtualMemory.getSwapPagesIn()),
+        getNetFileSizeDescription(virtualMemory.getSwapPagesOut())
+    };
+    list.add(objects);
+    return list;
+  }
+
+  public static List<Object[]> getCpuInfo() {
+    final List<Object[]> list = new ArrayList<>();
+    CentralProcessor processor = OshiUtil.getProcessor();
+    Object[] objects = {
+        processor.getProcessorIdentifier().getProcessorID(),
+        processor.getProcessorIdentifier().getModel(),
+        processor.getProcessorIdentifier().getMicroarchitecture(),
+        processor.getPhysicalProcessorCount(),
+        processor.getLogicalProcessorCount(),
+        processor.getProcessorIdentifier().isCpu64bit() ? 64 : 32,
+        processor.getMaxFreq(),
+        processor.getPhysicalPackageCount(),
+        processor.getSystemCpuLoad(1000L)
+    };
+    list.add(objects);
+    return list;
+  }
+
+  public static List<Object[]> getCpuTimeInfo() {
+    final List<Object[]> list = new ArrayList<>();
+    CpuTicks cpuTicks = OshiUtil.getCpuInfo().getTicks();
+    Object[] objects = {
+        cpuTicks.getIdle(),
+        cpuTicks.getNice(),
+        cpuTicks.getIrq(),
+        cpuTicks.getSoftIrq(),
+        cpuTicks.getSteal(),
+        cpuTicks.getcSys(),
+        cpuTicks.getUser(),
+        cpuTicks.getIoWait()
+    };
+    list.add(objects);
+    return list;
+  }
+
+  public static List<Object[]> getInterfaceAddressesInfo() {
+    final List<Object[]> list = new ArrayList<>();
+    List<NetworkIF> networkIFList = OshiUtil.getNetworkIFs();
+    for (NetworkIF intf : networkIFList) {
+      Object[] objects = {
+          intf.getName(),
+          getIPAddressesString(intf.getIPv4addr()),
+          getIPAddressesString(intf.getIPv6addr()),
+          intf.getMacaddr(),
+          intf.getIfOperStatus().toString().contains("UNKNOWN") ? "" : 
intf.getIfOperStatus()
+      };
+      list.add(objects);
+    }
+    return list;
+  }
+
+  public static List<Object[]> getInterfaceDetailsInfo() {
+    final List<Object[]> list = new ArrayList<>();
+    List<NetworkIF> networkIFList = OshiUtil.getNetworkIFs();
+    for (NetworkIF intf : networkIFList) {
+      Object[] objects = {
+          intf.getName(),
+          intf.getMacaddr(),
+          intf.queryNetworkInterface().isVirtual(),
+          intf.getMTU(),
+          intf.getSpeed(),
+          intf.getPacketsRecv(),
+          intf.getPacketsSent(),
+          intf.getBytesRecv(),
+          intf.getBytesSent(),
+          intf.getInErrors(),
+          intf.getOutErrors(),
+          intf.getInDrops(),
+          intf.getCollisions()
+      };
+      list.add(objects);
+    }
+    return list;
+  }
+
+  public static List<Object[]> getMountsInfo() {
+    final List<Object[]> list = new ArrayList<>();
+    FileSystem fileSystem = OshiUtil.getOs().getFileSystem();
+    List<OSFileStore> fileStores = fileSystem.getFileStores();
+    for (OSFileStore fileStore : fileStores) {
+      Object[] objects = {
+          fileStore.getName(),
+          fileStore.getName(),
+          getNetFileSizeDescription(fileStore.getTotalSpace()),
+          getNetFileSizeDescription(fileStore.getUsableSpace()),
+          getNetFileSizeDescription(fileStore.getFreeSpace()),
+          getNetFileSizeDescription(fileStore.getTotalInodes()),
+          getNetFileSizeDescription(fileStore.getFreeInodes()),
+          fileStore.getMount()
+      };
+      list.add(objects);
+    }
+    return list;
+  }
+
+  public static String getIPAddressesString(String[] ipAddressArr) {
+    StringBuilder sb = new StringBuilder();
+    boolean first = true;
+
+    for (String ipAddress : ipAddressArr) {
+      if (first) {
+        first = false;
+      } else {
+        sb.append(IP_ADDRESS_SEPARATOR);
+      }
+      sb.append(ipAddress);
+    }
+
+    return sb.toString();
+  }
+
+  public static String getNetFileSizeDescription(long size) {
+    String[] units = {"B", "KB", "MB", "GB"};
+    int index = 0;
+    double fileSize = size;
+    while (fileSize >= 1024 && index < units.length - 1) {
+      fileSize /= 1024;
+      index++;
+    }
+    return String.format(Locale.ROOT, "%.2f%s", fileSize, units[index]);
+  }
+}
diff --git a/plus/build.gradle.kts 
b/plus/src/main/java/org/apache/calcite/adapter/utils/package-info.java
similarity index 51%
copy from plus/build.gradle.kts
copy to plus/src/main/java/org/apache/calcite/adapter/utils/package-info.java
index fc696a4497..619fdc2c2d 100644
--- a/plus/build.gradle.kts
+++ b/plus/src/main/java/org/apache/calcite/adapter/utils/package-info.java
@@ -14,23 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-dependencies {
-    api(project(":core"))
-    api(project(":linq4j"))
-    api("net.hydromatic:quidem")
-    api("org.apache.calcite.avatica:avatica-core")
-    api("org.checkerframework:checker-qual")
 
-    implementation("com.google.guava:guava")
-    implementation("com.teradata.tpcds:tpcds")
-    implementation("io.prestosql.tpch:tpch")
-    implementation("net.hydromatic:chinook-data-hsqldb")
-    implementation("net.hydromatic:tpcds")
-    implementation("org.apache.calcite.avatica:avatica-server")
-    implementation("org.hsqldb:hsqldb::jdk8")
-
-    testImplementation("net.hydromatic:sql-logic-test")
-    testImplementation(project(":testkit"))
-    testImplementation("org.incava:java-diff")
-    testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j-impl")
-}
+/**
+ * Used to put OS adapter related util classes.
+ */
+package org.apache.calcite.adapter.utils;
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 33d0aba9d8..ab03a8198a 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
@@ -36,12 +36,14 @@ import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.sql.SQLException;
 import java.util.function.Consumer;
 
 import static org.apache.calcite.util.TestUtil.rethrow;
 
+import static org.hamcrest.CoreMatchers.any;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.CoreMatchers.startsWith;
@@ -53,6 +55,8 @@ import static org.junit.jupiter.api.Assertions.fail;
 import static org.junit.jupiter.api.Assumptions.assumeFalse;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * Unit tests for the OS (operating system) adapter.
  *
@@ -68,16 +72,18 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
  * </ul>
  */
 class OsAdapterTest {
+  private static final String OS_NAME = System.getProperty("os.name");
+
   private static boolean isWindows() {
-    return System.getProperty("os.name").startsWith("Windows");
+    return OS_NAME.startsWith("Windows");
   }
 
   /** Returns whether there is a ".git" directory in this directory or in a
    * directory between this directory and root. */
   private static boolean hasGit() {
     assumeToolExists("git");
-    final String path = Sources.of(OsAdapterTest.class.getResource("/"))
-        .file().getAbsolutePath();
+    final URL url = requireNonNull(OsAdapterTest.class.getResource("/"));
+    final String path = Sources.of(url).file().getAbsolutePath();
     File f = new File(path);
     for (;;) {
       if (f == null || !f.exists()) {
@@ -212,10 +218,11 @@ class OsAdapterTest {
     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));
+        if (r.next()) {
+          assertThat(r.getString(1), notNullValue());
+          assertThat(r.getString(2), notNullValue());
+          assertThat(r.wasNull(), is(false));
+        }
       } catch (SQLException e) {
         throw TestUtil.rethrow(e);
       }
@@ -242,17 +249,17 @@ class OsAdapterTest {
 
   @Test void testStdin() throws SQLException {
     try (Hook.Closeable ignore =
-             Hook.STANDARD_STREAMS.addThread((Consumer<Holder<Object[]>>) o -> 
{
-               final Object[] values = o.get();
-               final InputStream in = (InputStream) values[0];
-               final String s = "First line\n"
-                   + "Second line";
-               final ByteArrayInputStream in2 =
-                   new 
ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8));
-               final OutputStream out = (OutputStream) values[1];
-               final OutputStream err = (OutputStream) values[2];
-               o.set(new Object[] {in2, out, err});
-             })) {
+        Hook.STANDARD_STREAMS.addThread((Consumer<Holder<Object[]>>) o -> {
+          final Object[] values = o.get();
+          final InputStream in = (InputStream) values[0];
+          final String s = "First line\n"
+              + "Second line";
+          final ByteArrayInputStream in2 =
+              new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8));
+          final OutputStream out = (OutputStream) values[1];
+          final OutputStream err = (OutputStream) values[2];
+          o.set(new Object[] {in2, out, err});
+        })) {
       assertThat(foo("select count(*) as c from stdin"), is("2\n"));
     }
   }
@@ -388,4 +395,58 @@ class OsAdapterTest {
         .with(CalciteConnectionProperty.CONFORMANCE, 
SqlConformanceEnum.LENIENT)
         .query(sql);
   }
+
+  private void checkOsQuery(String tableName, int colSize) {
+    final String q = "select * from " + tableName;
+    sql(q).returns(r -> {
+      try {
+        if (r.next()) {
+          for (int i = 1; i <= colSize; i++) {
+            if (r.getString(i) != null) {
+              assertThat(r.getString(i), any(String.class));
+            }
+          }
+          assertThat(r.wasNull(), is(false));
+        }
+      } catch (SQLException e) {
+        throw TestUtil.rethrow(e);
+      }
+    });
+  }
+
+  @Test void testSystemInfo() {
+    checkOsQuery("system_info", 18);
+  }
+
+  @Test void testJavaInfo() {
+    checkOsQuery("java_info", 18);
+  }
+
+  @Test void testCpuInfo() {
+    checkOsQuery("cpu_info", 9);
+  }
+
+  @Test void testCpuTime() {
+    checkOsQuery("cpu_time", 8);
+  }
+
+  @Test void testOsVersion() {
+    checkOsQuery("os_version", 5);
+  }
+
+  @Test void testMemoryInfo() {
+    checkOsQuery("memory_info", 8);
+  }
+
+  @Test void testInterfaceAddresses() {
+    checkOsQuery("interface_addresses", 5);
+  }
+
+  @Test void testInterfaceDetails() {
+    checkOsQuery("interface_details", 13);
+  }
+
+  @Test void testMounts() {
+    checkOsQuery("mounts", 8);
+  }
 }
diff --git a/site/_docs/os_adapter.md b/site/_docs/os_adapter.md
index 4575a6a75e..3f543b3d58 100644
--- a/site/_docs/os_adapter.md
+++ b/site/_docs/os_adapter.md
@@ -88,11 +88,20 @@ care. Often adding a back-slash will suffice.
 
 The OS adapter contains the following tables:
 
+* `cpu_info` - CPU information (from [oshi](https://github.com/oshi/oshi))
+* `cpu_time` - CPU time (from oshi)
 * `du` - Disk usage (based on `du` command)
-* `ps` - Processes (based on `ps` command)
-* `stdin` - Standard input
 * `files` - Files (based on the `find` command)
 * `git_commits` - Git commits (based on `git log`)
+* `interface_addresses` - Network addresses (from oshi)
+* `interface_details` - Network interface (from oshi)
+* `java_info` - Java information (from oshi)
+* `memory_info` - Memory (from oshi)
+* `mounts` - File system mounts (from oshi)
+* `os_version` - Operating System version (from oshi)
+* `ps` - Processes (based on `ps` command)
+* `stdin` - Standard input
+* `system_info` - System information (from oshi)
 * `vmstat` - Virtual memory (based on `vmstat` command)
 
 Most tables are implemented as views on top of table functions.

Reply via email to