jamesstarr commented on a change in pull request #2378:
URL: https://github.com/apache/calcite/pull/2378#discussion_r742284367



##########
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:
       There are several requirements metadata in calcite:
   Metadata retrieval - the api for getting a metdata value for a relnode and 
give set of arguments.  This is currently the RelMetadataQuery.
   Metadata implementation - The code that is called to for a relnode to get a 
metadata value.  This is currently sub-classes of RelMetdataProvider.
   Defaulting and Validation - There is defaulting, canonization, validation, 
etc after a metadata value is retrieved in RelMetadataQuery.
   Dispatch - How the implementation is called for given arguments.  This is 
currently done in Janino compiled code.
   Cycle Detection - This is currently a **hard** requirement of volcano 
planner.  This is currently done in Janino compiled code.
   Caching Invalidation - This is required for volcano planner.  This is 
currently done through RelMetadataQuery.clearCache.
   Caching Implementation - This is coupled with cycle detection, but is 
currently accomplished through RelMetadataQuery.map.
   Caching Values - The caches need to be checked and updated.  This is 
currently done in the generated code.
   
   Metadata retrieval and Metadata implementation are hard requirements for 
external facing APIs.  They are currently exist as external facing APIs.  Many 
downstream projects depend on the ability to either customize existing metadata 
types or add their own metadata types.  When a down stream project adds their 
own metadata type, they need to be able to expose it to the larger system aka 
through metadata retrieval.  This is currently done by subclassing 
RelMetadataQuery and calling methods RelMetadataQueryBase.  An example of this 
can be seen in RelMetadataTest.MyRelMetadataQuery.
   
   So the metadata retrieval api is the only api need to for the rest of 
calcite core, however, downstream users of calcite need to be able to configure 
and extend the metadata implementation.  So some of RelMetadataQuery 
implementation must be exposed with the current setup.
   
   I support making RelMetadataQuery an interface so the metadata retrieval is 
clearly defined.  However, this is not the only public API necessary to expose. 
 Also, it is breaking change which does not separate the defaulting and 
validation from the RelMetadataQueryImpl.  If RelMetadataQuery was split into 
RelMetadataQuery(an interface), DefaultingAndValidatingRelMetadataQuery and 
HandlerBackedRelMetadataQuery, then down stream projects would have to 
implement 2 different RelMetadataQueries to add a custom metadata.  This api 
seems a bit convoluted and cumbersome.  Alternatively, breaking it up into 
class hierarchy of RelMetadataQuery -> DefaultingAndValidatingRelMetadataQuery 
->  HandlerBackedRelMetadataQuery also feels a bit convoluted and is a breaking 
change.
   
   I also support removing the leaky abstraction of the metadata implementation 
to the rest of calcite core.  But changing this does not actually help things 
much other than remove a thread local that can cause odd behaviors in uncommon 
nesting scenarios. 




-- 
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]


Reply via email to