Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed 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 io.trino.cost;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.inject.Inject;
import io.trino.Session;
import io.trino.matching.Pattern;
import io.trino.matching.pattern.TypeOfPattern;
import io.trino.sql.planner.TypeProvider;
import io.trino.sql.planner.iterative.Lookup;
import io.trino.sql.planner.plan.PlanNode;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Multimaps.toMultimap;
public class ComposableStatsCalculator
implements StatsCalculator
{
private final ListMultimap, Rule>> rulesByRootType;
@Inject
public ComposableStatsCalculator(List> rules)
{
this.rulesByRootType = rules.stream()
.peek(rule -> {
checkArgument(rule.getPattern() instanceof TypeOfPattern, "Rule pattern must be TypeOfPattern");
Class> expectedClass = ((TypeOfPattern>) rule.getPattern()).expectedClass();
checkArgument(!expectedClass.isInterface() && !Modifier.isAbstract(expectedClass.getModifiers()), "Rule must be registered on a concrete class");
})
.collect(toMultimap(
rule -> ((TypeOfPattern>) rule.getPattern()).expectedClass(),
rule -> rule,
ArrayListMultimap::create));
}
private Stream> getCandidates(PlanNode node)
{
for (Class> superclass = node.getClass().getSuperclass(); superclass != null; superclass = superclass.getSuperclass()) {
// This is important because rule ordering, given in the constructor, is significant.
// We can't check this fully in the constructor, since abstract class may lack `abstract` modifier.
checkState(rulesByRootType.get(superclass).isEmpty(), "Cannot maintain rule order because there is rule registered for %s", superclass);
}
return rulesByRootType.get(node.getClass()).stream();
}
@Override
public PlanNodeStatsEstimate calculateStats(PlanNode node, StatsProvider sourceStats, Lookup lookup, Session session, TypeProvider types, TableStatsProvider tableStatsProvider)
{
Iterator> ruleIterator = getCandidates(node).iterator();
while (ruleIterator.hasNext()) {
Rule> rule = ruleIterator.next();
Optional calculatedStats = calculateStats(rule, node, sourceStats, lookup, session, types, tableStatsProvider);
if (calculatedStats.isPresent()) {
return calculatedStats.get();
}
}
return PlanNodeStatsEstimate.unknown();
}
private static Optional calculateStats(Rule rule, PlanNode node, StatsProvider sourceStats, Lookup lookup, Session session, TypeProvider types, TableStatsProvider tableStatsProvider)
{
@SuppressWarnings("unchecked")
T typedNode = (T) node;
return rule.calculate(typedNode, sourceStats, lookup, session, types, tableStatsProvider);
}
public interface Rule
{
Pattern getPattern();
Optional calculate(T node, StatsProvider sourceStats, Lookup lookup, Session session, TypeProvider types, TableStatsProvider tableStatsProvider);
}
}