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

mbudiu 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 12b3f3a6e4 [CALCITE-5649] Get row count statistics from 
ReflectiveSchema
12b3f3a6e4 is described below

commit 12b3f3a6e486ef0d1cfce44664125372e35109bf
Author: Adam Kennedy <[email protected]>
AuthorDate: Fri Apr 14 17:47:08 2023 -0700

    [CALCITE-5649] Get row count statistics from ReflectiveSchema
    
    Get row counts for tables in reflective schemas that are represented
    both as arrays and as Collection objects.
---
 .../calcite/adapter/java/ReflectiveSchema.java     | 17 ++++++++-
 .../calcite/test/MaterializedViewTester.java       |  3 +-
 .../apache/calcite/test/ReflectiveSchemaTest.java  | 36 +++++++++++++++++++
 .../test/enumerable/EnumerableCorrelateTest.java   |  4 +--
 .../test/enumerable/EnumerableHashJoinTest.java    |  4 +--
 .../test/enumerable/EnumerableRepeatUnionTest.java |  5 +--
 .../org/apache/calcite/test/CalciteAssert.java     |  2 +-
 .../java/org/apache/calcite/test/QuidemTest.java   |  3 +-
 .../test/ReflectiveSchemaWithoutRowCount.java      | 41 ++++++++++++++++++++++
 9 files changed, 103 insertions(+), 12 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/adapter/java/ReflectiveSchema.java 
b/core/src/main/java/org/apache/calcite/adapter/java/ReflectiveSchema.java
index ba1f9f70fa..5e317fe6a1 100644
--- a/core/src/main/java/org/apache/calcite/adapter/java/ReflectiveSchema.java
+++ b/core/src/main/java/org/apache/calcite/adapter/java/ReflectiveSchema.java
@@ -56,11 +56,13 @@ import com.google.common.collect.Multimap;
 import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
 import org.checkerframework.checker.nullness.qual.Nullable;
 
+import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -205,7 +207,11 @@ public class ReflectiveSchema
     requireNonNull(o, () -> "field " + field + " is null for " + target);
     @SuppressWarnings("unchecked")
     final Enumerable<T> enumerable = toEnumerable(o);
-    return new FieldTable<>(field, elementType, enumerable);
+    final Double rows = getRowCount(o);
+    final Statistic statistic = rows == null
+        ? Statistics.UNKNOWN
+        : Statistics.of(rows, null);
+    return new FieldTable<>(field, elementType, enumerable, statistic);
   }
 
   /** Deduces the element type of a collection;
@@ -235,6 +241,15 @@ public class ReflectiveSchema
         "Cannot convert " + o.getClass() + " into a Enumerable");
   }
 
+  protected @Nullable Double getRowCount(final Object o) {
+    if (o.getClass().isArray()) {
+      return (double) Array.getLength(o);
+    } else if (o instanceof Collection) {
+      return (double) ((Collection<?>) o).size();
+    }
+    return null;
+  }
+
   /** Table that is implemented by reading from a Java object. */
   private static class ReflectiveTable
       extends AbstractQueryableTable
diff --git 
a/core/src/test/java/org/apache/calcite/test/MaterializedViewTester.java 
b/core/src/test/java/org/apache/calcite/test/MaterializedViewTester.java
index 146a8de6f3..0f3e0dafdf 100644
--- a/core/src/test/java/org/apache/calcite/test/MaterializedViewTester.java
+++ b/core/src/test/java/org/apache/calcite/test/MaterializedViewTester.java
@@ -18,7 +18,6 @@ package org.apache.calcite.test;
 
 import org.apache.calcite.DataContexts;
 import org.apache.calcite.adapter.enumerable.EnumerableTableScan;
-import org.apache.calcite.adapter.java.ReflectiveSchema;
 import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.jdbc.CalciteSchema;
 import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
@@ -114,7 +113,7 @@ public abstract class MaterializedViewTester {
         if (f.schemaSpec == null) {
           defaultSchema =
               rootSchema.add("hr",
-                  new ReflectiveSchema(new 
MaterializationTest.HrFKUKSchema()));
+                  new ReflectiveSchemaWithoutRowCount(new 
MaterializationTest.HrFKUKSchema()));
         } else {
           defaultSchema = CalciteAssert.addSchema(rootSchema, f.schemaSpec);
         }
diff --git 
a/core/src/test/java/org/apache/calcite/test/ReflectiveSchemaTest.java 
b/core/src/test/java/org/apache/calcite/test/ReflectiveSchemaTest.java
index 8360dc7123..0ed43d2783 100644
--- a/core/src/test/java/org/apache/calcite/test/ReflectiveSchemaTest.java
+++ b/core/src/test/java/org/apache/calcite/test/ReflectiveSchemaTest.java
@@ -29,11 +29,14 @@ import org.apache.calcite.linq4j.tree.Expressions;
 import org.apache.calcite.linq4j.tree.ParameterExpression;
 import org.apache.calcite.linq4j.tree.Types;
 import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.Statistic;
+import org.apache.calcite.schema.Table;
 import org.apache.calcite.schema.impl.AbstractSchema;
 import org.apache.calcite.schema.impl.TableMacroImpl;
 import org.apache.calcite.schema.impl.ViewTable;
 import org.apache.calcite.test.schemata.catchall.CatchallSchema;
 import org.apache.calcite.test.schemata.catchall.CatchallSchema.EveryType;
+import org.apache.calcite.test.schemata.hr.Dependent;
 import org.apache.calcite.test.schemata.hr.Employee;
 import org.apache.calcite.test.schemata.hr.HrSchema;
 import org.apache.calcite.util.Smalls;
@@ -65,6 +68,7 @@ import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.hasToString;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
@@ -79,6 +83,15 @@ public class ReflectiveSchemaTest {
   private static final ReflectiveSchema CATCHALL =
       new ReflectiveSchema(new CatchallSchema());
 
+  /**
+   * Extension of HrSchema with a dummy field for testing a row count from a 
Collection.
+   */
+  public static class HrSchemaPlus extends HrSchema {
+    public final ImmutableList<Dependent> xlocations =
+        ImmutableList.of(new Dependent(10, "San Francisco"),
+            new Dependent(20, "San Diego"));
+  }
+
   /**
    * Test that uses a JDBC connection as a linq4j
    * {@link org.apache.calcite.linq4j.QueryProvider}.
@@ -919,4 +932,27 @@ public class ReflectiveSchemaTest {
             "EXPR$0=0",
             "EXPR$0=null");
   }
+
+  /**
+   * Test that the row count statistic can be retrieved from a 
ReflectiveSchema.
+   *
+   * @see <a 
href="https://issues.apache.org/jira/browse/CALCITE-5649";>[CALCITE-5649]</a>
+   */
+  @Test void testArrayFieldTableHasRowCount() {
+    ReflectiveSchema schema = new ReflectiveSchema(new HrSchema());
+    Table table = schema.getTable("emps");
+    assertNotNull(table);
+    Statistic statistic = table.getStatistic();
+    assertNotNull(statistic);
+    assertEquals(4, statistic.getRowCount());
+  }
+
+  @Test void testCollectionFieldTableHasRowCount() {
+    ReflectiveSchema schema = new ReflectiveSchema(new HrSchemaPlus());
+    Table table = schema.getTable("xlocations");
+    assertNotNull(table);
+    Statistic statistic = table.getStatistic();
+    assertNotNull(statistic);
+    assertEquals(2, statistic.getRowCount());
+  }
 }
diff --git 
a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java
 
b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java
index 4dc0d4fb8e..e1cd3dda83 100644
--- 
a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java
+++ 
b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java
@@ -18,7 +18,6 @@ package org.apache.calcite.test.enumerable;
 
 import org.apache.calcite.adapter.enumerable.EnumerableCorrelate;
 import org.apache.calcite.adapter.enumerable.EnumerableRules;
-import org.apache.calcite.adapter.java.ReflectiveSchema;
 import org.apache.calcite.config.CalciteConnectionProperty;
 import org.apache.calcite.config.Lex;
 import org.apache.calcite.plan.RelOptPlanner;
@@ -26,6 +25,7 @@ import org.apache.calcite.rel.rules.CoreRules;
 import org.apache.calcite.runtime.Hook;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.test.CalciteAssert;
+import org.apache.calcite.test.ReflectiveSchemaWithoutRowCount;
 import org.apache.calcite.test.schemata.hr.HrSchema;
 
 import org.junit.jupiter.api.Test;
@@ -283,6 +283,6 @@ class EnumerableCorrelateTest {
     return CalciteAssert.that()
         .with(CalciteConnectionProperty.LEX, Lex.JAVA)
         .with(CalciteConnectionProperty.FORCE_DECORRELATE, forceDecorrelate)
-        .withSchema("s", new ReflectiveSchema(schema));
+        .withSchema("s", new ReflectiveSchemaWithoutRowCount(schema));
   }
 }
diff --git 
a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableHashJoinTest.java
 
b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableHashJoinTest.java
index 1207e405c2..5545a47217 100644
--- 
a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableHashJoinTest.java
+++ 
b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableHashJoinTest.java
@@ -17,13 +17,13 @@
 package org.apache.calcite.test.enumerable;
 
 import org.apache.calcite.adapter.enumerable.EnumerableRules;
-import org.apache.calcite.adapter.java.ReflectiveSchema;
 import org.apache.calcite.config.CalciteConnectionProperty;
 import org.apache.calcite.config.Lex;
 import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.runtime.Hook;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.test.CalciteAssert;
+import org.apache.calcite.test.ReflectiveSchemaWithoutRowCount;
 import org.apache.calcite.test.schemata.hr.HrSchema;
 
 import org.junit.jupiter.api.Test;
@@ -306,6 +306,6 @@ class EnumerableHashJoinTest {
     return CalciteAssert.that()
         .with(CalciteConnectionProperty.LEX, Lex.JAVA)
         .with(CalciteConnectionProperty.FORCE_DECORRELATE, forceDecorrelate)
-        .withSchema("s", new ReflectiveSchema(schema));
+        .withSchema("s", new ReflectiveSchemaWithoutRowCount(schema));
   }
 }
diff --git 
a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableRepeatUnionTest.java
 
b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableRepeatUnionTest.java
index 83594c6145..5803667d1d 100644
--- 
a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableRepeatUnionTest.java
+++ 
b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableRepeatUnionTest.java
@@ -29,6 +29,7 @@ import org.apache.calcite.rel.rules.JoinToCorrelateRule;
 import org.apache.calcite.runtime.Hook;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.test.CalciteAssert;
+import org.apache.calcite.test.ReflectiveSchemaWithoutRowCount;
 import org.apache.calcite.test.schemata.hr.HierarchySchema;
 
 import org.junit.jupiter.api.Test;
@@ -266,7 +267,7 @@ class EnumerableRepeatUnionTest {
     CalciteAssert.that()
         .with(CalciteConnectionProperty.LEX, Lex.JAVA)
         .with(CalciteConnectionProperty.FORCE_DECORRELATE, false)
-        .withSchema("s", new ReflectiveSchema(new HierarchySchema()))
+        .withSchema("s", new ReflectiveSchemaWithoutRowCount(new 
HierarchySchema()))
         .withHook(Hook.PLANNER, (Consumer<RelOptPlanner>) planner -> {
           planner.addRule(JoinToCorrelateRule.Config.DEFAULT.toRule());
           planner.removeRule(JoinCommuteRule.Config.DEFAULT.toRule());
@@ -309,7 +310,7 @@ class EnumerableRepeatUnionTest {
     CalciteAssert.that()
         .with(CalciteConnectionProperty.LEX, Lex.JAVA)
         .with(CalciteConnectionProperty.FORCE_DECORRELATE, false)
-        .withSchema("s", new ReflectiveSchema(new HierarchySchema()))
+        .withSchema("s", new ReflectiveSchemaWithoutRowCount(new 
HierarchySchema()))
         .withHook(Hook.PLANNER, (Consumer<RelOptPlanner>) planner -> {
           planner.addRule(JoinToCorrelateRule.Config.DEFAULT.toRule());
           planner.removeRule(JoinCommuteRule.Config.DEFAULT.toRule());
diff --git a/testkit/src/main/java/org/apache/calcite/test/CalciteAssert.java 
b/testkit/src/main/java/org/apache/calcite/test/CalciteAssert.java
index b0c615180c..089bb53b00 100644
--- a/testkit/src/main/java/org/apache/calcite/test/CalciteAssert.java
+++ b/testkit/src/main/java/org/apache/calcite/test/CalciteAssert.java
@@ -899,7 +899,7 @@ public class CalciteAssert {
       return s;
     case HR:
       return rootSchema.add(schema.schemaName,
-          new ReflectiveSchema(new HrSchema()));
+          new ReflectiveSchemaWithoutRowCount(new HrSchema()));
     case LINGUAL:
       return rootSchema.add(schema.schemaName,
           new ReflectiveSchema(new LingualSchema()));
diff --git a/testkit/src/main/java/org/apache/calcite/test/QuidemTest.java 
b/testkit/src/main/java/org/apache/calcite/test/QuidemTest.java
index 9760536492..c7b59fd826 100644
--- a/testkit/src/main/java/org/apache/calcite/test/QuidemTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/QuidemTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.calcite.test;
 
-import org.apache.calcite.adapter.java.ReflectiveSchema;
 import org.apache.calcite.avatica.AvaticaUtils;
 import org.apache.calcite.config.CalciteConnectionProperty;
 import org.apache.calcite.jdbc.CalciteConnection;
@@ -326,7 +325,7 @@ public abstract class QuidemTest {
         return CalciteAssert.that()
             .with(CalciteConnectionProperty.TIME_ZONE, "UTC")
             .withSchema("s",
-                new ReflectiveSchema(
+                new ReflectiveSchemaWithoutRowCount(
                     new CatchallSchema()))
             .connect();
       case "orinoco":
diff --git 
a/testkit/src/main/java/org/apache/calcite/test/ReflectiveSchemaWithoutRowCount.java
 
b/testkit/src/main/java/org/apache/calcite/test/ReflectiveSchemaWithoutRowCount.java
new file mode 100644
index 0000000000..d87173a871
--- /dev/null
+++ 
b/testkit/src/main/java/org/apache/calcite/test/ReflectiveSchemaWithoutRowCount.java
@@ -0,0 +1,41 @@
+/*
+ * 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.test;
+
+import org.apache.calcite.adapter.java.ReflectiveSchema;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+/**
+ * A ReflectiveSchema that does not return row count statistics.
+ * Intended to be used with tests written before row count statistics were 
supported
+ * by ReflectiveSchema that rely on legacy behavior.
+ */
+public class ReflectiveSchemaWithoutRowCount extends ReflectiveSchema  {
+  /**
+   * Creates a ReflectiveSchema.
+   *
+   * @param target Object whose fields will be sub-objects of the schema
+   */
+  public ReflectiveSchemaWithoutRowCount(Object target) {
+    super(target);
+  }
+
+  @Override protected @Nullable Double getRowCount(Object o) {
+    return null;
+  }
+}

Reply via email to