// 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.impala.analysis;

import static org.apache.impala.analysis.ToSqlOptions.DEFAULT;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import org.apache.impala.authorization.Privilege;
import org.apache.impala.catalog.FeFsTable;
import org.apache.impala.catalog.FeTable;
import org.apache.impala.common.AnalysisException;
import org.apache.impala.planner.JoinNode.DistributionMode;
import org.apache.impala.rewrite.ExprRewriter;
import org.apache.impala.thrift.TReplicaPreference;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;

/**
 * Superclass of all table references, including references to views, base tables
 * (Hdfs, HBase or DataSource tables), and nested collections. Contains the join
 * specification. An instance of a TableRef (and not a subclass thereof) represents
 * an unresolved table reference that must be resolved during analysis. All resolved
 * table references are subclasses of TableRef.
 *
 * The analysis of table refs follows a two-step process:
 *
 * 1. Resolution: A table ref's path is resolved and then the generic TableRef is
 * replaced by a concrete table ref (a BaseTableRef, CollectionTabeRef or ViewRef)
 * in the originating stmt and that is given the resolved path. This step is driven by
 * Analyzer.resolveTableRef().
 *
 * 2. Analysis/registration: After resolution, the concrete table ref is analyzed
 * to register a tuple descriptor for its resolved path and register other table-ref
 * specific state with the analyzer (e.g., whether it is outer/semi joined, etc.).
 *
 * Therefore, subclasses of TableRef should never call the analyze() of its superclass.
 *
 * TODO for 2.3: The current TableRef class hierarchy and the related two-phase analysis
 * feels convoluted and is hard to follow. We should reorganize the TableRef class
 * structure for clarity of analysis and avoid a table ref 'switching genders' in between
 * resolution and registration.
 *
 * TODO for 2.3: Rename this class to CollectionRef and re-consider the naming and
 * structure of all subclasses.
 */
public class TableRef extends StmtNode {
  // Path to a collection type. Not set for inline views.
  protected List<String> rawPath_;

  // Legal aliases of this table ref. Contains the explicit alias as its sole element if
  // there is one. Otherwise, contains the two implicit aliases. Implicit aliases are set
  // in the c'tor of the corresponding resolved table ref (subclasses of TableRef) during
  // analysis. By convention, for table refs with multiple implicit aliases, aliases_[0]
  // contains the fully-qualified implicit alias to ensure that aliases_[0] always
  // uniquely identifies this table ref regardless of whether it has an explicit alias.
  protected String[] aliases_;

  // Indicates whether this table ref is given an explicit alias,
  protected boolean hasExplicitAlias_;

  // Analysis registers privilege and/or audit requests based on this privilege.
  protected final Privilege priv_;
  protected final boolean requireGrantOption_;

  // Optional TABLESAMPLE clause. Null if not specified.
  protected TableSampleClause sampleParams_;

  protected JoinOperator joinOp_;
  protected List<PlanHint> joinHints_ = new ArrayList<>();
  protected List<String> usingColNames_;

  protected List<PlanHint> tableHints_ = new ArrayList<>();
  protected TReplicaPreference replicaPreference_;
  protected boolean randomReplica_;

  // Hinted distribution mode for this table ref; set after analyzeJoinHints()
  // TODO: Move join-specific members out of TableRef.
  private DistributionMode distrMode_ = DistributionMode.NONE;

  /////////////////////////////////////////
  // BEGIN: Members that need to be reset()

  // Resolution of rawPath_ if applicable. Result of analysis.
  protected Path resolvedPath_;

  protected Expr onClause_;

  // the ref to the left of us, if we're part of a JOIN clause
  protected TableRef leftTblRef_;

  // true if this TableRef has been analyzed; implementing subclass should set it to true
  // at the end of analyze() call.
  protected boolean isAnalyzed_;

  // Lists of table ref ids and materialized tuple ids of the full sequence of table
  // refs up to and including this one. These ids are cached during analysis because
  // we may alter the chain of table refs during plan generation, but we still rely
  // on the original list of ids for correct predicate assignment.
  // Populated in analyzeJoin().
  protected List<TupleId> allTableRefIds_ = new ArrayList<>();
  protected List<TupleId> allMaterializedTupleIds_ = new ArrayList<>();

  // All physical tuple ids that this table ref is correlated with:
  // Tuple ids of root descriptors from outer query blocks that this table ref
  // (if a CollectionTableRef) or contained CollectionTableRefs (if an InlineViewRef)
  // are rooted at. Populated during analysis.
  protected List<TupleId> correlatedTupleIds_ = new ArrayList<>();

  // analysis output
  protected TupleDescriptor desc_;

  // true if this table is masked by a table masking view and need to expose its nested
  // columns via the view.
  protected boolean exposeNestedColumnsByTableMaskView_ = false;

  // END: Members that need to be reset()
  /////////////////////////////////////////

  public TableRef(List<String> path, String alias) {
    this(path, alias, Privilege.SELECT);
  }

  public TableRef(List<String> path, String alias, TableSampleClause tableSample) {
    this(path, alias, tableSample, Privilege.SELECT, false);
  }

  public TableRef(List<String> path, String alias, Privilege priv) {
    this(path, alias, null, priv, false);
  }

  public TableRef(List<String> path, String alias, Privilege priv,
      boolean requireGrantOption) {
    this(path, alias, null, priv, requireGrantOption);
  }

  public TableRef(List<String> path, String alias, TableSampleClause sampleParams,
      Privilege priv, boolean requireGrantOption) {
    rawPath_ = path;
    if (alias != null) {
      aliases_ = new String[] { alias.toLowerCase() };
      hasExplicitAlias_ = true;
    } else {
      hasExplicitAlias_ = false;
    }
    sampleParams_ = sampleParams;
    priv_ = priv;
    requireGrantOption_ = requireGrantOption;
    isAnalyzed_ = false;
    replicaPreference_ = null;
    randomReplica_ = false;
  }

  /**
   * C'tor for cloning.
   */
  protected TableRef(TableRef other) {
    rawPath_ = other.rawPath_;
    resolvedPath_ = other.resolvedPath_;
    aliases_ = other.aliases_;
    hasExplicitAlias_ = other.hasExplicitAlias_;
    sampleParams_ = other.sampleParams_;
    priv_ = other.priv_;
    requireGrantOption_ = other.requireGrantOption_;
    joinOp_ = other.joinOp_;
    joinHints_ = Lists.newArrayList(other.joinHints_);
    onClause_ = (other.onClause_ != null) ? other.onClause_.clone() : null;
    usingColNames_ =
        (other.usingColNames_ != null) ? Lists.newArrayList(other.usingColNames_) : null;
    tableHints_ = Lists.newArrayList(other.tableHints_);
    replicaPreference_ = other.replicaPreference_;
    randomReplica_ = other.randomReplica_;
    distrMode_ = other.distrMode_;
    // The table ref links are created at the statement level, so cloning a set of linked
    // table refs is the responsibility of the statement.
    leftTblRef_ = null;
    isAnalyzed_ = other.isAnalyzed_;
    allTableRefIds_ = Lists.newArrayList(other.allTableRefIds_);
    allMaterializedTupleIds_ = Lists.newArrayList(other.allMaterializedTupleIds_);
    correlatedTupleIds_ = Lists.newArrayList(other.correlatedTupleIds_);
    desc_ = other.desc_;
    exposeNestedColumnsByTableMaskView_ = other.exposeNestedColumnsByTableMaskView_;
  }

  @Override
  public void analyze(Analyzer analyzer) throws AnalysisException {
    throw new IllegalStateException(
        "Should not call analyze() on an unresolved TableRef.");
  }

  /**
   * Creates and returns a empty TupleDescriptor registered with the analyzer
   * based on the resolvedPath_.
   * This method is called from the analyzer when registering this table reference.
   */
  public TupleDescriptor createTupleDescriptor(Analyzer analyzer)
      throws AnalysisException {
    TupleDescriptor result = analyzer.getDescTbl().createTupleDescriptor(
        getClass().getSimpleName() + " " + getUniqueAlias());
    result.setPath(resolvedPath_);
    return result;
  }

  /**
   * Set this table's context-dependent join attributes from the given table.
   * Does not clone the attributes.
   */
  protected void setJoinAttrs(TableRef other) {
    this.joinOp_ = other.joinOp_;
    this.joinHints_ = other.joinHints_;
    this.tableHints_ = other.tableHints_;
    this.onClause_ = other.onClause_;
    this.usingColNames_ = other.usingColNames_;
  }

  public JoinOperator getJoinOp() {
    // if it's not explicitly set, we're doing an inner join
    return (joinOp_ == null ? JoinOperator.INNER_JOIN : joinOp_);
  }

  public TReplicaPreference getReplicaPreference() { return replicaPreference_; }
  public boolean getRandomReplica() { return randomReplica_; }

  /**
   * Returns true if this table ref has a resolved path that is rooted at a registered
   * tuple descriptor, false otherwise.
   */
  public boolean isRelative() { return false; }

  /**
   * Indicates if this TableRef directly or indirectly references another TableRef from
   * an outer query block.
   */
  public boolean isCorrelated() { return !correlatedTupleIds_.isEmpty(); }

  public List<String> getPath() { return rawPath_; }
  public Path getResolvedPath() { return resolvedPath_; }

  /**
   * Returns all legal aliases of this table ref.
   */
  public String[] getAliases() { return aliases_; }

  /**
   * Returns the explicit alias or the fully-qualified implicit alias. The returned alias
   * is guaranteed to be unique (i.e., column/field references against the alias cannot
   * be ambiguous).
   */
  public String getUniqueAlias() { return aliases_[0]; }

  /**
   * Returns true if this table ref has an explicit alias.
   * Note that getAliases().length() == 1 does not imply an explicit alias because
   * nested collection refs have only a single implicit alias.
   */
  public boolean hasExplicitAlias() { return hasExplicitAlias_; }

  /**
   * Returns the explicit alias if this table ref has one, null otherwise.
   */
  public String getExplicitAlias() {
    if (hasExplicitAlias()) return getUniqueAlias();
    return null;
  }

  public FeTable getTable() {
    Preconditions.checkNotNull(resolvedPath_);
    return resolvedPath_.getRootTable();
  }
  public TableSampleClause getSampleParams() { return sampleParams_; }
  public Privilege getPrivilege() { return priv_; }
  public boolean requireGrantOption() { return requireGrantOption_; }
  public List<PlanHint> getJoinHints() { return joinHints_; }
  public List<PlanHint> getTableHints() { return tableHints_; }
  public Expr getOnClause() { return onClause_; }
  public void setJoinOp(JoinOperator op) { this.joinOp_ = op; }
  public void setOnClause(Expr e) { this.onClause_ = e; }
  public void setUsingClause(List<String> colNames) { this.usingColNames_ = colNames; }
  public TableRef getLeftTblRef() { return leftTblRef_; }
  public void setLeftTblRef(TableRef leftTblRef) { this.leftTblRef_ = leftTblRef; }
  public void setExposeNestedColumnsByTableMaskView() {
    exposeNestedColumnsByTableMaskView_ = true;
  }
  public boolean exposeNestedColumnsByTableMaskView() {
    return exposeNestedColumnsByTableMaskView_;
  }

  public void setJoinHints(List<PlanHint> hints) {
    Preconditions.checkNotNull(hints);
    joinHints_ = hints;
  }

  public void setTableHints(List<PlanHint> hints) {
    Preconditions.checkNotNull(hints);
    tableHints_ = hints;
  }

  public boolean isBroadcastJoin() { return distrMode_ == DistributionMode.BROADCAST; }

  public boolean isPartitionedJoin() {
    return distrMode_ == DistributionMode.PARTITIONED;
  }

  public DistributionMode getDistributionMode() { return distrMode_; }
  public List<TupleId> getCorrelatedTupleIds() { return correlatedTupleIds_; }
  public boolean isAnalyzed() { return isAnalyzed_; }
  public boolean isResolved() { return !getClass().equals(TableRef.class); }

  /**
   * This method should only be called after the TableRef has been analyzed.
   */
  public TupleDescriptor getDesc() {
    Preconditions.checkState(isAnalyzed_);
    // after analyze(), desc should be set.
    Preconditions.checkState(desc_ != null);
    return desc_;
  }

  /**
   * This method should only be called after the TableRef has been analyzed.
   */
  public TupleId getId() {
    Preconditions.checkState(isAnalyzed_);
    // after analyze(), desc should be set.
    Preconditions.checkNotNull(desc_);
    return desc_.getId();
  }

  public List<TupleId> getMaterializedTupleIds() {
    // This function should only be called after analyze().
    Preconditions.checkState(isAnalyzed_);
    Preconditions.checkNotNull(desc_);
    return desc_.getId().asList();
  }

  /**
   * Returns the list of tuple ids materialized by the full sequence of
   * table refs up to and including this one.
   */
  public List<TupleId> getAllMaterializedTupleIds() {
    Preconditions.checkState(isAnalyzed_);
    return allMaterializedTupleIds_;
  }

  /**
   * Return the list of table ref ids of the full sequence of table refs up to
   * and including this one.
   */
  public List<TupleId> getAllTableRefIds() {
    Preconditions.checkState(isAnalyzed_);
    return allTableRefIds_;
  }

  protected void analyzeTableSample(Analyzer analyzer) throws AnalysisException {
    if (sampleParams_ == null) return;
    sampleParams_.analyze(analyzer);
    if (!(this instanceof BaseTableRef)
        || !(resolvedPath_.destTable() instanceof FeFsTable)) {
      throw new AnalysisException(
          "TABLESAMPLE is only supported on HDFS tables: " + getUniqueAlias());
    }
  }

  protected void analyzeHints(Analyzer analyzer) throws AnalysisException {
    // We prefer adding warnings over throwing exceptions here to maintain view
    // compatibility with Hive.
    Preconditions.checkState(isResolved());
    analyzeTableHints(analyzer);
    analyzeJoinHints(analyzer);
  }

  private void analyzeTableHints(Analyzer analyzer) {
    if (tableHints_.isEmpty()) return;
    if (!(this instanceof BaseTableRef)) {
      analyzer.addWarning("Table hints not supported for inline view and collections");
      return;
    }
    // BaseTableRef will always have their path resolved at this point.
    Preconditions.checkState(getResolvedPath() != null);
    if (getResolvedPath().destTable() != null &&
        !(getResolvedPath().destTable() instanceof FeFsTable)) {
      analyzer.addWarning("Table hints only supported for Hdfs tables");
    }
    for (PlanHint hint: tableHints_) {
      if (hint.is("SCHEDULE_CACHE_LOCAL")) {
        analyzer.setHasPlanHints();
        replicaPreference_ = TReplicaPreference.CACHE_LOCAL;
      } else if (hint.is("SCHEDULE_DISK_LOCAL")) {
        analyzer.setHasPlanHints();
        replicaPreference_ = TReplicaPreference.DISK_LOCAL;
      } else if (hint.is("SCHEDULE_REMOTE")) {
        analyzer.setHasPlanHints();
        replicaPreference_ = TReplicaPreference.REMOTE;
      } else if (hint.is("SCHEDULE_RANDOM_REPLICA")) {
        analyzer.setHasPlanHints();
        randomReplica_ = true;
      } else {
        Preconditions.checkState(getAliases() != null && getAliases().length > 0);
        analyzer.addWarning("Table hint not recognized for table " + getUniqueAlias() +
            ": " + hint);
      }
    }
  }

  private void analyzeJoinHints(Analyzer analyzer) throws AnalysisException {
    if (joinHints_.isEmpty()) return;
    for (PlanHint hint: joinHints_) {
      if (hint.is("BROADCAST")) {
        if (joinOp_ == JoinOperator.RIGHT_OUTER_JOIN
            || joinOp_ == JoinOperator.FULL_OUTER_JOIN
            || joinOp_ == JoinOperator.RIGHT_SEMI_JOIN
            || joinOp_ == JoinOperator.RIGHT_ANTI_JOIN) {
          throw new AnalysisException(
              joinOp_.toString() + " does not support BROADCAST.");
        }
        if (isPartitionedJoin()) {
          throw new AnalysisException("Conflicting JOIN hint: " + hint);
        }
        distrMode_ = DistributionMode.BROADCAST;
        analyzer.setHasPlanHints();
      } else if (hint.is("SHUFFLE")) {
        if (joinOp_ == JoinOperator.CROSS_JOIN) {
          throw new AnalysisException("CROSS JOIN does not support SHUFFLE.");
        }
        if (isBroadcastJoin()) {
          throw new AnalysisException("Conflicting JOIN hint: " + hint);
        }
        distrMode_ = DistributionMode.PARTITIONED;
        analyzer.setHasPlanHints();
      } else {
        analyzer.addWarning("JOIN hint not recognized: " + hint);
      }
    }
  }

  /**
   * Analyzes the join clause. Populates allTableRefIds_ and allMaterializedTupleIds_.
   * The join clause can only be analyzed after the left table has been analyzed
   * and the TupleDescriptor (desc) of this table has been created.
   */
  public void analyzeJoin(Analyzer analyzer) throws AnalysisException {
    Preconditions.checkState(leftTblRef_ == null || leftTblRef_.isAnalyzed_);
    Preconditions.checkState(desc_ != null);

    // Populate the lists of all table ref and materialized tuple ids.
    allTableRefIds_.clear();
    allMaterializedTupleIds_.clear();
    if (leftTblRef_ != null) {
      allTableRefIds_.addAll(leftTblRef_.getAllTableRefIds());
      allMaterializedTupleIds_.addAll(leftTblRef_.getAllMaterializedTupleIds());
    }
    allTableRefIds_.add(getId());
    allMaterializedTupleIds_.addAll(getMaterializedTupleIds());

    if (joinOp_ == JoinOperator.CROSS_JOIN) {
      // A CROSS JOIN is always a broadcast join, regardless of the join hints
      distrMode_ = DistributionMode.BROADCAST;
    }

    if (usingColNames_ != null) {
      Preconditions.checkState(joinOp_ != JoinOperator.CROSS_JOIN);
      // Turn USING clause into equivalent ON clause.
      onClause_ = null;
      for (String colName: usingColNames_) {
        // check whether colName exists both for our table and the one
        // to the left of us
        Path leftColPath = new Path(leftTblRef_.getDesc(),
            Lists.newArrayList(colName.toLowerCase()));
        if (!leftColPath.resolve()) {
          throw new AnalysisException(
              "unknown column " + colName + " for alias "
              + leftTblRef_.getUniqueAlias() + " (in \"" + this.toSql() + "\")");
        }
        Path rightColPath = new Path(desc_,
            Lists.newArrayList(colName.toLowerCase()));
        if (!rightColPath.resolve()) {
          throw new AnalysisException(
              "unknown column " + colName + " for alias "
              + getUniqueAlias() + " (in \"" + this.toSql() + "\")");
        }

        // create predicate "<left>.colName = <right>.colName"
        BinaryPredicate eqPred =
            new BinaryPredicate(BinaryPredicate.Operator.EQ,
              new SlotRef(Path.createRawPath(leftTblRef_.getUniqueAlias(), colName)),
              new SlotRef(Path.createRawPath(getUniqueAlias(), colName)));
        onClause_ = CompoundPredicate.createConjunction(eqPred, onClause_);
      }
    }

    // at this point, both 'this' and leftTblRef have been analyzed and registered;
    // register the tuple ids of the TableRefs on the nullable side of an outer join
    if (joinOp_ == JoinOperator.LEFT_OUTER_JOIN
        || joinOp_ == JoinOperator.FULL_OUTER_JOIN) {
      analyzer.registerOuterJoinedTids(getId().asList(), this);
    }
    if (joinOp_ == JoinOperator.RIGHT_OUTER_JOIN
        || joinOp_ == JoinOperator.FULL_OUTER_JOIN) {
      analyzer.registerOuterJoinedTids(leftTblRef_.getAllTableRefIds(), this);
    }
    // register the tuple ids of a full outer join
    if (joinOp_ == JoinOperator.FULL_OUTER_JOIN) {
      analyzer.registerFullOuterJoinedTids(leftTblRef_.getAllTableRefIds(), this);
      analyzer.registerFullOuterJoinedTids(getId().asList(), this);
    }
    // register the tuple id of the rhs of a left semi join
    TupleId semiJoinedTupleId = null;
    if (joinOp_ == JoinOperator.LEFT_SEMI_JOIN
        || joinOp_ == JoinOperator.LEFT_ANTI_JOIN
        || joinOp_ == JoinOperator.NULL_AWARE_LEFT_ANTI_JOIN) {
      analyzer.registerSemiJoinedTid(getId(), this);
      semiJoinedTupleId = getId();
    }
    // register the tuple id of the lhs of a right semi join
    if (joinOp_ == JoinOperator.RIGHT_SEMI_JOIN
        || joinOp_ == JoinOperator.RIGHT_ANTI_JOIN) {
      analyzer.registerSemiJoinedTid(leftTblRef_.getId(), this);
      semiJoinedTupleId = leftTblRef_.getId();
    }

    if (onClause_ != null) {
      Preconditions.checkState(joinOp_ != JoinOperator.CROSS_JOIN);
      analyzer.setVisibleSemiJoinedTuple(semiJoinedTupleId);
      onClause_.analyze(analyzer);
      analyzer.setVisibleSemiJoinedTuple(null);
      onClause_.checkReturnsBool("ON clause", true);
        if (onClause_.contains(Expr.IS_AGGREGATE)) {
          throw new AnalysisException(
              "aggregate function not allowed in ON clause: " + toSql());
      }
      if (onClause_.contains(AnalyticExpr.class)) {
        throw new AnalysisException(
            "analytic expression not allowed in ON clause: " + toSql());
      }
      if (onClause_.contains(Subquery.class)) {
        throw new AnalysisException(
            "Subquery is not allowed in ON clause: " + toSql());
      }
      Set<TupleId> onClauseTupleIds = new HashSet<>();
      List<Expr> conjuncts = onClause_.getConjuncts();
      // Outer join clause conjuncts are registered for this particular table ref
      // (ie, can only be evaluated by the plan node that implements this join).
      // The exception are conjuncts that only pertain to the nullable side
      // of the outer join; those can be evaluated directly when materializing tuples
      // without violating outer join semantics.
      analyzer.registerOnClauseConjuncts(conjuncts, this);
      for (Expr e: conjuncts) {
        List<TupleId> tupleIds = new ArrayList<>();
        e.getIds(tupleIds, null);
        onClauseTupleIds.addAll(tupleIds);
      }
    } else if (!isRelative() && !isCorrelated()
        && (getJoinOp().isOuterJoin() || getJoinOp().isSemiJoin())) {
      throw new AnalysisException(
          joinOp_.toString() + " requires an ON or USING clause.");
    } else {
      // Indicate that this table ref has an empty ON-clause.
      analyzer.registerOnClauseConjuncts(Collections.<Expr>emptyList(), this);
    }
  }

  public void rewriteExprs(ExprRewriter rewriter, Analyzer analyzer)
      throws AnalysisException {
    Preconditions.checkState(isAnalyzed_);
    if (onClause_ != null) onClause_ = rewriter.rewrite(onClause_, analyzer);
  }

  public String debugString() { return tableRefToSql(); }

  protected String tableRefToSql() { return tableRefToSql(DEFAULT); }

  protected String tableRefToSql(ToSqlOptions options) {
    String aliasSql = null;
    String alias = getExplicitAlias();
    if (alias != null) aliasSql = ToSqlUtils.getIdentSql(alias);
    List<String> path = rawPath_;
    if (resolvedPath_ != null) path = resolvedPath_.getFullyQualifiedRawPath();
    return ToSqlUtils.getPathSql(path) + ((aliasSql != null) ? " " + aliasSql : "");
  }

  @Override
  public final String toSql() {
    return toSql(DEFAULT);
  }

  @Override
  public String toSql(ToSqlOptions options) {
    if (joinOp_ == null) {
      // prepend "," if we're part of a sequence of table refs w/o an
      // explicit JOIN clause
      return (leftTblRef_ != null ? ", " : "") + tableRefToSql(options);
    }

    StringBuilder output = new StringBuilder(" " + joinOp_.toString() + " ");
    if (!joinHints_.isEmpty())
      output.append(ToSqlUtils.getPlanHintsSql(options, joinHints_)).append(" ");
    output.append(tableRefToSql(options));
    if (usingColNames_ != null) {
      output.append(" USING (").append(Joiner.on(", ").join(usingColNames_)).append(")");
    } else if (onClause_ != null) {
      output.append(" ON ").append(onClause_.toSql(options));
    }
    return output.toString();
  }

  /**
   * Returns a deep clone of this table ref without also cloning the chain of table refs.
   * Sets leftTblRef_ in the returned clone to null.
   */
  @Override
  protected TableRef clone() { return new TableRef(this); }

  public void reset() {
    isAnalyzed_ = false;
    resolvedPath_ = null;
    if (usingColNames_ != null) {
      // The using col names are converted into an on-clause predicate during analysis,
      // so unset the on-clause here.
      onClause_ = null;
    } else if (onClause_ != null) {
      onClause_.reset();
    }
    leftTblRef_ = null;
    allTableRefIds_.clear();
    allMaterializedTupleIds_.clear();
    correlatedTupleIds_.clear();
    desc_ = null;
  }

  public boolean isTableMaskingView() { return false; }

  void migratePropertiesTo(TableRef other) {
    other.aliases_ = aliases_;
    other.onClause_ = onClause_;
    other.usingColNames_ = usingColNames_;
    other.joinOp_ = joinOp_;
    other.joinHints_ = joinHints_;
    other.tableHints_ = tableHints_;
    // Clear properties. Don't clear aliases_ since it's still used in resolving slots
    // in the query block of 'other'.
    onClause_ = null;
    usingColNames_ = null;
    joinOp_ = null;
    joinHints_ = new ArrayList<>();
    tableHints_ = new ArrayList<>();
  }
}
