By “extend” do you mean “sub-class”?
> On Jun 4, 2019, at 10:19 PM, Yuzhao Chen <yuzhao....@gmail.com> wrote: > > Thanks Julian for your detail reply, > > > 1. I checked the Janino gened-code and the > RelMetadataQuery/RelMetadataProvidor and almost can make sure MetadataQuery > only use the RelMetadataProvidor#handlers method for multiple dispatch, the > RelMetadataProvidor#apply is only used for MetadataFactory. > 2. I agree that we should provide new RelMetadataProvider for extension, but > the RelMetadataQuery has top level interfaces for metadata query, these top > level interfaces should be extendable and sync with our metadata handlers. > > > Best, > Danny Chan > 在 2019年6月5日 +0800 AM1:48,Julian Hyde <jh...@apache.org>,写道: >>> 1. Why we have 2 methods in RelMetadataProvider? >> >> The metadata system is complicated. We need to allow multiple handlers >> for any given call. So, making a metadata call involves multiple >> dispatch [1] based on the metadata method being called, the type of >> RelNode, and the handlers that are registered. Also it needs to cache >> results, and detect cycles. And the dispatch needs to be efficient, so >> we generate janino code to do the dispatch, and re-generate when new >> handlers or sub-classes of RelNode are added. >> >> I forget details, the two methods are basically required to allow us >> to generate code to do the dispatch. >> >>> 2. We should make the RelMetadataQuery in RelOptCluster pluggable. >> >> I disagree. RelMetadataQuery is not an extension point. Its sole >> purpose is to to keep state (the cache and cycle-checking). >> RelMetadataProvider is the extension point. (By analogy, if you are >> un-parsing an AST, you let each AST sub-class handle unparsing itself, >> but the unparsed text goes to a simple StringBuilder. RelMetadataQuery >> is in the role of the StringBuilder. In a complex system, it is nice >> to keep some of the components simple, or at least keep them to >> prescribed roles.) >> >> Julian >> >> [1] https://en.wikipedia.org/wiki/Multiple_dispatch >> >>> On Sun, Jun 2, 2019 at 11:19 PM Yuzhao Chen <yuzhao....@gmail.com> wrote: >>> >>> Currently we provide answer to metadata query through RelMetadataProvider >>> [1], there are some sub-classes of it: >>> >>> RelMetadataProvider >>> | >>> |- VolcanoRelMetadataProvider >>> |- ChainedRelMetadataProvider/DefaultRelMetadataProvider >>> |- HepRelMetadataProvider >>> |- CachingRelMetadataProvider >>> |- ReflectiveRelMetadataProvider >>> |- JaninoRelMetadataProvider >>> >>> The RelMetadataProvider has two methods: #apply and #handlers, the #apply >>> method seems a programming interface and there is a demo code how we can >>> use it: >>> >>> RelMetadataProvider provider; >>> LogicalFilter filter; >>> RexNode predicate; >>> Function<RelNode, Metadata> function = >>> provider.apply(LogicalFilter.class, Selectivity.class}; >>> Selectivity selectivity = function.apply(filter); >>> Double d = selectivity.selectivity(predicate); >>> >>> But let's see our RelOptCluster's member variables[2], there are >>> MetadataFactory and RelMetadataQuery which all can be used to query the >>> metadata, for MetadataFactory, there is a default impl named >>> MetadataFactoryImpl which will invoke RelMetadataProvider#apply internally, >>> for RelMetadataQuery, it will invoke RelMetadataProvider#handlers (finally >>> composed and codeden by JaninoRelMetadataProvider). >>> >>> In our planning phrase, we can invoke RelOptRuleCall#getMetadataQuery to >>> get the MQ and query the metadata. >>> >>> For extension of metadata handlers, we can set our customized >>> RelMetadataProvider in RelOptCluster[3]. But for RelMetadataQuery, we have >>> no way to extend it now, because the RelOptCluster always has a singleton >>> instance [4] which is only the default implementation. >>> >>> >>> My question is as follows: >>> >>> 1. Why we have 2 methods in RelMetadataProvider, and why we need the >>> MetadataFactory and RelMetadataProvider#apply ? It seems that it's function >>> is already been overriden by RelMetadataQuery(The difference is that >>> MetadataFactory use Reflection and RelMetadataQuery use gened bytes code). >>> 2. We should make the RelMetadataQuery in RelOptCluster pluggable. >>> >>> >>> [1] >>> https://github.com/apache/calcite/blob/b0e83c469ff57257c1ea621ff943ca76f626a9b7/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataProvider.java#L38 >>> [2] >>> https://github.com/apache/calcite/blob/b0e83c469ff57257c1ea621ff943ca76f626a9b7/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java#L49 >>> [3] >>> https://github.com/apache/calcite/blob/b0e83c469ff57257c1ea621ff943ca76f626a9b7/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java#L135 >>> [4] >>> https://github.com/apache/calcite/blob/b0e83c469ff57257c1ea621ff943ca76f626a9b7/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java#L151 >>> >>> >>> >>> Best, >>> Danny Chan