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;
+ }
+}