
com.hazelcast.org.apache.calcite.rel.metadata.JaninoRelMetadataProvider Maven / Gradle / Ivy
/*
* 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 com.hazelcast.org.apache.calcite.rel.metadata;
import com.hazelcast.org.apache.calcite.config.CalciteSystemProperty;
import com.hazelcast.org.apache.calcite.interpreter.JaninoRexCompiler;
import com.hazelcast.org.apache.calcite.linq4j.Ord;
import com.hazelcast.org.apache.calcite.linq4j.tree.Primitive;
import com.hazelcast.org.apache.calcite.rel.RelNode;
import com.hazelcast.org.apache.calcite.rel.metadata.janino.DescriptiveCacheKey;
import com.hazelcast.org.apache.calcite.rel.metadata.janino.DispatchGenerator;
import com.hazelcast.org.apache.calcite.util.ControlFlowException;
import com.hazelcast.org.apache.calcite.util.Util;
import com.hazelcast.com.google.common.cache.CacheBuilder;
import com.hazelcast.com.google.common.cache.CacheLoader;
import com.hazelcast.com.google.common.cache.LoadingCache;
import com.hazelcast.com.google.common.collect.ImmutableList;
import com.hazelcast.com.google.common.collect.Multimap;
import com.hazelcast.com.google.common.util.concurrent.UncheckedExecutionException;
import com.hazelcast.org.checkerframework.checker.nullness.qual.Nullable;
import com.hazelcast.org.codehaus.commons.compiler.CompileException;
import com.hazelcast.org.codehaus.commons.compiler.CompilerFactoryFactory;
import com.hazelcast.org.codehaus.commons.compiler.ICompilerFactory;
import com.hazelcast.org.codehaus.commons.compiler.ISimpleCompiler;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
/**
* Implementation of the {@link RelMetadataProvider} interface that generates
* a class that dispatches to the underlying providers.
*/
public class JaninoRelMetadataProvider implements RelMetadataProvider {
private final RelMetadataProvider provider;
// Constants and static fields
public static final JaninoRelMetadataProvider DEFAULT =
JaninoRelMetadataProvider.of(DefaultRelMetadataProvider.INSTANCE);
/** Cache of pre-generated handlers by provider and kind of metadata.
* For the cache to be effective, providers should implement identity
* correctly. */
private static final LoadingCache> HANDLERS =
maxSize(CacheBuilder.newBuilder(),
CalciteSystemProperty.METADATA_HANDLER_CACHE_MAXIMUM_SIZE.value())
.build(
CacheLoader.from(key ->
generateCompileAndInstantiate(key.handlerClass,
key.provider.handlers(key.handlerClass))));
/** Private constructor; use {@link #of}. */
private JaninoRelMetadataProvider(RelMetadataProvider provider) {
this.provider = provider;
}
/** Creates a JaninoRelMetadataProvider.
*
* @param provider Underlying provider
*/
public static JaninoRelMetadataProvider of(RelMetadataProvider provider) {
if (provider instanceof JaninoRelMetadataProvider) {
return (JaninoRelMetadataProvider) provider;
}
return new JaninoRelMetadataProvider(provider);
}
// helper for initialization
private static CacheBuilder maxSize(CacheBuilder builder,
int size) {
if (size >= 0) {
builder.maximumSize(size);
}
return builder;
}
@Override public boolean equals(@Nullable Object obj) {
return obj == this
|| obj instanceof JaninoRelMetadataProvider
&& ((JaninoRelMetadataProvider) obj).provider.equals(provider);
}
@Override public int hashCode() {
return 109 + provider.hashCode();
}
@Deprecated // to be removed before 2.0
@Override public <@Nullable M extends @Nullable Metadata> UnboundMetadata apply(
Class extends RelNode> relClass, Class extends M> metadataClass) {
throw new UnsupportedOperationException();
}
@Deprecated // to be removed before 2.0
@Override public Multimap>
handlers(MetadataDef def) {
return provider.handlers(def);
}
@Override public List> handlers(
Class extends MetadataHandler>> handlerClass) {
return provider.handlers(handlerClass);
}
private static > MH generateCompileAndInstantiate(
Class handlerClass,
List extends MetadataHandler extends Metadata>> handlers) {
final LinkedHashSet extends MetadataHandler extends Metadata>> handlerSet =
new LinkedHashSet<>(handlers);
final StringBuilder buff = new StringBuilder();
final String name =
"GeneratedMetadata_" + simpleNameForHandler(handlerClass);
final Map, String> handlerToName = new LinkedHashMap<>();
for (MetadataHandler> provider : handlerSet) {
if (!handlerToName.containsKey(provider)) {
handlerToName.put(provider, "provider" + handlerToName.size());
}
}
//Properties
for (Map.Entry, String> handlerAndName : handlerToName.entrySet()) {
buff.append(" public final ").append(handlerAndName.getKey().getClass().getName())
.append(' ').append(handlerAndName.getValue()).append(";\n");
}
//Constructor
buff.append(" public ").append(name).append("(\n");
for (Map.Entry, String> handlerAndName : handlerToName.entrySet()) {
buff.append(" ")
.append(handlerAndName.getKey().getClass().getName())
.append(' ')
.append(handlerAndName.getValue())
.append(",\n");
}
if (!handlerToName.isEmpty()) {
//Remove trailing comma and new line
buff.setLength(buff.length() - 2);
}
buff.append(") {\n");
for (String handlerName : handlerToName.values()) {
buff.append(" this.").append(handlerName).append(" = ").append(handlerName)
.append(";\n");
}
buff.append(" }\n");
getDefMethod(buff, handlerToName.values()
.stream()
.findFirst()
.orElse(null));
DispatchGenerator dispatchGenerator = new DispatchGenerator(handlerToName);
for (Ord method : Ord.zip(handlerClass.getDeclaredMethods())) {
cacheProperties(buff, method.e, method.i);
generateCachedMethod(buff, method.e, method.i);
dispatchGenerator.dispatchMethod(buff, method.e, handlerSet);
}
final List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy