/* * 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.eigenbase.relopt; import java.util.*; import java.util.logging.*; import org.eigenbase.rel.*; import org.eigenbase.trace.*; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; /** * A <code>RelOptRuleCall</code> is an invocation of a {@link RelOptRule} with a * set of {@link RelNode relational expression}s as arguments. */ public abstract class RelOptRuleCall { //~ Static fields/initializers --------------------------------------------- protected static final Logger LOGGER = EigenbaseTrace.getPlannerTracer(); /** * Generator for {@link #id} values. */ private static int nextId = 0; //~ Instance fields -------------------------------------------------------- public final int id; private final RelOptRuleOperand operand0; private final Map<RelNode, List<RelNode>> nodeChildren; public final RelOptRule rule; public final RelNode[] rels; private final RelOptPlanner planner; private final List<RelNode> parents; //~ Constructors ----------------------------------------------------------- /** * Creates a RelOptRuleCall. * * @param planner Planner * @param operand Root operand * @param rels Array of relational expressions which matched each * operand * @param nodeChildren For each node which matched with <code> * matchAnyChildren</code>=true, a list of the node's * children * @param parents list of parent RelNodes corresponding to the first * relational expression in the array argument, if known; * otherwise, null */ protected RelOptRuleCall( RelOptPlanner planner, RelOptRuleOperand operand, RelNode[] rels, Map<RelNode, List<RelNode>> nodeChildren, List<RelNode> parents) { this.id = nextId++; this.planner = planner; this.operand0 = operand; this.nodeChildren = nodeChildren; this.rule = operand.getRule(); this.rels = rels; this.parents = parents; assert rels.length == rule.operands.size(); } protected RelOptRuleCall( RelOptPlanner planner, RelOptRuleOperand operand, RelNode[] rels, Map<RelNode, List<RelNode>> nodeChildren) { this(planner, operand, rels, nodeChildren, null); } //~ Methods ---------------------------------------------------------------- /** * Returns the root operand matched by this rule. * * @return root operand */ public RelOptRuleOperand getOperand0() { return operand0; } /** * Returns the invoked planner rule. * * @return planner rule */ public RelOptRule getRule() { return rule; } /** * Returns a list of matched relational expressions. * * @return matched relational expressions * @deprecated Use {@link #getRelList()} or {@link #rel(int)} */ public RelNode[] getRels() { return rels; } /** * Returns a list of matched relational expressions. * * @return matched relational expressions * @see #rel(int) */ public List<RelNode> getRelList() { return ImmutableList.copyOf(rels); } /** * Retrieves the {@code ordinal}th matched relational expression. This * corresponds to the {@code ordinal}th operand of the rule. * * @param ordinal Ordinal * @param <T> Type * @return Relational expression */ public <T extends RelNode> T rel(int ordinal) { //noinspection unchecked return (T) rels[ordinal]; } /** * Returns the children of a given relational expression node matched in a * rule. * * <p>If the policy of the operand which caused the match is not * {@link org.eigenbase.relopt.RelOptRuleOperandChildPolicy#ANY}, * the children will have their * own operands and therefore be easily available in the array returned by * the {@link #getRels} method, so this method returns null. * * <p>This method is for * {@link org.eigenbase.relopt.RelOptRuleOperandChildPolicy#ANY}, * which is generally used when a node can have a variable number of * children, and hence where the matched children are not retrievable by any * other means. * * @param rel Relational expression * @return Children of relational expression */ public List<RelNode> getChildRels(RelNode rel) { return nodeChildren.get(rel); } /** * Returns the planner. * * @return planner */ public RelOptPlanner getPlanner() { return planner; } /** * @return list of parents of the first relational expression */ public List<RelNode> getParents() { return parents; } /** * Registers that a rule has produced an equivalent relational expression. * * <p>Called by the rule whenever it finds a match. The implementation of * this method guarantees that the original relational expression (that is, * <code>this.rels[0]</code>) has its traits propagated to the new * relational expression (<code>rel</code>) and its unregistered children. * Any trait not specifically set in the RelTraitSet returned by <code> * rel.getTraits()</code> will be copied from <code> * this.rels[0].getTraitSet()</code>. * * @param rel Relational expression equivalent to the root relational * expression of the rule call, {@code call.rels(0)} * @param equiv Map of other equivalences */ public abstract void transformTo(RelNode rel, Map<RelNode, RelNode> equiv); /** * Registers that a rule has produced an equivalent relational expression, * but no other equivalences. * * @param rel Relational expression equivalent to the root relational * expression of the rule call, {@code call.rels(0)} */ public final void transformTo(RelNode rel) { transformTo(rel, ImmutableMap.<RelNode, RelNode>of()); } } // End RelOptRuleCall.java