jacques-n commented on a change in pull request #2378:
URL: https://github.com/apache/calcite/pull/2378#discussion_r742179082
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
##########
@@ -107,47 +106,69 @@
private BuiltInMetadata.LowerBoundCost.Handler lowerBoundCostHandler;
/**
- * Creates the instance with {@link JaninoRelMetadataProvider} instance
- * from {@link #THREAD_PROVIDERS} and {@link #EMPTY} as a prototype.
+ * Creates the instance using the Handler.classualt prototype.
*/
protected RelMetadataQuery() {
- this(castNonNull(THREAD_PROVIDERS.get()), EMPTY);
+ this(PROTOTYPE);
}
/** Creates and initializes the instance that will serve as a prototype for
* all other instances. */
- private RelMetadataQuery(@SuppressWarnings("unused") boolean dummy) {
- super(null);
- this.collationHandler =
initialHandler(BuiltInMetadata.Collation.Handler.class);
- this.columnOriginHandler =
initialHandler(BuiltInMetadata.ColumnOrigin.Handler.class);
- this.expressionLineageHandler =
initialHandler(BuiltInMetadata.ExpressionLineage.Handler.class);
- this.tableReferencesHandler =
initialHandler(BuiltInMetadata.TableReferences.Handler.class);
- this.columnUniquenessHandler =
initialHandler(BuiltInMetadata.ColumnUniqueness.Handler.class);
- this.cumulativeCostHandler =
initialHandler(BuiltInMetadata.CumulativeCost.Handler.class);
- this.distinctRowCountHandler =
initialHandler(BuiltInMetadata.DistinctRowCount.Handler.class);
- this.distributionHandler =
initialHandler(BuiltInMetadata.Distribution.Handler.class);
- this.explainVisibilityHandler =
initialHandler(BuiltInMetadata.ExplainVisibility.Handler.class);
- this.maxRowCountHandler =
initialHandler(BuiltInMetadata.MaxRowCount.Handler.class);
- this.minRowCountHandler =
initialHandler(BuiltInMetadata.MinRowCount.Handler.class);
- this.memoryHandler = initialHandler(BuiltInMetadata.Memory.Handler.class);
- this.nonCumulativeCostHandler =
initialHandler(BuiltInMetadata.NonCumulativeCost.Handler.class);
- this.parallelismHandler =
initialHandler(BuiltInMetadata.Parallelism.Handler.class);
+ protected RelMetadataQuery(MetadataHandlerProvider metadataHandlerProvider) {
Review comment:
I'd like to separate the concern and the two solution into two separate
discussions.
First the concern:
The problem is the coupling between RelMetdataQuery and RelMetdataProvider.
In this patch you add additional new public apis that reinforce this coupling.
There is no need for the coupling. It is completely reasonable that someone
should be able to implement RelMetadataQuery without having to work at all with
RelMetdataProvider related items. That is the beauty of the RelMetadataQuery
surface area from the planning/rule pov. For example, someone should be able
hand write a RelMetadatQuery implementation that has all the handling of
supported rel types.
Second, the solution:
It is important to remove the coupling of RelMetdataQuery and
RelMetdataProvider. Ideally, we would convert RelMetadataQuery to an abstract
implementation (or interface) that only does a minimal number of data
cleansing/canonicalization options (null to sentinels, conveniences interfaces,
etc). However, because of the exposure of the protected constructor for
RelMetadatQuery, this has to be done in two steps to avoid breaking changes. I
proposed one way to get there but I don't think it is the only way. I don't
understand any of your comments around complexity, more subclasses, caching
cyclic dependency and boiler plate. As part of the first step towards a clean
api there has to be some shims to support old users until we can remove old
apis but that's also true with all of these metadata patches. We shouldn't
dismiss an ultimately cleaner solution because we have to maintain a shim for
one release (and really, a shim must exist in either case).
Lastly, it would be good to clarify what you mean by breaking changes. In
both the proposal I've put forward and the current patch, I see
deprecation/upgrade paths required (new apis that replace old apis exist
simultaneously and then old apis are removed post version deprecation). In both
cases, a user should have to do no code changes when upgrading but should see
deprecation warnings and then the following upgrade would see breakage if they
didn't solve deprecation warnings.
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
##########
@@ -107,47 +106,69 @@
private BuiltInMetadata.LowerBoundCost.Handler lowerBoundCostHandler;
/**
- * Creates the instance with {@link JaninoRelMetadataProvider} instance
- * from {@link #THREAD_PROVIDERS} and {@link #EMPTY} as a prototype.
+ * Creates the instance using the Handler.classualt prototype.
*/
protected RelMetadataQuery() {
- this(castNonNull(THREAD_PROVIDERS.get()), EMPTY);
+ this(PROTOTYPE);
}
/** Creates and initializes the instance that will serve as a prototype for
* all other instances. */
- private RelMetadataQuery(@SuppressWarnings("unused") boolean dummy) {
- super(null);
- this.collationHandler =
initialHandler(BuiltInMetadata.Collation.Handler.class);
- this.columnOriginHandler =
initialHandler(BuiltInMetadata.ColumnOrigin.Handler.class);
- this.expressionLineageHandler =
initialHandler(BuiltInMetadata.ExpressionLineage.Handler.class);
- this.tableReferencesHandler =
initialHandler(BuiltInMetadata.TableReferences.Handler.class);
- this.columnUniquenessHandler =
initialHandler(BuiltInMetadata.ColumnUniqueness.Handler.class);
- this.cumulativeCostHandler =
initialHandler(BuiltInMetadata.CumulativeCost.Handler.class);
- this.distinctRowCountHandler =
initialHandler(BuiltInMetadata.DistinctRowCount.Handler.class);
- this.distributionHandler =
initialHandler(BuiltInMetadata.Distribution.Handler.class);
- this.explainVisibilityHandler =
initialHandler(BuiltInMetadata.ExplainVisibility.Handler.class);
- this.maxRowCountHandler =
initialHandler(BuiltInMetadata.MaxRowCount.Handler.class);
- this.minRowCountHandler =
initialHandler(BuiltInMetadata.MinRowCount.Handler.class);
- this.memoryHandler = initialHandler(BuiltInMetadata.Memory.Handler.class);
- this.nonCumulativeCostHandler =
initialHandler(BuiltInMetadata.NonCumulativeCost.Handler.class);
- this.parallelismHandler =
initialHandler(BuiltInMetadata.Parallelism.Handler.class);
+ protected RelMetadataQuery(MetadataHandlerProvider metadataHandlerProvider) {
Review comment:
I'd like to separate the concern and the solution into two separate
discussions.
First the concern:
The problem is the coupling between RelMetdataQuery and RelMetdataProvider.
In this patch you add additional new public apis that reinforce this coupling.
There is no need for the coupling. It is completely reasonable that someone
should be able to implement RelMetadataQuery without having to work at all with
RelMetdataProvider related items. That is the beauty of the RelMetadataQuery
surface area from the planning/rule pov. For example, someone should be able
hand write a RelMetadatQuery implementation that has all the handling of
supported rel types.
Second, the solution:
It is important to remove the coupling of RelMetdataQuery and
RelMetdataProvider. Ideally, we would convert RelMetadataQuery to an abstract
implementation (or interface) that only does a minimal number of data
cleansing/canonicalization options (null to sentinels, conveniences interfaces,
etc). However, because of the exposure of the protected constructor for
RelMetadatQuery, this has to be done in two steps to avoid breaking changes. I
proposed one way to get there but I don't think it is the only way. I don't
understand any of your comments around complexity, more subclasses, caching
cyclic dependency and boiler plate. As part of the first step towards a clean
api there has to be some shims to support old users until we can remove old
apis but that's also true with all of these metadata patches. We shouldn't
dismiss an ultimately cleaner solution because we have to maintain a shim for
one release (and really, a shim must exist in either case).
Lastly, it would be good to clarify what you mean by breaking changes. In
both the proposal I've put forward and the current patch, I see
deprecation/upgrade paths required (new apis that replace old apis exist
simultaneously and then old apis are removed post version deprecation). In both
cases, a user should have to do no code changes when upgrading but should see
deprecation warnings and then the following upgrade would see breakage if they
didn't solve deprecation warnings.
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
##########
@@ -107,47 +106,69 @@
private BuiltInMetadata.LowerBoundCost.Handler lowerBoundCostHandler;
/**
- * Creates the instance with {@link JaninoRelMetadataProvider} instance
- * from {@link #THREAD_PROVIDERS} and {@link #EMPTY} as a prototype.
+ * Creates the instance using the Handler.classualt prototype.
*/
protected RelMetadataQuery() {
- this(castNonNull(THREAD_PROVIDERS.get()), EMPTY);
+ this(PROTOTYPE);
}
/** Creates and initializes the instance that will serve as a prototype for
* all other instances. */
- private RelMetadataQuery(@SuppressWarnings("unused") boolean dummy) {
- super(null);
- this.collationHandler =
initialHandler(BuiltInMetadata.Collation.Handler.class);
- this.columnOriginHandler =
initialHandler(BuiltInMetadata.ColumnOrigin.Handler.class);
- this.expressionLineageHandler =
initialHandler(BuiltInMetadata.ExpressionLineage.Handler.class);
- this.tableReferencesHandler =
initialHandler(BuiltInMetadata.TableReferences.Handler.class);
- this.columnUniquenessHandler =
initialHandler(BuiltInMetadata.ColumnUniqueness.Handler.class);
- this.cumulativeCostHandler =
initialHandler(BuiltInMetadata.CumulativeCost.Handler.class);
- this.distinctRowCountHandler =
initialHandler(BuiltInMetadata.DistinctRowCount.Handler.class);
- this.distributionHandler =
initialHandler(BuiltInMetadata.Distribution.Handler.class);
- this.explainVisibilityHandler =
initialHandler(BuiltInMetadata.ExplainVisibility.Handler.class);
- this.maxRowCountHandler =
initialHandler(BuiltInMetadata.MaxRowCount.Handler.class);
- this.minRowCountHandler =
initialHandler(BuiltInMetadata.MinRowCount.Handler.class);
- this.memoryHandler = initialHandler(BuiltInMetadata.Memory.Handler.class);
- this.nonCumulativeCostHandler =
initialHandler(BuiltInMetadata.NonCumulativeCost.Handler.class);
- this.parallelismHandler =
initialHandler(BuiltInMetadata.Parallelism.Handler.class);
+ protected RelMetadataQuery(MetadataHandlerProvider metadataHandlerProvider) {
Review comment:
To put this another way: RelMetadataQuery is the what,
RelMetadataProvider is one possible how. Let's not couple the two.
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/MetadataHandlerProvider.java
##########
@@ -0,0 +1,52 @@
+/*
+ * 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.rel.metadata;
+
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.util.ControlFlowException;
+
+/**
+ * Provides {@link MetadataHandler} call sites and {@link MetadataCache} for
+ * {@link RelMetadataQuery}. The handlers provided are responsible for
+ * updating the cache stored in {@link RelMetadataQuery}.
+ */
+public interface MetadataHandlerProvider {
+
+ <MH extends MetadataHandler<?>> MH initialHandler(Class<MH> handlerClass);
+
+ /** Re-generates the handler for a given kind of metadata.. */
+ <MH extends MetadataHandler<?>> MH revise(Class<MH> handlerClass);
+
+ /**
+ * Creates a new cache.
+ *
+ * @return A new cache for {@link RelMetadataQuery}
+ */
+ MetadataCache buildCache();
Review comment:
I don't really understand the meaning of this method. Why does someone
call this? What happens if I call it multiple times? What is this caching? Does
it have to be called? Why is it on this interface? Also, if you wanted to
customize the cache for things like a double property, wouldn't you potentially
want to implement a cache that avoided the constant creation of objects and
boxing (which the interface of MetadataCache forces)?
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQueryBase.java
##########
@@ -62,49 +62,56 @@
* </ol>
*/
public class RelMetadataQueryBase {
+
//~ Instance fields --------------------------------------------------------
/** Set of active metadata queries, and cache of previous results. */
- public final Table<RelNode, Object, Object> map = HashBasedTable.create();
+ @Deprecated // to be removed before 2.0
+ public final Table<RelNode, Object, Object> map;
- public final @Nullable JaninoRelMetadataProvider metadataProvider;
+ @API(status = API.Status.INTERNAL)
+ public final MetadataCache cache;
+ protected final MetadataHandlerProvider metadataHandlerProvider;
+
+ @Deprecated // to be removed before 2.0
+ public final @Nullable JaninoRelMetadataProvider metadataProvider =
THREAD_PROVIDERS.get();
//~ Static fields/initializers ---------------------------------------------
+ @Deprecated // to be removed before 2.0
public static final ThreadLocal<@Nullable JaninoRelMetadataProvider>
THREAD_PROVIDERS =
new ThreadLocal<>();
- //~ Constructors -----------------------------------------------------------
-
Review comment:
Isn't removing this constructor a breaking change?
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
##########
@@ -107,47 +109,70 @@
private BuiltInMetadata.LowerBoundCost.Handler lowerBoundCostHandler;
/**
- * Creates the instance with {@link JaninoRelMetadataProvider} instance
- * from {@link #THREAD_PROVIDERS} and {@link #EMPTY} as a prototype.
+ * Creates the instance using the Handler.classualt prototype.
*/
+ @Deprecated
protected RelMetadataQuery() {
- this(castNonNull(THREAD_PROVIDERS.get()), EMPTY);
+ this(PROTOTYPE);
}
/** Creates and initializes the instance that will serve as a prototype for
* all other instances. */
- private RelMetadataQuery(@SuppressWarnings("unused") boolean dummy) {
- super(null);
- this.collationHandler =
initialHandler(BuiltInMetadata.Collation.Handler.class);
- this.columnOriginHandler =
initialHandler(BuiltInMetadata.ColumnOrigin.Handler.class);
- this.expressionLineageHandler =
initialHandler(BuiltInMetadata.ExpressionLineage.Handler.class);
- this.tableReferencesHandler =
initialHandler(BuiltInMetadata.TableReferences.Handler.class);
- this.columnUniquenessHandler =
initialHandler(BuiltInMetadata.ColumnUniqueness.Handler.class);
- this.cumulativeCostHandler =
initialHandler(BuiltInMetadata.CumulativeCost.Handler.class);
- this.distinctRowCountHandler =
initialHandler(BuiltInMetadata.DistinctRowCount.Handler.class);
- this.distributionHandler =
initialHandler(BuiltInMetadata.Distribution.Handler.class);
- this.explainVisibilityHandler =
initialHandler(BuiltInMetadata.ExplainVisibility.Handler.class);
- this.maxRowCountHandler =
initialHandler(BuiltInMetadata.MaxRowCount.Handler.class);
- this.minRowCountHandler =
initialHandler(BuiltInMetadata.MinRowCount.Handler.class);
- this.memoryHandler = initialHandler(BuiltInMetadata.Memory.Handler.class);
- this.nonCumulativeCostHandler =
initialHandler(BuiltInMetadata.NonCumulativeCost.Handler.class);
- this.parallelismHandler =
initialHandler(BuiltInMetadata.Parallelism.Handler.class);
+ protected RelMetadataQuery(MetadataHandlerProvider metadataHandlerProvider) {
+ super(metadataHandlerProvider);
+ this.collationHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.Collation.Handler.class);
+ this.columnOriginHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.ColumnOrigin.Handler.class);
+ this.expressionLineageHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.ExpressionLineage.Handler.class);
+ this.tableReferencesHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.TableReferences.Handler.class);
+ this.columnUniquenessHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.ColumnUniqueness.Handler.class);
+ this.cumulativeCostHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.CumulativeCost.Handler.class);
+ this.distinctRowCountHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.DistinctRowCount.Handler.class);
+ this.distributionHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.Distribution.Handler.class);
+ this.explainVisibilityHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.ExplainVisibility.Handler.class);
+ this.maxRowCountHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.MaxRowCount.Handler.class);
+ this.minRowCountHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.MinRowCount.Handler.class);
+ this.memoryHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.Memory.Handler.class);
+ this.nonCumulativeCostHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.NonCumulativeCost.Handler.class);
+ this.parallelismHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.Parallelism.Handler.class);
this.percentageOriginalRowsHandler =
- initialHandler(BuiltInMetadata.PercentageOriginalRows.Handler.class);
- this.populationSizeHandler =
initialHandler(BuiltInMetadata.PopulationSize.Handler.class);
- this.predicatesHandler =
initialHandler(BuiltInMetadata.Predicates.Handler.class);
- this.allPredicatesHandler =
initialHandler(BuiltInMetadata.AllPredicates.Handler.class);
- this.nodeTypesHandler =
initialHandler(BuiltInMetadata.NodeTypes.Handler.class);
- this.rowCountHandler =
initialHandler(BuiltInMetadata.RowCount.Handler.class);
- this.selectivityHandler =
initialHandler(BuiltInMetadata.Selectivity.Handler.class);
- this.sizeHandler = initialHandler(BuiltInMetadata.Size.Handler.class);
- this.uniqueKeysHandler =
initialHandler(BuiltInMetadata.UniqueKeys.Handler.class);
- this.lowerBoundCostHandler =
initialHandler(BuiltInMetadata.LowerBoundCost.Handler.class);
- }
-
- private RelMetadataQuery(JaninoRelMetadataProvider metadataProvider,
- RelMetadataQuery prototype) {
- super(requireNonNull(metadataProvider, "metadataProvider"));
+ metadataHandlerProvider.initialHandler(
+ BuiltInMetadata.PercentageOriginalRows.Handler.class);
+ this.populationSizeHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.PopulationSize.Handler.class);
+ this.predicatesHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.Predicates.Handler.class);
+ this.allPredicatesHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.AllPredicates.Handler.class);
+ this.nodeTypesHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.NodeTypes.Handler.class);
+ this.rowCountHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.RowCount.Handler.class);
+ this.selectivityHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.Selectivity.Handler.class);
+ this.sizeHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.Size.Handler.class);
+ this.uniqueKeysHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.UniqueKeys.Handler.class);
+ this.lowerBoundCostHandler =
+
metadataHandlerProvider.initialHandler(BuiltInMetadata.LowerBoundCost.Handler.class);
+ }
+
+ protected RelMetadataQuery(RelMetadataQuery prototype) {
Review comment:
please make this private.
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/MetadataHandlerProvider.java
##########
@@ -0,0 +1,52 @@
+/*
+ * 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.rel.metadata;
+
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.util.ControlFlowException;
+
+/**
+ * Provides {@link MetadataHandler} call sites and {@link MetadataCache} for
+ * {@link RelMetadataQuery}. The handlers provided are responsible for
+ * updating the cache stored in {@link RelMetadataQuery}.
+ */
+public interface MetadataHandlerProvider {
Review comment:
Config feels like it would be weird here. As I have thought more about
the name I'm pretty much okay with it as is.
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
##########
@@ -107,47 +106,69 @@
private BuiltInMetadata.LowerBoundCost.Handler lowerBoundCostHandler;
/**
- * Creates the instance with {@link JaninoRelMetadataProvider} instance
- * from {@link #THREAD_PROVIDERS} and {@link #EMPTY} as a prototype.
+ * Creates the instance using the Handler.classualt prototype.
*/
protected RelMetadataQuery() {
- this(castNonNull(THREAD_PROVIDERS.get()), EMPTY);
+ this(PROTOTYPE);
}
/** Creates and initializes the instance that will serve as a prototype for
* all other instances. */
- private RelMetadataQuery(@SuppressWarnings("unused") boolean dummy) {
- super(null);
- this.collationHandler =
initialHandler(BuiltInMetadata.Collation.Handler.class);
- this.columnOriginHandler =
initialHandler(BuiltInMetadata.ColumnOrigin.Handler.class);
- this.expressionLineageHandler =
initialHandler(BuiltInMetadata.ExpressionLineage.Handler.class);
- this.tableReferencesHandler =
initialHandler(BuiltInMetadata.TableReferences.Handler.class);
- this.columnUniquenessHandler =
initialHandler(BuiltInMetadata.ColumnUniqueness.Handler.class);
- this.cumulativeCostHandler =
initialHandler(BuiltInMetadata.CumulativeCost.Handler.class);
- this.distinctRowCountHandler =
initialHandler(BuiltInMetadata.DistinctRowCount.Handler.class);
- this.distributionHandler =
initialHandler(BuiltInMetadata.Distribution.Handler.class);
- this.explainVisibilityHandler =
initialHandler(BuiltInMetadata.ExplainVisibility.Handler.class);
- this.maxRowCountHandler =
initialHandler(BuiltInMetadata.MaxRowCount.Handler.class);
- this.minRowCountHandler =
initialHandler(BuiltInMetadata.MinRowCount.Handler.class);
- this.memoryHandler = initialHandler(BuiltInMetadata.Memory.Handler.class);
- this.nonCumulativeCostHandler =
initialHandler(BuiltInMetadata.NonCumulativeCost.Handler.class);
- this.parallelismHandler =
initialHandler(BuiltInMetadata.Parallelism.Handler.class);
+ protected RelMetadataQuery(MetadataHandlerProvider metadataHandlerProvider) {
Review comment:
I think I have a simple solution to avoiding the introduction of a new
constructor on this class:
- Make this constructor private
- Add a new inner static subclass that uses that constructor and exposes a
protected class.
Then we tell people that want to use the handler behavior to extend that
subclass. That way, we have deprecated subclassing RelMetadataQuery directly
while moving towards this new pattern with minimal code changes.
This avoids the introduction of a new coupling api between RelMetadataQuery
the handler concept, is minimal changes in your patch and sets us on a path to
moving RelMetadataQuery to an interface or dumb abstract class.
##########
File path: core/src/main/java/org/apache/calcite/plan/RelOptCluster.java
##########
@@ -136,7 +134,7 @@ public RexBuilder getRexBuilder() {
return rexBuilder;
}
- public @Nullable RelMetadataProvider getMetadataProvider() {
+ public RelMetadataProvider getMetadataProvider() {
Review comment:
I see this marked resolved but don't see it being deprecated.
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQueryBase.java
##########
@@ -63,49 +61,56 @@
* </ol>
*/
public class RelMetadataQueryBase {
+
//~ Instance fields --------------------------------------------------------
/** Set of active metadata queries, and cache of previous results. */
- public final Table<RelNode, List, Object> map = HashBasedTable.create();
- public final @Nullable JaninoRelMetadataProvider metadataProvider;
+ @Deprecated // to be removed before 2.0
+ public final Table<RelNode, Object, Object> map;
+
+ public final MetadataCache cache;
+ protected final MetadataHandlerProvider metadataHandlerProvider;
Review comment:
Please make metadataHandlerProvider private. I think this means that for
now you need to move it to relmetadataquery and pass a cache supplier into the
RelMetadataQueryBase
Please make the cache private. I think using the Api pattern to "hide"
things should be used as a last resort. This may mean it should also move to
RelMetadataQuery (for now).
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
##########
@@ -886,10 +919,59 @@ public Boolean isVisibleInExplain(RelNode rel,
for (;;) {
try {
return lowerBoundCostHandler.getLowerBoundCost(rel, this, planner);
- } catch (JaninoRelMetadataProvider.NoHandler e) {
+ } catch (MetadataHandlerProvider.NoHandler e) {
lowerBoundCostHandler =
- revise(BuiltInMetadata.LowerBoundCost.Handler.class);
+
metadataHandlerProvider.revise(BuiltInMetadata.LowerBoundCost.Handler.class);
}
}
}
+
+ public static Builder<RelMetadataQuery> builder() {
Review comment:
If we want to go with a builder, I think we should make a couple
changes. (Not entirely sure a builder is yet necessary.)
-This should probably be a method called `supplierBuilder()` or similar
since it doesn't actually build the type of class it is contained within. I'd
expect a builder on RelMetdataQuery to build a `RelMetadataQuery`, not
`Supplier<RelMetadataQuery>`.
- I think that we may want to add other ways of building in the future. For
example I'm exploring the introduction of a lambda based metadata handling
systems. In that situation, we may want to construct one of those using the
same initial builder. As such I suggest a specialization strategy where calling
withProviders returns a subtype of builder that has configuration options
related to a provider based builder. Maybe in the future we have a separate one
that works based on lambdas and we call withLambdas() to use it (and a call to
that would specialize the builder to that type of metadataquery supplier.
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
##########
@@ -886,10 +919,59 @@ public Boolean isVisibleInExplain(RelNode rel,
for (;;) {
try {
return lowerBoundCostHandler.getLowerBoundCost(rel, this, planner);
- } catch (JaninoRelMetadataProvider.NoHandler e) {
+ } catch (MetadataHandlerProvider.NoHandler e) {
lowerBoundCostHandler =
- revise(BuiltInMetadata.LowerBoundCost.Handler.class);
+
metadataHandlerProvider.revise(BuiltInMetadata.LowerBoundCost.Handler.class);
}
}
}
+
+ public static Builder<RelMetadataQuery> builder() {
Review comment:
If we want to go with a builder, I think we should make a couple
changes. (Not entirely sure a builder is yet necessary.)
- This should probably be a method called `supplierBuilder()` or similar
since it doesn't actually build the type of class it is contained within. I'd
expect a builder on RelMetdataQuery to build a `RelMetadataQuery`, not
`Supplier<RelMetadataQuery>`.
- I think that we may want to add other ways of building in the future. For
example I'm exploring the introduction of a lambda based metadata handling
systems. In that situation, we may want to construct one of those using the
same initial builder. As such I suggest a specialization strategy where calling
withProviders returns a subtype of builder that has configuration options
related to a provider based builder. Maybe in the future we have a separate one
that works based on lambdas and we call withLambdas() to use it (and a call to
that would specialize the builder to that type of metadataquery supplier.
##########
File path:
core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
##########
@@ -886,10 +919,59 @@ public Boolean isVisibleInExplain(RelNode rel,
for (;;) {
try {
return lowerBoundCostHandler.getLowerBoundCost(rel, this, planner);
- } catch (JaninoRelMetadataProvider.NoHandler e) {
+ } catch (MetadataHandlerProvider.NoHandler e) {
lowerBoundCostHandler =
- revise(BuiltInMetadata.LowerBoundCost.Handler.class);
+
metadataHandlerProvider.revise(BuiltInMetadata.LowerBoundCost.Handler.class);
}
}
}
+
+ public static Builder<RelMetadataQuery> builder() {
Review comment:
If we want to go with a builder, I think we should make a couple
changes. (Not entirely sure a builder is yet necessary.)
- This should probably be a method called `supplierBuilder()` or similar
since it doesn't actually build the type of class it is contained within. I'd
expect `RelMetdataQuery.builder()` to build a `RelMetadataQuery`, not
`Supplier<RelMetadataQuery>`.
- I think that we may want to add other ways of building in the future. For
example I'm exploring the introduction of a lambda based metadata handling
systems. In that situation, we may want to construct one of those using the
same initial builder. As such I suggest a specialization strategy where calling
withProviders returns a subtype of builder that has configuration options
related to a provider based builder. Maybe in the future we have a separate one
that works based on lambdas and we call withLambdas() to use it (and a call to
that would specialize the builder to that type of metadataquery supplier.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]