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.sql.validate;
  
  import org.apache.calcite.rel.type.RelDataType;
  import org.apache.calcite.rel.type.RelDataTypeField;
  import org.apache.calcite.sql.SqlNode;
  import org.apache.calcite.util.Pair;
  
  import org.checkerframework.checker.nullness.qual.Nullable;
  import org.checkerframework.dataflow.qual.Pure;
  
  import java.util.List;
  
  /**
   * A namespace describes the relation returned by a section of a SQL query.
   *
   * <p>For example, in the query <code>SELECT emp.deptno, age FROM emp,
   * dept</code>, the FROM clause forms a namespace consisting of two tables EMP
   * and DEPT, and a row type consisting of the combined columns of those tables.
   *
   * <p>Other examples of namespaces include a table in the from list (the
   * namespace contains the constituent columns) and a sub-query (the namespace
   * contains the columns in the SELECT clause of the sub-query).
   *
   * <p>These various kinds of namespace are implemented by classes
   * {@link IdentifierNamespace} for table names, {@link SelectNamespace} for
   * SELECT queries, {@link SetopNamespace} for UNION, EXCEPT and INTERSECT, and
   * so forth. But if you are looking at a SELECT query and call
   * {@link SqlValidator#getNamespace(org.apache.calcite.sql.SqlNode)}, you may
   * not get a SelectNamespace. Why? Because the validator is allowed to wrap
   * namespaces in other objects which implement
   * {@link SqlValidatorNamespace}. Your SelectNamespace will be there somewhere,
   * but might be one or two levels deep.  Don't try to cast the namespace or use
   * <code>instanceof</code>; use {@link SqlValidatorNamespace#unwrap(Class)} and
   * {@link SqlValidatorNamespace#isWrapperFor(Class)} instead.
   *
   * @see SqlValidator
   * @see SqlValidatorScope
   */
  public interface SqlValidatorNamespace {
    //~ Methods ----------------------------------------------------------------
  
    /**
     * Returns the validator.
     *
     * @return validator
     */
    SqlValidator getValidator();
  
    /**
     * Returns the underlying table, or null if there is none.
     */
    @Nullable SqlValidatorTable getTable();
  
    /**
     * Returns the row type of this namespace, which comprises a list of names
     * and types of the output columns. If the scope's type has not yet been
     * derived, derives it.
     *
     * @return Row type of this namespace, never null, always a struct
     */
    RelDataType getRowType();
  
    /**
     * Returns the type of this namespace.
     *
     * @return Row type converted to struct
     */
    RelDataType getType();
  
    /**
     * Sets the type of this namespace.
     *
     * <p>Allows the type for the namespace to be explicitly set, but usually is
     * called during {@link #validate(RelDataType)}.
     *
     * <p>Implicitly also sets the row type. If the type is not a struct, then
     * the row type is the type wrapped as a struct with a single column,
     * otherwise the type and row type are the same.
     */
    void setType(RelDataType type);
  
    /**
     * Returns the row type of this namespace, sans any system columns.
     *
     * @return Row type sans system columns
     */
    RelDataType getRowTypeSansSystemColumns();
  
    /**
     * Validates this namespace.
     *
     * <p>If the scope has already been validated, does nothing.
     *
     * <p>Please call {@link SqlValidatorImpl#validateNamespace} rather than
     * calling this method directly.
     *
     * @param targetRowType Desired row type, must not be null, may be the data
     *                      type 'unknown'.
     */
    void validate(RelDataType targetRowType);
  
    /**
     * Returns the parse tree node at the root of this namespace.
     *
     * @return parse tree node; null for {@link TableNamespace}
     */
    @Nullable SqlNode getNode();
  
    /**
     * Returns the parse tree node that at is at the root of this namespace and
     * includes all decorations. If there are no decorations, returns the same
     * as {@link #getNode()}.
     */
    @Pure
    @Nullable SqlNode getEnclosingNode();
  
    /**
     * Looks up a child namespace of a given name.
     *
     * <p>For example, in the query <code>select e.name from emps as e</code>,
     * <code>e</code> is an {@link IdentifierNamespace} which has a child <code>
     * name</code> which is a {@link FieldNamespace}.
     *
     * @param name Name of namespace
     * @return Namespace
     */
    @Nullable SqlValidatorNamespace lookupChild(String name);
  
    /**
     * Returns whether this namespace has a field of a given name.
     *
     * @param name Field name
     * @return Whether field exists
     */
    default boolean fieldExists(String name) {
      return field(name) != null;
    }
  
    /**
     * Returns a field of a given name, or null.
     *
     * @param name Field name
     * @return Field, or null
     */
    @Nullable RelDataTypeField field(String name);
  
    /**
     * Returns a list of expressions which are monotonic in this namespace. For
     * example, if the namespace represents a relation ordered by a column
     * called "TIMESTAMP", then the list would contain a
     * {@link org.apache.calcite.sql.SqlIdentifier} called "TIMESTAMP".
     */
    List<Pair<SqlNode, SqlMonotonicity>> getMonotonicExprs();
  
    /**
     * Returns whether and how a given column is sorted.
     */
    SqlMonotonicity getMonotonicity(String columnName);
  
    @Deprecated // to be removed before 2.0
    void makeNullable();
  
    /**
     * Returns this namespace, or a wrapped namespace, cast to a particular
     * class.
     *
     * @param clazz Desired type
     * @return This namespace cast to desired type
     * @throws ClassCastException if no such interface is available
     */
    <T> T unwrap(Class<T> clazz);
  
    /**
     * Returns whether this namespace implements a given interface, or wraps a
     * class which does.
     *
     * @param clazz Interface
     * @return Whether namespace implements given interface
     */
    boolean isWrapperFor(Class<?> clazz);
  
    /** If this namespace resolves to another namespace, returns that namespace,
     * following links to the end of the chain.
     *
     * <p>A {@code WITH}) clause defines table names that resolve to queries
     * (the body of the with-item). An {@link IdentifierNamespace} typically
     * resolves to a {@link TableNamespace}.
     *
     * <p>You must not call this method before {@link #validate(RelDataType)} has
     * completed. */
    SqlValidatorNamespace resolve();
  
    /** Returns whether this namespace is capable of giving results of the desired
     * modality. {@code true} means streaming, {@code false} means relational.
     *
     * @param modality Modality
     */
    boolean supportsModality(SqlModality modality);
  
    /** Returns a {@code FilterRequirement} object describing the "must-filter"
     * fields of this namespace (fields that must be filtered in a query) and
     * "bypass" fields that can remove the requirement that fields are
     * filtered. */
    default FilterRequirement getFilterRequirement() {
      return FilterRequirement.EMPTY;
    }
  }
  