content: /*
   * 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.apache.calcite.rel;
  
  import org.apache.calcite.plan.Convention;
  import org.apache.calcite.plan.RelDigest;
  import org.apache.calcite.plan.RelOptCost;
  import org.apache.calcite.plan.RelOptNode;
  import org.apache.calcite.plan.RelOptPlanner;
  import org.apache.calcite.plan.RelOptTable;
  import org.apache.calcite.plan.RelOptUtil;
  import org.apache.calcite.plan.RelTraitSet;
  import org.apache.calcite.rel.core.CorrelationId;
  import org.apache.calcite.rel.metadata.Metadata;
  import org.apache.calcite.rel.metadata.RelMetadataQuery;
  import org.apache.calcite.rel.type.RelDataType;
  import org.apache.calcite.rex.RexNode;
  import org.apache.calcite.rex.RexShuttle;
  import org.apache.calcite.util.Litmus;
  
  import org.apiguardian.api.API;
  import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
  import org.checkerframework.checker.nullness.qual.Nullable;
  import org.checkerframework.dataflow.qual.Pure;
  
  import java.util.List;
  import java.util.Set;
  
  /**
   * A <code>RelNode</code> is a relational expression.
   *
   * <p>Relational expressions process data, so their names are typically verbs:
   * Sort, Join, Project, Filter, Scan, Sample.
   *
   * <p>A relational expression is not a scalar expression; see
   * {@link org.apache.calcite.sql.SqlNode} and {@link RexNode}.
   *
   * <p>If this type of relational expression has some particular planner rules,
   * it should implement the <em>public static</em> method
   * {@link AbstractRelNode#register}.
   *
   * <p>When a relational expression comes to be implemented, the system allocates
   * a {@link org.apache.calcite.plan.RelImplementor} to manage the process. Every
   * implementable relational expression has a {@link RelTraitSet} describing its
   * physical attributes. The RelTraitSet always contains a {@link Convention}
   * describing how the expression passes data to its consuming
   * relational expression, but may contain other traits, including some applied
   * externally. Because traits can be applied externally, implementations of
   * RelNode should never assume the size or contents of their trait set (beyond
   * those traits configured by the RelNode itself).
   *
   * <p>For each calling-convention, there is a corresponding sub-interface of
   * RelNode. For example,
   * {@code org.apache.calcite.adapter.enumerable.EnumerableRel}
   * has operations to manage the conversion to a graph of
   * {@code org.apache.calcite.adapter.enumerable.EnumerableConvention}
   * calling-convention, and it interacts with a
   * {@code EnumerableRelImplementor}.
   *
   * <p>A relational expression is only required to implement its
   * calling-convention's interface when it is actually implemented, that is,
   * converted into a plan/program. This means that relational expressions which
   * cannot be implemented, such as converters, are not required to implement
   * their convention's interface.
   *
   * <p>Every relational expression must derive from {@link AbstractRelNode}. (Why
   * have the <code>RelNode</code> interface, then? We need a root interface,
   * because an interface can only derive from an interface.)
   */
  public interface RelNode extends RelOptNode, Cloneable {
    //~ Methods ----------------------------------------------------------------
  
    /**
     * Return the CallingConvention trait from this RelNode's
     * {@link #getTraitSet() trait set}.
     *
     * @return this RelNode's CallingConvention
     */
    @Pure
    @Nullable Convention getConvention();
  
    /**
     * Returns the name of the variable which is to be implicitly set at runtime
     * each time a row is returned from the first input of this relational
     * expression; or null if there is no variable.
     *
     * @return Name of correlating variable, or null
     */
    @Nullable String getCorrelVariable();
  
    /**
     * Returns the <code>i</code><sup>th</sup> input relational expression.
     *
     * @param i Ordinal of input
     * @return <code>i</code><sup>th</sup> input
     */
    RelNode getInput(int i);
  
    /**
     * Returns the type of the rows returned by this relational expression.
     */
    @Override RelDataType getRowType();
  
    /**
     * Returns the type of the rows expected for an input. Defaults to
     * {@link #getRowType}.
     *
     * @param ordinalInParent input's 0-based ordinal with respect to this
     *                        parent rel
     * @return expected row type
     */
    RelDataType getExpectedInputRowType(int ordinalInParent);
  
    /**
     * Returns an array of this relational expression's inputs. If there are no
     * inputs, returns an empty list, not {@code null}.
     *
     * @return Array of this relational expression's inputs
     */
    @Override List<RelNode> getInputs();
  
    /**
     * Returns an estimate of the number of rows this relational expression will
     * return.
     *
     * <p>NOTE jvs 29-Mar-2006: Don't call this method directly. Instead, use
     * {@link RelMetadataQuery#getRowCount}, which gives plugins a chance to
     * override the rel's default ideas about row count.
     *
     * @param mq Metadata query
     * @return Estimate of the number of rows this relational expression will
     *   return
     */
    double estimateRowCount(RelMetadataQuery mq);
  
    /**
     * Returns the variables that are set in this relational
     * expression but also used and therefore not available to parents of this
     * relational expression.
     *
     * @return Names of variables which are set in this relational
     *   expression
     */
    Set<CorrelationId> getVariablesSet();
  
    /**
     * Collects variables known to be used by this expression or its
     * descendants. By default, no such information is available and must be
     * derived by analyzing sub-expressions, but some optimizer implementations
     * may insert special expressions which remember such information.
     *
     * @param variableSet receives variables used
     */
    void collectVariablesUsed(Set<CorrelationId> variableSet);
  
    /**
     * Collects variables set by this expression.
     * TODO: is this required?
     *
     * @param variableSet receives variables known to be set by
     */
    void collectVariablesSet(Set<CorrelationId> variableSet);
  
    /**
     * Interacts with the {@link RelVisitor} in a
     * {@link org.apache.calcite.util.Glossary#VISITOR_PATTERN visitor pattern} to
     * traverse the tree of relational expressions.
     *
     * @param visitor Visitor that will traverse the tree of relational
     *                expressions
     */
    void childrenAccept(RelVisitor visitor);
  
    /**
     * Returns the cost of this plan (not including children). The base
     * implementation throws an error; derived classes should override.
     *
     * <p>NOTE jvs 29-Mar-2006: Don't call this method directly. Instead, use
     * {@link RelMetadataQuery#getNonCumulativeCost}, which gives plugins a
     * chance to override the rel's default ideas about cost.
     *
     * @param planner Planner for cost calculation
     * @param mq Metadata query
     * @return Cost of this plan (not including children)
     */
    @Nullable RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq);
  
    /**
     * Returns a metadata interface.
     *
     * @deprecated Use {@link RelMetadataQuery} via {@link #getCluster()}.
     *
     * @param <M> Type of metadata being requested
     * @param metadataClass Metadata interface
     * @param mq Metadata query
     *
     * @return Metadata object that supplies the desired metadata (never null,
     *     although if the information is not present the metadata object may
     *     return null from all methods)
     */
    @Deprecated // to be removed before 2.0
    <@Nullable M extends @Nullable Metadata> M metadata(Class<M> metadataClass, RelMetadataQuery mq);
  
    /**
     * Describes the inputs and attributes of this relational expression.
     * Each node should call {@code super.explain}, then call the
     * {@link org.apache.calcite.rel.externalize.RelWriterImpl#input(String, RelNode)}
     * and
     * {@link RelWriter#item(String, Object)}
     * methods for each input and attribute.
     *
     * @param pw Plan writer
     */
    void explain(RelWriter pw);
  
    /**
     * Returns a relational expression string of this {@code RelNode}.
     * The string returned is the same as
     * {@link RelOptUtil#toString(org.apache.calcite.rel.RelNode)}.
     *
     * <p>This method is intended mainly for use while debugging in an IDE,
     * as a convenient shorthand for {@link RelOptUtil#toString}.
     * We recommend that classes implementing this interface
     * do not override this method.
     *
     * @return Relational expression string of this {@code RelNode}
     */
    default String explain() {
      return RelOptUtil.toString(this);
    }
  
    /**
     * Receives notification that this expression is about to be registered. The
     * implementation of this method must at least register all child
     * expressions.
     *
     * @param planner Planner that plans this relational node
     * @return Relational expression that should be used by the planner
     */
    RelNode onRegister(RelOptPlanner planner);
  
    /**
     * Returns a digest string of this {@code RelNode}.
     *
     * <p>Each call creates a new digest string,
     * so don't forget to cache the result if necessary.
     *
     * @return Digest string of this {@code RelNode}
     *
     * @see #getRelDigest()
     */
    @Override default String getDigest() {
      return getRelDigest().toString();
    }
  
    /**
     * Returns a digest of this {@code RelNode}.
     *
     * <p>INTERNAL USE ONLY. For use by the planner.
     *
     * @return Digest of this {@code RelNode}
     * @see #getDigest()
     */
    @API(since = "1.24", status = API.Status.INTERNAL)
    RelDigest getRelDigest();
  
    /**
     * Recomputes the digest.
     *
     * <p>INTERNAL USE ONLY. For use by the planner.
     *
     * @see #getDigest()
     */
    @API(since = "1.24", status = API.Status.INTERNAL)
    void recomputeDigest();
  
    /**
     * Deep equality check for RelNode digest.
     *
     * <p>By default this method collects digest attributes from
     * explain terms, then compares each attribute pair.
     *
     * @return Whether the 2 RelNodes are equivalent or have the same digest.
     * @see #deepHashCode()
     */
    @EnsuresNonNullIf(expression = "#1", result = true)
    boolean deepEquals(@Nullable Object obj);
  
    /**
     * Compute deep hash code for RelNode digest.
     *
     * @see #deepEquals(Object)
     */
    int deepHashCode();
  
    /**
     * Replaces the <code>ordinalInParent</code><sup>th</sup> input. You must
     * override this method if you override {@link #getInputs}.
     *
     * @param ordinalInParent Position of the child input, 0 is the first
     * @param p New node that should be put at position {@code ordinalInParent}
     */
    void replaceInput(
        int ordinalInParent,
        RelNode p);
  
    /**
     * If this relational expression represents an access to a table, returns
     * that table, otherwise returns null.
     *
     * @return If this relational expression represents an access to a table,
     *   returns that table, otherwise returns null
     */
    @Nullable RelOptTable getTable();
  
    /**
     * Returns the name of this relational expression's class, sans package
     * name, for use in explain. For example, for a <code>
     * org.apache.calcite.rel.ArrayRel.ArrayReader</code>, this method returns
     * "ArrayReader".
     *
     * @return Name of this relational expression's class, sans package name,
     *   for use in explain
     */
    String getRelTypeName();
  
    /**
     * Returns whether this relational expression is valid.
     *
     * <p>If assertions are enabled, this method is typically called with <code>
     * litmus</code> = <code>THROW</code>, as follows:
     *
     * <blockquote>
     * <pre>assert rel.isValid(Litmus.THROW)</pre>
     * </blockquote>
     *
     * <p>This signals that the method can throw an {@link AssertionError} if it
     * is not valid.
     *
     * @param litmus What to do if invalid
     * @param context Context for validity checking
     * @return Whether relational expression is valid
     * @throws AssertionError if this relational expression is invalid and
     *                        litmus is THROW
     */
    boolean isValid(Litmus litmus, @Nullable Context context);
  
    /**
     * Creates a copy of this relational expression, perhaps changing traits and
     * inputs.
     *
     * <p>Sub-classes with other important attributes are encouraged to create
     * variants of this method with more parameters.
     *
     * @param traitSet Trait set
     * @param inputs   Inputs
     * @return Copy of this relational expression, substituting traits and
     * inputs
     */
    RelNode copy(
        RelTraitSet traitSet,
        List<RelNode> inputs);
  
    /**
     * Registers any special rules specific to this kind of relational
     * expression.
     *
     * <p>The planner calls this method this first time that it sees a
     * relational expression of this class. The derived class should call
     * {@link org.apache.calcite.plan.RelOptPlanner#addRule} for each rule, and
     * then call {@code super.register}.
     *
     * @param planner Planner to be used to register additional relational
     *                expressions
     */
    void register(RelOptPlanner planner);
  
    /**
     * Indicates whether it is an enforcer operator, e.g. PhysicalSort,
     * PhysicalHashDistribute, etc. As an enforcer, the operator must be
     * created only when required traitSet is not satisfied by its input.
     *
     * @return Whether it is an enforcer operator
     */
    default boolean isEnforcer() {
      return false;
    }
  
    /**
     * Accepts a visit from a shuttle.
     *
     * @param shuttle Shuttle
     * @return A copy of this node incorporating changes made by the shuttle to
     * this node's children
     */
    RelNode accept(RelShuttle shuttle);
  
    /**
     * Accepts a visit from a shuttle. If the shuttle updates expression, then
     * a copy of the relation should be created. This new relation might have
     * a different row-type.
     *
     * @param shuttle Shuttle
     * @return A copy of this node incorporating changes made by the shuttle to
     * this node's children
     */
    RelNode accept(RexShuttle shuttle);
  
    /** Returns whether a field is nullable. */
    default boolean fieldIsNullable(int i) {
      return getRowType().getFieldList().get(i).getType().isNullable();
    }
  
    /** Returns this node without any wrapper added by the planner. */
    default RelNode stripped() {
      return this;
    }
  
    /** Context of a relational expression, for purposes of checking validity. */
    interface Context {
      Set<CorrelationId> correlationIds();
    }
  }
  