/*
 * 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.tools;

import org.apache.calcite.linq4j.Ord;
import org.apache.calcite.linq4j.function.Experimental;
import org.apache.calcite.plan.Context;
import org.apache.calcite.plan.Contexts;
import org.apache.calcite.plan.Convention;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptPredicateList;
import org.apache.calcite.plan.RelOptSchema;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.plan.ViewExpanders;
import org.apache.calcite.prepare.RelOptTableImpl;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelDistribution;
import org.apache.calcite.rel.RelFieldCollation;
import org.apache.calcite.rel.RelHomogeneousShuttle;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.core.AggregateCall;
import org.apache.calcite.rel.core.Correlate;
import org.apache.calcite.rel.core.CorrelationId;
import org.apache.calcite.rel.core.Filter;
import org.apache.calcite.rel.core.Intersect;
import org.apache.calcite.rel.core.Join;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.core.Match;
import org.apache.calcite.rel.core.Minus;
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.core.RelFactories;
import org.apache.calcite.rel.core.RepeatUnion;
import org.apache.calcite.rel.core.Snapshot;
import org.apache.calcite.rel.core.Sort;
import org.apache.calcite.rel.core.Spool;
import org.apache.calcite.rel.core.TableFunctionScan;
import org.apache.calcite.rel.core.TableScan;
import org.apache.calcite.rel.core.TableSpool;
import org.apache.calcite.rel.core.Uncollect;
import org.apache.calcite.rel.core.Union;
import org.apache.calcite.rel.core.Values;
import org.apache.calcite.rel.hint.Hintable;
import org.apache.calcite.rel.hint.RelHint;
import org.apache.calcite.rel.logical.LogicalFilter;
import org.apache.calcite.rel.logical.LogicalProject;
import org.apache.calcite.rel.metadata.RelColumnMapping;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexCall;
import org.apache.calcite.rex.RexCallBinding;
import org.apache.calcite.rex.RexCorrelVariable;
import org.apache.calcite.rex.RexDynamicParam;
import org.apache.calcite.rex.RexExecutor;
import org.apache.calcite.rex.RexFieldCollation;
import org.apache.calcite.rex.RexInputRef;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexShuttle;
import org.apache.calcite.rex.RexSimplify;
import org.apache.calcite.rex.RexSubQuery;
import org.apache.calcite.rex.RexUtil;
import org.apache.calcite.rex.RexWindowBound;
import org.apache.calcite.rex.RexWindowBounds;
import org.apache.calcite.runtime.Hook;
import org.apache.calcite.schema.TransientTable;
import org.apache.calcite.schema.impl.ListTransientTable;
import org.apache.calcite.sql.SqlAggFunction;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlUtil;
import org.apache.calcite.sql.SqlWindow;
import org.apache.calcite.sql.fun.SqlCountAggFunction;
import org.apache.calcite.sql.fun.SqlLikeOperator;
import org.apache.calcite.sql.fun.SqlQuantifyOperator;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.type.SqlReturnTypeInference;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.sql.type.TableFunctionReturnTypeInference;
import org.apache.calcite.sql.validate.SqlValidatorUtil;
import org.apache.calcite.sql2rel.SqlToRelConverter;
import org.apache.calcite.util.Holder;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.ImmutableIntList;
import org.apache.calcite.util.ImmutableNullableList;
import org.apache.calcite.util.Litmus;
import org.apache.calcite.util.NlsString;
import org.apache.calcite.util.Optionality;
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.Util;
import org.apache.calcite.util.mapping.Mapping;
import org.apache.calcite.util.mapping.Mappings;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMultiset;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;

import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.immutables.value.Value;

import java.math.BigDecimal;
import java.util.AbstractList;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.Deque;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import static org.apache.calcite.linq4j.Nullness.castNonNull;
import static org.apache.calcite.sql.SqlKind.UNION;
import static org.apache.calcite.util.Static.RESOURCE;

import static java.util.Objects.requireNonNull;

/**
 * Builder for relational expressions.
 *
 * <p>{@code RelBuilder} does not make possible anything that you could not
 * also accomplish by calling the factory methods of the particular relational
 * expression. But it makes common tasks more straightforward and concise.
 *
 * <p>{@code RelBuilder} uses factories to create relational expressions.
 * By default, it uses the default factories, which create logical relational
 * expressions ({@link LogicalFilter},
 * {@link LogicalProject} and so forth).
 * But you could override those factories so that, say, {@code filter} creates
 * instead a {@code HiveFilter}.
 *
 * <p>It is not thread-safe.
 */
@Value.Enclosing
public class RelBuilder {
  protected final RelOptCluster cluster;
  protected final @Nullable RelOptSchema relOptSchema;
  private final Deque<Frame> stack = new ArrayDeque<>();
  private RexSimplify simplifier;
  private final Config config;
  private final RelOptTable.ViewExpander viewExpander;
  private RelFactories.Struct struct;

  protected RelBuilder(@Nullable Context context, RelOptCluster cluster,
      @Nullable RelOptSchema relOptSchema) {
    this.cluster = cluster;
    this.relOptSchema = relOptSchema;
    if (context == null) {
      context = Contexts.EMPTY_CONTEXT;
    }
    this.config = getConfig(context);
    this.viewExpander = getViewExpander(cluster, context);
    this.struct =
        requireNonNull(RelFactories.Struct.fromContext(context));
    final RexExecutor executor =
        context.maybeUnwrap(RexExecutor.class)
            .orElse(
                Util.first(cluster.getPlanner().getExecutor(),
                    RexUtil.EXECUTOR));
    final RelOptPredicateList predicates = RelOptPredicateList.EMPTY;
    this.simplifier =
        new RexSimplify(cluster.getRexBuilder(), predicates, executor);
  }

  /**
   * Derives the view expander
   * {@link org.apache.calcite.plan.RelOptTable.ViewExpander}
   * to be used for this RelBuilder.
   *
   * <p>The ViewExpander instance is used for expanding views in the default
   * table scan factory {@code RelFactories.TableScanFactoryImpl}.
   * You can also define a new table scan factory in the {@code struct}
   * to override the whole table scan creation.
   *
   * <p>The default view expander does not support expanding views.
   */
  private static RelOptTable.ViewExpander getViewExpander(RelOptCluster cluster,
      Context context) {
    return context.maybeUnwrap(RelOptTable.ViewExpander.class)
        .orElseGet(() -> ViewExpanders.simpleContext(cluster));
  }

  /** Derives the Config to be used for this RelBuilder.
   *
   * <p>Overrides {@link RelBuilder.Config#simplify} if
   * {@link Hook#REL_BUILDER_SIMPLIFY} is set.
   */
  private static Config getConfig(Context context) {
    final Config config =
        context.maybeUnwrap(Config.class).orElse(Config.DEFAULT);
    boolean simplify = Hook.REL_BUILDER_SIMPLIFY.get(config.simplify());
    return config.withSimplify(simplify);
  }

  /** Creates a RelBuilder. */
  public static RelBuilder create(FrameworkConfig config) {
    return Frameworks.withPrepare(config,
        (cluster, relOptSchema, rootSchema, statement) ->
            new RelBuilder(config.getContext(), cluster, relOptSchema));
  }

  /** Creates a copy of this RelBuilder, with the same state as this, applying
   * a transform to the config. */
  public RelBuilder transform(UnaryOperator<Config> transform) {
    final Context context =
        Contexts.of(struct, transform.apply(config));
    return new RelBuilder(context, cluster, relOptSchema);
  }

  /** Performs an action on this RelBuilder.
   *
   * <p>For example, consider the following code:
   *
   * <blockquote><pre>
   *   RelNode filterAndRename(RelBuilder relBuilder, RelNode rel,
   *       RexNode condition, List&lt;String&gt; fieldNames) {
   *     relBuilder.push(rel)
   *         .filter(condition);
   *     if (fieldNames != null) {
   *       relBuilder.rename(fieldNames);
   *     }
   *     return relBuilder
   *         .build();</pre>
   * </blockquote>
   *
   * <p>The pipeline is disrupted by the 'if'. The {@code let} method
   * allows you to perform the flow as a single pipeline:
   *
   * <blockquote><pre>
   *   RelNode filterAndRename(RelBuilder relBuilder, RelNode rel,
   *       RexNode condition, List&lt;String&gt; fieldNames) {
   *     return relBuilder.push(rel)
   *         .filter(condition)
   *         .let(r -&gt; fieldNames == null ? r : r.rename(fieldNames))
   *         .build();</pre>
   * </blockquote>
   *
   * <p>In pipelined cases such as this one, the lambda must return this
   * RelBuilder. But {@code let} return values of other types.
   */
  public <R> R let(Function<RelBuilder, R> consumer) {
    return consumer.apply(this);
  }

  /** Converts this RelBuilder to a string.
   * The string is the string representation of all of the RelNodes on the stack. */
  @Override public String toString() {
    return stack.stream()
        .map(frame -> RelOptUtil.toString(frame.rel))
        .collect(Collectors.joining(""));
  }

  /** Returns the type factory. */
  public RelDataTypeFactory getTypeFactory() {
    return cluster.getTypeFactory();
  }

  /** Returns new RelBuilder that adopts the convention provided.
   * RelNode will be created with such convention if corresponding factory is provided. */
  public RelBuilder adoptConvention(Convention convention) {
    this.struct = convention.getRelFactories();
    return this;
  }

  /** Returns the builder for {@link RexNode} expressions. */
  public RexBuilder getRexBuilder() {
    return cluster.getRexBuilder();
  }

  /** Creates a {@link RelBuilderFactory}, a partially-created RelBuilder.
   * Just add a {@link RelOptCluster} and a {@link RelOptSchema} */
  public static RelBuilderFactory proto(final Context context) {
    return (cluster, schema) -> new RelBuilder(context, cluster, schema);
  }

  /** Creates a {@link RelBuilderFactory} that uses a given set of factories. */
  public static RelBuilderFactory proto(Object... factories) {
    return proto(Contexts.of(factories));
  }

  public RelOptCluster getCluster() {
    return cluster;
  }

  public @Nullable RelOptSchema getRelOptSchema() {
    return relOptSchema;
  }

  public RelFactories.TableScanFactory getScanFactory() {
    return struct.scanFactory;
  }

  // Methods for manipulating the stack

  /** Adds a relational expression to be the input to the next relational
   * expression constructed.
   *
   * <p>This method is usual when you want to weave in relational expressions
   * that are not supported by the builder. If, while creating such expressions,
   * you need to use previously built expressions as inputs, call
   * {@link #build()} to pop those inputs. */
  public RelBuilder push(RelNode node) {
    stack.push(new Frame(node));
    return this;
  }

  /** Adds a rel node to the top of the stack while preserving the field names
   * and aliases. */
  private void replaceTop(RelNode node) {
    final Frame frame = stack.pop();
    stack.push(new Frame(node, frame.fields));
  }

  /** Pushes a collection of relational expressions. */
  public RelBuilder pushAll(Iterable<? extends RelNode> nodes) {
    for (RelNode node : nodes) {
      push(node);
    }
    return this;
  }

  /** Returns the size of the stack. */
  public int size() {
    return stack.size();
  }

  /** Returns the final relational expression.
   *
   * <p>Throws if the stack is empty.
   */
  public RelNode build() {
    return stack.pop().rel;
  }

  /** Returns the relational expression at the top of the stack, but does not
   * remove it. */
  public RelNode peek() {
    return castNonNull(peek_()).rel;
  }

  private @Nullable Frame peek_() {
    return stack.peek();
  }

  /** Returns the relational expression {@code n} positions from the top of the
   * stack, but does not remove it. */
  public RelNode peek(int n) {
    return peek_(n).rel;
  }

  private Frame peek_(int n) {
    if (n == 0) {
      // more efficient than starting an iterator
      return Objects.requireNonNull(stack.peek(), "stack.peek");
    }
    return Iterables.get(stack, n);
  }

  /** Returns the relational expression {@code n} positions from the top of the
   * stack, but does not remove it. */
  public RelNode peek(int inputCount, int inputOrdinal) {
    return peek_(inputCount, inputOrdinal).rel;
  }

  private Frame peek_(int inputCount, int inputOrdinal) {
    return peek_(inputCount - 1 - inputOrdinal);
  }

  /** Returns the number of fields in all inputs before (to the left of)
   * the given input.
   *
   * @param inputCount Number of inputs
   * @param inputOrdinal Input ordinal
   */
  private int inputOffset(int inputCount, int inputOrdinal) {
    int offset = 0;
    for (int i = 0; i < inputOrdinal; i++) {
      offset += peek(inputCount, i).getRowType().getFieldCount();
    }
    return offset;
  }

  /** Evaluates an expression with a relational expression temporarily on the
   * stack. */
  public <E> E with(RelNode r, Function<RelBuilder, E> fn) {
    try {
      push(r);
      return fn.apply(this);
    } finally {
      stack.pop();
    }
  }

  /** Performs an action with a temporary simplifier. */
  public <E> E withSimplifier(
      BiFunction<RelBuilder, RexSimplify, RexSimplify> simplifierTransform,
      Function<RelBuilder, E> fn) {
    final RexSimplify previousSimplifier = this.simplifier;
    try {
      this.simplifier = simplifierTransform.apply(this, previousSimplifier);
      return fn.apply(this);
    } finally {
      this.simplifier = previousSimplifier;
    }
  }

  /** Performs an action using predicates of
   * the {@link #peek() current node} to simplify. */
  public <E> E withPredicates(RelMetadataQuery mq,
      Function<RelBuilder, E> fn) {
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(peek());
    return withSimplifier((r, s) -> s.withPredicates(predicates), fn);
  }

  // Methods that return scalar expressions

  /** Creates a literal (constant expression). */
  public RexLiteral literal(@Nullable Object value) {
    final RexBuilder rexBuilder = cluster.getRexBuilder();
    if (value == null) {
      final RelDataType type = getTypeFactory().createSqlType(SqlTypeName.NULL);
      return rexBuilder.makeNullLiteral(type);
    } else if (value instanceof Boolean) {
      return rexBuilder.makeLiteral((Boolean) value);
    } else if (value instanceof BigDecimal) {
      return rexBuilder.makeExactLiteral((BigDecimal) value);
    } else if (value instanceof Float || value instanceof Double) {
      return rexBuilder.makeApproxLiteral(
          BigDecimal.valueOf(((Number) value).doubleValue()));
    } else if (value instanceof Number) {
      return rexBuilder.makeExactLiteral(
          BigDecimal.valueOf(((Number) value).longValue()));
    } else if (value instanceof String) {
      return rexBuilder.makeLiteral((String) value);
    } else if (value instanceof Enum) {
      return rexBuilder.makeLiteral(value,
          getTypeFactory().createSqlType(SqlTypeName.SYMBOL));
    } else {
      throw new IllegalArgumentException("cannot convert " + value
          + " (" + value.getClass() + ") to a constant");
    }
  }

  /** Creates a correlation variable for the current input, and writes it into
   * a Holder. */
  public RelBuilder variable(Holder<RexCorrelVariable> v) {
    v.set((RexCorrelVariable)
        getRexBuilder().makeCorrel(peek().getRowType(),
            cluster.createCorrel()));
    return this;
  }

  /** Creates a reference to a field by name.
   *
   * <p>Equivalent to {@code field(1, 0, fieldName)}.
   *
   * @param fieldName Field name
   */
  public RexInputRef field(String fieldName) {
    return field(1, 0, fieldName);
  }

  /** Creates a reference to a field of given input relational expression
   * by name.
   *
   * @param inputCount Number of inputs
   * @param inputOrdinal Input ordinal
   * @param fieldName Field name
   */
  public RexInputRef field(int inputCount, int inputOrdinal, String fieldName) {
    final Frame frame = peek_(inputCount, inputOrdinal);
    final List<String> fieldNames = Pair.left(frame.fields());
    int i = fieldNames.indexOf(fieldName);
    if (i >= 0) {
      return field(inputCount, inputOrdinal, i);
    } else {
      throw new IllegalArgumentException("field [" + fieldName
          + "] not found; input fields are: " + fieldNames);
    }
  }

  /** Creates a reference to an input field by ordinal.
   *
   * <p>Equivalent to {@code field(1, 0, ordinal)}.
   *
   * @param fieldOrdinal Field ordinal
   */
  public RexInputRef field(int fieldOrdinal) {
    return (RexInputRef) field(1, 0, fieldOrdinal, false);
  }

  /** Creates a reference to a field of a given input relational expression
   * by ordinal.
   *
   * @param inputCount Number of inputs
   * @param inputOrdinal Input ordinal
   * @param fieldOrdinal Field ordinal within input
   */
  public RexInputRef field(int inputCount, int inputOrdinal, int fieldOrdinal) {
    return (RexInputRef) field(inputCount, inputOrdinal, fieldOrdinal, false);
  }

  /** As {@link #field(int, int, int)}, but if {@code alias} is true, the method
   * may apply an alias to make sure that the field has the same name as in the
   * input frame. If no alias is applied the expression is definitely a
   * {@link RexInputRef}. */
  private RexNode field(int inputCount, int inputOrdinal, int fieldOrdinal,
      boolean alias) {
    final Frame frame = peek_(inputCount, inputOrdinal);
    final RelNode input = frame.rel;
    final RelDataType rowType = input.getRowType();
    if (fieldOrdinal < 0 || fieldOrdinal > rowType.getFieldCount()) {
      throw new IllegalArgumentException("field ordinal [" + fieldOrdinal
          + "] out of range; input fields are: " + rowType.getFieldNames());
    }
    final RelDataTypeField field = rowType.getFieldList().get(fieldOrdinal);
    final int offset = inputOffset(inputCount, inputOrdinal);
    final RexInputRef ref = cluster.getRexBuilder()
        .makeInputRef(field.getType(), offset + fieldOrdinal);
    final RelDataTypeField aliasField = frame.fields().get(fieldOrdinal);
    if (!alias || field.getName().equals(aliasField.getName())) {
      return ref;
    } else {
      return alias(ref, aliasField.getName());
    }
  }

  /** Creates a reference to a field of the current record which originated
   * in a relation with a given alias. */
  public RexNode field(String alias, String fieldName) {
    return field(1, alias, fieldName);
  }

  /** Creates a reference to a field which originated in a relation with the
   * given alias. Searches for the relation starting at the top of the
   * stack. */
  public RexNode field(int inputCount, String alias, String fieldName) {
    requireNonNull(alias, "alias");
    requireNonNull(fieldName, "fieldName");
    final List<String> fields = new ArrayList<>();
    for (int inputOrdinal = 0; inputOrdinal < inputCount; ++inputOrdinal) {
      final Frame frame = peek_(inputOrdinal);
      for (Ord<Field> p
          : Ord.zip(frame.fields)) {
        // If alias and field name match, reference that field.
        if (p.e.left.contains(alias)
            && p.e.right.getName().equals(fieldName)) {
          return field(inputCount, inputCount - 1 - inputOrdinal, p.i);
        }
        fields.add(
            String.format(Locale.ROOT, "{aliases=%s,fieldName=%s}", p.e.left,
                p.e.right.getName()));
      }
    }
    throw new IllegalArgumentException("{alias=" + alias + ",fieldName=" + fieldName + "} "
        + "field not found; fields are: " + fields);
  }

  /** Returns a reference to a given field of a record-valued expression. */
  public RexNode field(RexNode e, String name) {
    return getRexBuilder().makeFieldAccess(e, name, false);
  }

  /** Returns references to the fields of the top input. */
  public ImmutableList<RexNode> fields() {
    return fields(1, 0);
  }

  /** Returns references to the fields of a given input. */
  public ImmutableList<RexNode> fields(int inputCount, int inputOrdinal) {
    final RelNode input = peek(inputCount, inputOrdinal);
    final RelDataType rowType = input.getRowType();
    final ImmutableList.Builder<RexNode> nodes = ImmutableList.builder();
    for (int fieldOrdinal : Util.range(rowType.getFieldCount())) {
      nodes.add(field(inputCount, inputOrdinal, fieldOrdinal));
    }
    return nodes.build();
  }

  /** Returns references to fields for a given collation. */
  public ImmutableList<RexNode> fields(RelCollation collation) {
    final ImmutableList.Builder<RexNode> nodes = ImmutableList.builder();
    for (RelFieldCollation fieldCollation : collation.getFieldCollations()) {
      RexNode node = field(fieldCollation.getFieldIndex());
      switch (fieldCollation.direction) {
      case DESCENDING:
        node = desc(node);
        break;
      default:
        break;
      }
      switch (fieldCollation.nullDirection) {
      case FIRST:
        node = nullsFirst(node);
        break;
      case LAST:
        node = nullsLast(node);
        break;
      default:
        break;
      }
      nodes.add(node);
    }
    return nodes.build();
  }

  /** Returns references to fields for a given list of input ordinals. */
  public ImmutableList<RexNode> fields(List<? extends Number> ordinals) {
    final ImmutableList.Builder<RexNode> nodes = ImmutableList.builder();
    for (Number ordinal : ordinals) {
      RexNode node = field(1, 0, ordinal.intValue(), false);
      nodes.add(node);
    }
    return nodes.build();
  }

  /** Returns references to fields for a given bit set of input ordinals. */
  public ImmutableList<RexNode> fields(ImmutableBitSet ordinals) {
    return fields(ordinals.asList());
  }

  /** Returns references to fields identified by name. */
  public ImmutableList<RexNode> fields(Iterable<String> fieldNames) {
    final ImmutableList.Builder<RexNode> builder = ImmutableList.builder();
    for (String fieldName : fieldNames) {
      builder.add(field(fieldName));
    }
    return builder.build();
  }

  /** Returns references to fields identified by a mapping. */
  public ImmutableList<RexNode> fields(Mappings.TargetMapping mapping) {
    return fields(Mappings.asListNonNull(mapping));
  }

  /** Creates an access to a field by name. */
  public RexNode dot(RexNode node, String fieldName) {
    final RexBuilder builder = cluster.getRexBuilder();
    return builder.makeFieldAccess(node, fieldName, true);
  }

  /** Creates an access to a field by ordinal. */
  public RexNode dot(RexNode node, int fieldOrdinal) {
    final RexBuilder builder = cluster.getRexBuilder();
    return builder.makeFieldAccess(node, fieldOrdinal);
  }

  /** Creates a call to a scalar operator. */
  public RexNode call(SqlOperator operator, RexNode... operands) {
    return call(operator, ImmutableList.copyOf(operands));
  }

  /** Creates a call to a scalar operator. */
  private RexCall call(SqlOperator operator, List<RexNode> operandList) {
    switch (operator.getKind()) {
    case LIKE:
    case SIMILAR:
      final SqlLikeOperator likeOperator = (SqlLikeOperator) operator;
      if (likeOperator.isNegated()) {
        final SqlOperator notLikeOperator = likeOperator.not();
        return (RexCall) not(call(notLikeOperator, operandList));
      }
      break;
    case BETWEEN:
      assert operandList.size() == 3;
      return (RexCall) between(operandList.get(0), operandList.get(1),
          operandList.get(2));
    default:
      break;
    }
    final RexBuilder builder = cluster.getRexBuilder();
    final RelDataType type = builder.deriveReturnType(operator, operandList);
    return (RexCall) builder.makeCall(type, operator, operandList);
  }

  /** Creates a call to a scalar operator. */
  public RexNode call(SqlOperator operator,
      Iterable<? extends RexNode> operands) {
    return call(operator, ImmutableList.copyOf(operands));
  }

  /** Creates an IN predicate with a list of values.
   *
   * <p>For example,
   * <pre>{@code
   * b.scan("Emp")
   *     .filter(b.in(b.field("deptno"), b.literal(10), b.literal(20)))
   * }</pre>
   * is equivalent to SQL
   * <pre>{@code
   * SELECT *
   * FROM Emp
   * WHERE deptno IN (10, 20)
   * }</pre> */
  public RexNode in(RexNode arg, RexNode... ranges) {
    return in(arg, ImmutableList.copyOf(ranges));
  }

  /** Creates an IN predicate with a list of values.
   *
   * <p>For example,
   *
   * <pre>{@code
   * b.scan("Emps")
   *     .filter(
   *         b.in(b.field("deptno"),
   *             Arrays.asList(b.literal(10), b.literal(20))))
   * }</pre>
   *
   * <p>is equivalent to the SQL
   *
   * <pre>{@code
   * SELECT *
   * FROM Emps
   * WHERE deptno IN (10, 20)
   * }</pre> */
  public RexNode in(RexNode arg, Iterable<? extends RexNode> ranges) {
    return getRexBuilder().makeIn(arg, ImmutableList.copyOf(ranges));
  }

  /** Creates an IN predicate with a sub-query. */
  @Experimental
  public RexSubQuery in(RelNode rel, Iterable<? extends RexNode> nodes) {
    return RexSubQuery.in(rel, ImmutableList.copyOf(nodes));
  }

  /** Creates an IN predicate with a sub-query.
   *
   * <p>For example,
   *
   * <pre>{@code
   * b.scan("Emps")
   *     .filter(
   *         b.in(b.field("deptno"),
   *             b2 -> b2.scan("Depts")
   *                 .filter(
   *                     b2.eq(b2.field("location"), b2.literal("Boston")))
   *                 .project(b.field("deptno"))
   *                 .build()))
   * }</pre>
   *
   * <p>is equivalent to the SQL
   *
   * <pre>{@code
   * SELECT *
   * FROM Emps
   * WHERE deptno IN (SELECT deptno FROM Dept WHERE location = 'Boston')
   * }</pre> */
  @Experimental
  public RexNode in(RexNode arg, Function<RelBuilder, RelNode> f) {
    final RelNode rel = f.apply(this);
    return RexSubQuery.in(rel, ImmutableList.of(arg));
  }

  /** Creates a SOME (or ANY) predicate.
   *
   * <p>For example,
   *
   * <pre>{@code
   * b.scan("Emps")
   *     .filter(
   *         b.some(b.field("commission"),
   *             SqlStdOperatorTable.GREATER_THAN,
   *             b2 -> b2.scan("Emps")
   *                 .filter(
   *                     b2.eq(b2.field("job"), b2.literal("Manager")))
   *                 .project(b2.field("sal"))
   *                 .build()))
   * }</pre>
   *
   * <p>is equivalent to the SQL
   *
   * <pre>{@code
   * SELECT *
   * FROM Emps
   * WHERE commission > SOME (SELECT sal FROM Emps WHERE job = 'Manager')
   * }</pre>
   *
   * <p>or (since {@code SOME} and {@code ANY} are synonyms) the SQL
   *
   * <pre>{@code
   * SELECT *
   * FROM Emps
   * WHERE commission > ANY (SELECT sal FROM Emps WHERE job = 'Manager')
   * }</pre> */
  @Experimental
  public RexSubQuery some(RexNode node, SqlOperator op,
      Function<RelBuilder, RelNode> f) {
    return some_(node, op.kind, f);
  }

  private RexSubQuery some_(RexNode node, SqlKind kind,
      Function<RelBuilder, RelNode> f) {
    final RelNode rel = f.apply(this);
    final SqlQuantifyOperator quantifyOperator =
        SqlStdOperatorTable.some(kind);
    return RexSubQuery.some(rel, ImmutableList.of(node), quantifyOperator);
  }

  /** Creates an ALL predicate.
   *
   * <p>For example,
   *
   * <pre>{@code
   * b.scan("Emps")
   *     .filter(
   *         b.all(b.field("commission"),
   *             SqlStdOperatorTable.GREATER_THAN,
   *             b2 -> b2.scan("Emps")
   *                 .filter(
   *                     b2.eq(b2.field("job"), b2.literal("Manager")))
   *                 .project(b2.field("sal"))
   *                 .build()))
   * }</pre>
   *
   * <p>is equivalent to the SQL
   *
   * <pre>{@code
   * SELECT *
   * FROM Emps
   * WHERE commission > ALL (SELECT sal FROM Emps WHERE job = 'Manager')
   * }</pre>
   *
   * <p>Calcite translates {@code ALL} predicates to {@code NOT SOME}. The
   * following SQL is equivalent to the previous:
   *
   * <pre>{@code
   * SELECT *
   * FROM Emps
   * WHERE NOT (commission <= SOME (SELECT sal FROM Emps WHERE job = 'Manager'))
   * }</pre> */
  @Experimental
  public RexNode all(RexNode node, SqlOperator op,
      Function<RelBuilder, RelNode> f) {
    return not(some_(node, op.kind.negateNullSafe(), f));
  }

  /** Creates an EXISTS predicate.
   *
   * <p>For example,
   *
   * <pre>{@code
   * b.scan("Depts")
   *     .filter(
   *         b.exists(b2 ->
   *             b2.scan("Emps")
   *                 .filter(
   *                     b2.eq(b2.field("job"), b2.literal("Manager")))
   *                 .build()))
   * }</pre>
   *
   * <p>is equivalent to the SQL
   *
   * <pre>{@code
   * SELECT *
   * FROM Depts
   * WHERE EXISTS (SELECT 1 FROM Emps WHERE job = 'Manager')
   * }</pre> */
  @Experimental
  public RexSubQuery exists(Function<RelBuilder, RelNode> f) {
    final RelNode rel = f.apply(this);
    return RexSubQuery.exists(rel);
  }

  /** Creates a UNIQUE predicate.
   *
   * <p>For example,
   *
   * <pre>{@code
   * b.scan("Depts")
   *     .filter(
   *         b.exists(b2 ->
   *             b2.scan("Emps")
   *                 .filter(
   *                     b2.eq(b2.field("job"), b2.literal("Manager")))
   *                 .project(b2.field("deptno")
   *                 .build()))
   * }</pre>
   *
   * <p>is equivalent to the SQL
   *
   * <pre>{@code
   * SELECT *
   * FROM Depts
   * WHERE UNIQUE (SELECT deptno FROM Emps WHERE job = 'Manager')
   * }</pre> */
  @Experimental
  public RexSubQuery unique(Function<RelBuilder, RelNode> f) {
    final RelNode rel = f.apply(this);
    return RexSubQuery.unique(rel);
  }

  /** Creates a scalar sub-query.
   *
   * <p>For example,
   *
   * <pre>{@code
   * b.scan("Depts")
   *     .project(
   *         b.field("deptno")
   *         b.scalarQuery(b2 ->
   *             b2.scan("Emps")
   *                 .aggregate(
   *                     b2.eq(b2.field("job"), b2.literal("Manager")))
   *                 .build()))
   * }</pre>
   *
   * <p>is equivalent to the SQL
   *
   * <pre>{@code
   * SELECT deptno, (SELECT MAX(sal) FROM Emps)
   * FROM Depts
   * }</pre> */
  @Experimental
  public RexSubQuery scalarQuery(Function<RelBuilder, RelNode> f) {
    return RexSubQuery.scalar(f.apply(this));
  }

  /** Creates an ARRAY sub-query.
   *
   * <p>For example,
   *
   * <pre>{@code
   * b.scan("Depts")
   *     .project(
   *         b.field("deptno")
   *         b.arrayQuery(b2 ->
   *             b2.scan("Emps")
   *                 .build()))
   * }</pre>
   *
   * <p>is equivalent to the SQL
   *
   * <pre>{@code
   * SELECT deptno, ARRAY (SELECT * FROM Emps)
   * FROM Depts
   * }</pre> */
  @Experimental
  public RexSubQuery arrayQuery(Function<RelBuilder, RelNode> f) {
    return RexSubQuery.array(f.apply(this));
  }

  /** Creates a MULTISET sub-query.
   *
   * <p>For example,
   *
   * <pre>{@code
   * b.scan("Depts")
   *     .project(
   *         b.field("deptno")
   *         b.multisetQuery(b2 ->
   *             b2.scan("Emps")
   *                 .build()))
   * }</pre>
   *
   * <p>is equivalent to the SQL
   *
   * <pre>{@code
   * SELECT deptno, MULTISET (SELECT * FROM Emps)
   * FROM Depts
   * }</pre> */
  @Experimental
  public RexSubQuery multisetQuery(Function<RelBuilder, RelNode> f) {
    return RexSubQuery.multiset(f.apply(this));
  }

  /** Creates a MAP sub-query.
   *
   * <p>For example,
   *
   * <pre>{@code
   * b.scan("Depts")
   *     .project(
   *         b.field("deptno")
   *         b.multisetQuery(b2 ->
   *             b2.scan("Emps")
   *                 .project(b2.field("empno"), b2.field("job"))
   *                 .build()))
   * }</pre>
   *
   * <p>is equivalent to the SQL
   *
   * <pre>{@code
   * SELECT deptno, MAP (SELECT empno, job FROM Emps)
   * FROM Depts
   * }</pre> */
  @Experimental
  public RexSubQuery mapQuery(Function<RelBuilder, RelNode> f) {
    return RexSubQuery.map(f.apply(this));
  }

  /** Creates an AND. */
  public RexNode and(RexNode... operands) {
    return and(ImmutableList.copyOf(operands));
  }

  /** Creates an AND.
   *
   * <p>Simplifies the expression a little:
   * {@code e AND TRUE} becomes {@code e};
   * {@code e AND e2 AND NOT e} becomes {@code e2}. */
  public RexNode and(Iterable<? extends RexNode> operands) {
    return RexUtil.composeConjunction(getRexBuilder(), operands);
  }

  /** Creates an OR. */
  public RexNode or(RexNode... operands) {
    return or(ImmutableList.copyOf(operands));
  }

  /** Creates an OR. */
  public RexNode or(Iterable<? extends RexNode> operands) {
    return RexUtil.composeDisjunction(cluster.getRexBuilder(), operands);
  }

  /** Creates a NOT. */
  public RexNode not(RexNode operand) {
    return call(SqlStdOperatorTable.NOT, operand);
  }

  /** Creates an {@code =}. */
  public RexNode equals(RexNode operand0, RexNode operand1) {
    return call(SqlStdOperatorTable.EQUALS, operand0, operand1);
  }

  /** Creates a {@code >}. */
  public RexNode greaterThan(RexNode operand0, RexNode operand1) {
    return call(SqlStdOperatorTable.GREATER_THAN, operand0, operand1);
  }

  /** Creates a {@code >=}. */
  public RexNode greaterThanOrEqual(RexNode operand0, RexNode operand1) {
    return call(SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, operand0, operand1);
  }

  /** Creates a {@code <}. */
  public RexNode lessThan(RexNode operand0, RexNode operand1) {
    return call(SqlStdOperatorTable.LESS_THAN, operand0, operand1);
  }

  /** Creates a {@code <=}. */
  public RexNode lessThanOrEqual(RexNode operand0, RexNode operand1) {
    return call(SqlStdOperatorTable.LESS_THAN_OR_EQUAL, operand0, operand1);
  }

  /** Creates a {@code <>}. */
  public RexNode notEquals(RexNode operand0, RexNode operand1) {
    return call(SqlStdOperatorTable.NOT_EQUALS, operand0, operand1);
  }

  /** Creates an expression equivalent to "{@code o0 IS NOT DISTINCT FROM o1}".
   * It is also equivalent to
   * "{@code o0 = o1 OR (o0 IS NULL AND o1 IS NULL)}". */
  public RexNode isNotDistinctFrom(RexNode operand0, RexNode operand1) {
    return RelOptUtil.isDistinctFrom(getRexBuilder(), operand0, operand1, true);
  }

  /** Creates an expression equivalent to {@code o0 IS DISTINCT FROM o1}.
   * It is also equivalent to
   * "{@code NOT (o0 = o1 OR (o0 IS NULL AND o1 IS NULL))}. */
  public RexNode isDistinctFrom(RexNode operand0, RexNode operand1) {
    return RelOptUtil.isDistinctFrom(getRexBuilder(), operand0, operand1, false);
  }

  /** Creates a {@code BETWEEN}. */
  public RexNode between(RexNode arg, RexNode lower, RexNode upper) {
    return getRexBuilder().makeBetween(arg, lower, upper);
  }

  /** Creates ab {@code IS NULL}. */
  public RexNode isNull(RexNode operand) {
    return call(SqlStdOperatorTable.IS_NULL, operand);
  }

  /** Creates an {@code IS NOT NULL}. */
  public RexNode isNotNull(RexNode operand) {
    return call(SqlStdOperatorTable.IS_NOT_NULL, operand);
  }

  /** Creates an expression that casts an expression to a given type. */
  public RexNode cast(RexNode expr, SqlTypeName typeName) {
    final RelDataType type = cluster.getTypeFactory().createSqlType(typeName);
    return cluster.getRexBuilder().makeCast(type, expr);
  }

  /** Creates an expression that casts an expression to a type with a given name
   * and precision or length. */
  public RexNode cast(RexNode expr, SqlTypeName typeName, int precision) {
    final RelDataType type =
        cluster.getTypeFactory().createSqlType(typeName, precision);
    return cluster.getRexBuilder().makeCast(type, expr);
  }

  /** Creates an expression that casts an expression to a type with a given
   * name, precision and scale. */
  public RexNode cast(RexNode expr, SqlTypeName typeName, int precision,
      int scale) {
    final RelDataType type =
        cluster.getTypeFactory().createSqlType(typeName, precision, scale);
    return cluster.getRexBuilder().makeCast(type, expr);
  }

  /**
   * Returns an expression wrapped in an alias.
   *
   * <p>This method is idempotent: If the expression is already wrapped in the
   * correct alias, does nothing; if wrapped in an incorrect alias, removes
   * the incorrect alias and applies the correct alias.
   *
   * @see #project
   */
  public RexNode alias(RexNode expr, @Nullable String alias) {
    final RexNode aliasLiteral = literal(alias);
    switch (expr.getKind()) {
    case AS:
      final RexCall call = (RexCall) expr;
      if (call.operands.get(1).equals(aliasLiteral)) {
        // current alias is correct
        return expr;
      }
      expr = call.operands.get(0);
      // strip current (incorrect) alias, and fall through
    default:
      return call(SqlStdOperatorTable.AS, expr, aliasLiteral);
    }
  }

  /** Converts a sort expression to descending. */
  public RexNode desc(RexNode node) {
    return call(SqlStdOperatorTable.DESC, node);
  }

  /** Converts a sort expression to nulls last. */
  public RexNode nullsLast(RexNode node) {
    return call(SqlStdOperatorTable.NULLS_LAST, node);
  }

  /** Converts a sort expression to nulls first. */
  public RexNode nullsFirst(RexNode node) {
    return call(SqlStdOperatorTable.NULLS_FIRST, node);
  }

  // Methods that create window bounds

  /** Creates an {@code UNBOUNDED PRECEDING} window bound,
   * for use in methods such as {@link OverCall#rowsFrom(RexWindowBound)}
   * and {@link OverCall#rangeBetween(RexWindowBound, RexWindowBound)}. */
  public RexWindowBound unboundedPreceding() {
    return RexWindowBounds.UNBOUNDED_PRECEDING;
  }

  /** Creates a {@code bound PRECEDING} window bound,
   * for use in methods such as {@link OverCall#rowsFrom(RexWindowBound)}
   * and {@link OverCall#rangeBetween(RexWindowBound, RexWindowBound)}. */
  public RexWindowBound preceding(RexNode bound) {
    return RexWindowBounds.preceding(bound);
  }

  /** Creates a {@code CURRENT ROW} window bound,
   * for use in methods such as {@link OverCall#rowsFrom(RexWindowBound)}
   * and {@link OverCall#rangeBetween(RexWindowBound, RexWindowBound)}. */
  public RexWindowBound currentRow() {
    return RexWindowBounds.CURRENT_ROW;
  }

  /** Creates a {@code bound FOLLOWING} window bound,
   * for use in methods such as {@link OverCall#rowsFrom(RexWindowBound)}
   * and {@link OverCall#rangeBetween(RexWindowBound, RexWindowBound)}. */
  public RexWindowBound following(RexNode bound) {
    return RexWindowBounds.following(bound);
  }

  /** Creates an {@code UNBOUNDED FOLLOWING} window bound,
   * for use in methods such as {@link OverCall#rowsFrom(RexWindowBound)}
   * and {@link OverCall#rangeBetween(RexWindowBound, RexWindowBound)}. */
  public RexWindowBound unboundedFollowing() {
    return RexWindowBounds.UNBOUNDED_FOLLOWING;
  }

  // Methods that create group keys and aggregate calls

  /** Creates an empty group key. */
  public GroupKey groupKey() {
    return groupKey(ImmutableList.of());
  }

  /** Creates a group key. */
  public GroupKey groupKey(RexNode... nodes) {
    return groupKey(ImmutableList.copyOf(nodes));
  }

  /** Creates a group key. */
  public GroupKey groupKey(Iterable<? extends RexNode> nodes) {
    return new GroupKeyImpl(ImmutableList.copyOf(nodes), null, null);
  }

  /** Creates a group key with grouping sets. */
  public GroupKey groupKey(Iterable<? extends RexNode> nodes,
      Iterable<? extends Iterable<? extends RexNode>> nodeLists) {
    return groupKey_(nodes, nodeLists);
  }

  // CHECKSTYLE: IGNORE 1
  /** @deprecated Now that indicator is deprecated, use
   * {@link #groupKey(Iterable, Iterable)}, which has the same behavior as
   * calling this method with {@code indicator = false}. */
  @Deprecated // to be removed before 2.0
  public GroupKey groupKey(Iterable<? extends RexNode> nodes, boolean indicator,
      Iterable<? extends Iterable<? extends RexNode>> nodeLists) {
    Aggregate.checkIndicator(indicator);
    return groupKey_(nodes, nodeLists);
  }

  private static GroupKey groupKey_(Iterable<? extends RexNode> nodes,
      Iterable<? extends Iterable<? extends RexNode>> nodeLists) {
    final ImmutableList.Builder<ImmutableList<RexNode>> builder =
        ImmutableList.builder();
    for (Iterable<? extends RexNode> nodeList : nodeLists) {
      builder.add(ImmutableList.copyOf(nodeList));
    }
    return new GroupKeyImpl(ImmutableList.copyOf(nodes), builder.build(), null);
  }

  /** Creates a group key of fields identified by ordinal. */
  public GroupKey groupKey(int... fieldOrdinals) {
    return groupKey(fields(ImmutableIntList.of(fieldOrdinals)));
  }

  /** Creates a group key of fields identified by name. */
  public GroupKey groupKey(String... fieldNames) {
    return groupKey(fields(ImmutableList.copyOf(fieldNames)));
  }

  /** Creates a group key, identified by field positions
   * in the underlying relational expression.
   *
   * <p>This method of creating a group key does not allow you to group on new
   * expressions, only column projections, but is efficient, especially when you
   * are coming from an existing {@link Aggregate}. */
  public GroupKey groupKey(ImmutableBitSet groupSet) {
    return groupKey_(groupSet, ImmutableList.of(groupSet));
  }

  /** Creates a group key with grouping sets, both identified by field positions
   * in the underlying relational expression.
   *
   * <p>This method of creating a group key does not allow you to group on new
   * expressions, only column projections, but is efficient, especially when you
   * are coming from an existing {@link Aggregate}.
   *
   * <p>It is possible for {@code groupSet} to be strict superset of all
   * {@code groupSets}. For example, in the pseudo SQL
   *
   * <pre>{@code
   * GROUP BY 0, 1, 2
   * GROUPING SETS ((0, 1), 0)
   * }</pre>
   *
   * <p>column 2 does not appear in either grouping set. This is not valid SQL.
   * We can approximate in actual SQL by adding an extra grouping set and
   * filtering out using {@code HAVING}, as follows:
   *
   * <pre>{@code
   * GROUP BY GROUPING SETS ((0, 1, 2), (0, 1), 0)
   * HAVING GROUPING_ID(0, 1, 2) <> 0
   * }</pre>
   */
  public GroupKey groupKey(ImmutableBitSet groupSet,
      Iterable<? extends ImmutableBitSet> groupSets) {
    return groupKey_(groupSet, ImmutableList.copyOf(groupSets));
  }

  // CHECKSTYLE: IGNORE 1
  /** @deprecated Use {@link #groupKey(ImmutableBitSet, Iterable)}. */
  @Deprecated // to be removed before 2.0
  public GroupKey groupKey(ImmutableBitSet groupSet, boolean indicator,
      @Nullable ImmutableList<ImmutableBitSet> groupSets) {
    Aggregate.checkIndicator(indicator);
    return groupKey_(groupSet, groupSets == null
        ? ImmutableList.of(groupSet) : ImmutableList.copyOf(groupSets));
  }

  private GroupKey groupKey_(ImmutableBitSet groupSet,
      ImmutableList<ImmutableBitSet> groupSets) {
    if (groupSet.length() > peek().getRowType().getFieldCount()) {
      throw new IllegalArgumentException("out of bounds: " + groupSet);
    }
    requireNonNull(groupSets, "groupSets");
    final ImmutableList<RexNode> nodes = fields(groupSet);
    return groupKey_(nodes, Util.transform(groupSets, this::fields));
  }

  @Deprecated // to be removed before 2.0
  public AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct,
      RexNode filter, @Nullable String alias, RexNode... operands) {
    return aggregateCall(aggFunction, distinct, false, false, filter, null,
        ImmutableList.of(), alias, ImmutableList.copyOf(operands));
  }

  @Deprecated // to be removed before 2.0
  public AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct,
      boolean approximate, RexNode filter, @Nullable String alias, RexNode... operands) {
    return aggregateCall(aggFunction, distinct, approximate, false, filter,
        null, ImmutableList.of(), alias, ImmutableList.copyOf(operands));
  }

  @Deprecated // to be removed before 2.0
  public AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct,
      RexNode filter, @Nullable String alias, Iterable<? extends RexNode> operands) {
    return aggregateCall(aggFunction, distinct, false, false, filter, null,
        ImmutableList.of(), alias, ImmutableList.copyOf(operands));
  }

  @Deprecated // to be removed before 2.0
  public AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct,
      boolean approximate, RexNode filter, @Nullable String alias,
      Iterable<? extends RexNode> operands) {
    return aggregateCall(aggFunction, distinct, approximate, false, filter,
        null, ImmutableList.of(), alias, ImmutableList.copyOf(operands));
  }

  /** Creates a call to an aggregate function.
   *
   * <p>To add other operands, apply
   * {@link AggCall#distinct()},
   * {@link AggCall#approximate(boolean)},
   * {@link AggCall#filter(RexNode...)},
   * {@link AggCall#sort},
   * {@link AggCall#as} to the result. */
  public AggCall aggregateCall(SqlAggFunction aggFunction,
      Iterable<? extends RexNode> operands) {
    return aggregateCall(aggFunction, false, false, false, null, null,
        ImmutableList.of(), null, ImmutableList.copyOf(operands));
  }

  /** Creates a call to an aggregate function.
   *
   * <p>To add other operands, apply
   * {@link AggCall#distinct()},
   * {@link AggCall#approximate(boolean)},
   * {@link AggCall#filter(RexNode...)},
   * {@link AggCall#sort},
   * {@link AggCall#as} to the result. */
  public AggCall aggregateCall(SqlAggFunction aggFunction,
      RexNode... operands) {
    return aggregateCall(aggFunction, false, false, false, null, null,
        ImmutableList.of(), null, ImmutableList.copyOf(operands));
  }

  /** Creates a call to an aggregate function as a copy of an
   * {@link AggregateCall}. */
  public AggCall aggregateCall(AggregateCall a) {
    return aggregateCall(a.getAggregation(), a.isDistinct(), a.isApproximate(),
        a.ignoreNulls(), a.filterArg < 0 ? null : field(a.filterArg),
        a.distinctKeys == null ? null : fields(a.distinctKeys),
        fields(a.collation), a.name, fields(a.getArgList()));
  }

  /** Creates a call to an aggregate function as a copy of an
   * {@link AggregateCall}, applying a mapping. */
  public AggCall aggregateCall(AggregateCall a, Mapping mapping) {
    return aggregateCall(a.getAggregation(), a.isDistinct(), a.isApproximate(),
        a.ignoreNulls(),
        a.filterArg < 0 ? null : field(Mappings.apply(mapping, a.filterArg)),
        a.distinctKeys == null ? null
            : fields(Mappings.apply(mapping, a.distinctKeys)),
        fields(RexUtil.apply(mapping, a.collation)), a.name,
        fields(Mappings.apply2(mapping, a.getArgList())));
  }

  /** Creates a call to an aggregate function with all applicable operands. */
  protected AggCall aggregateCall(SqlAggFunction aggFunction, boolean distinct,
      boolean approximate, boolean ignoreNulls, @Nullable RexNode filter,
      @Nullable ImmutableList<RexNode> distinctKeys,
      ImmutableList<RexNode> orderKeys,
      @Nullable String alias, ImmutableList<RexNode> operands) {
    return new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls,
        filter, alias, operands, distinctKeys, orderKeys);
  }

  /** Creates a call to the {@code COUNT} aggregate function. */
  public AggCall count(RexNode... operands) {
    return count(false, null, operands);
  }

  /** Creates a call to the {@code COUNT} aggregate function. */
  public AggCall count(Iterable<? extends RexNode> operands) {
    return count(false, null, operands);
  }

  /** Creates a call to the {@code COUNT} aggregate function,
   * optionally distinct and with an alias. */
  public AggCall count(boolean distinct, @Nullable String alias, RexNode... operands) {
    return aggregateCall(SqlStdOperatorTable.COUNT, distinct, false, false, null,
        null, ImmutableList.of(), alias, ImmutableList.copyOf(operands));
  }

  /** Creates a call to the {@code COUNT} aggregate function,
   * optionally distinct and with an alias. */
  public AggCall count(boolean distinct, @Nullable String alias,
      Iterable<? extends RexNode> operands) {
    return aggregateCall(SqlStdOperatorTable.COUNT, distinct, false, false, null,
        null, ImmutableList.of(), alias, ImmutableList.copyOf(operands));
  }

  /** Creates a call to the {@code COUNT(*)} aggregate function. */
  public AggCall countStar(@Nullable String alias) {
    return count(false, alias);
  }

  /** Creates a call to the {@code SUM} aggregate function. */
  public AggCall sum(RexNode operand) {
    return sum(false, null, operand);
  }

  /** Creates a call to the {@code SUM} aggregate function,
   * optionally distinct and with an alias. */
  public AggCall sum(boolean distinct, @Nullable String alias, RexNode operand) {
    return aggregateCall(SqlStdOperatorTable.SUM, distinct, false, false, null,
        null, ImmutableList.of(), alias, ImmutableList.of(operand));
  }

  /** Creates a call to the {@code AVG} aggregate function. */
  public AggCall avg(RexNode operand) {
    return avg(false, null, operand);
  }

  /** Creates a call to the {@code AVG} aggregate function,
   * optionally distinct and with an alias. */
  public AggCall avg(boolean distinct, @Nullable String alias, RexNode operand) {
    return aggregateCall(SqlStdOperatorTable.AVG, distinct, false, false, null,
        null, ImmutableList.of(), alias, ImmutableList.of(operand));
  }

  /** Creates a call to the {@code MIN} aggregate function. */
  public AggCall min(RexNode operand) {
    return min(null, operand);
  }

  /** Creates a call to the {@code MIN} aggregate function,
   * optionally with an alias. */
  public AggCall min(@Nullable String alias, RexNode operand) {
    return aggregateCall(SqlStdOperatorTable.MIN, false, false, false, null,
        null, ImmutableList.of(), alias, ImmutableList.of(operand));
  }

  /** Creates a call to the {@code MAX} aggregate function,
   * optionally with an alias. */
  public AggCall max(RexNode operand) {
    return max(null, operand);
  }

  /** Creates a call to the {@code MAX} aggregate function. */
  public AggCall max(@Nullable String alias, RexNode operand) {
    return aggregateCall(SqlStdOperatorTable.MAX, false, false, false, null,
        null, ImmutableList.of(), alias, ImmutableList.of(operand));
  }

  // Methods for patterns

  /**
   * Creates a reference to a given field of the pattern.
   *
   * @param alpha the pattern name
   * @param type Type of field
   * @param i Ordinal of field
   * @return Reference to field of pattern
   */
  public RexNode patternField(String alpha, RelDataType type, int i) {
    return getRexBuilder().makePatternFieldRef(alpha, type, i);
  }

  /** Creates a call that concatenates patterns;
   * for use in {@link #match}. */
  public RexNode patternConcat(Iterable<? extends RexNode> nodes) {
    final ImmutableList<RexNode> list = ImmutableList.copyOf(nodes);
    if (list.size() > 2) {
      // Convert into binary calls
      return patternConcat(patternConcat(Util.skipLast(list)), Util.last(list));
    }
    final RelDataType t = getTypeFactory().createSqlType(SqlTypeName.NULL);
    return getRexBuilder().makeCall(t, SqlStdOperatorTable.PATTERN_CONCAT,
        list);
  }

  /** Creates a call that concatenates patterns;
   * for use in {@link #match}. */
  public RexNode patternConcat(RexNode... nodes) {
    return patternConcat(ImmutableList.copyOf(nodes));
  }

  /** Creates a call that creates alternate patterns;
   * for use in {@link #match}. */
  public RexNode patternAlter(Iterable<? extends RexNode> nodes) {
    final RelDataType t = getTypeFactory().createSqlType(SqlTypeName.NULL);
    return getRexBuilder().makeCall(t, SqlStdOperatorTable.PATTERN_ALTER,
        ImmutableList.copyOf(nodes));
  }

  /** Creates a call that creates alternate patterns;
   * for use in {@link #match}. */
  public RexNode patternAlter(RexNode... nodes) {
    return patternAlter(ImmutableList.copyOf(nodes));
  }

  /** Creates a call that creates quantify patterns;
   * for use in {@link #match}. */
  public RexNode patternQuantify(Iterable<? extends RexNode> nodes) {
    final RelDataType t = getTypeFactory().createSqlType(SqlTypeName.NULL);
    return getRexBuilder().makeCall(t, SqlStdOperatorTable.PATTERN_QUANTIFIER,
        ImmutableList.copyOf(nodes));
  }

  /** Creates a call that creates quantify patterns;
   * for use in {@link #match}. */
  public RexNode patternQuantify(RexNode... nodes) {
    return patternQuantify(ImmutableList.copyOf(nodes));
  }

  /** Creates a call that creates permute patterns;
   * for use in {@link #match}. */
  public RexNode patternPermute(Iterable<? extends RexNode> nodes) {
    final RelDataType t = getTypeFactory().createSqlType(SqlTypeName.NULL);
    return getRexBuilder().makeCall(t, SqlStdOperatorTable.PATTERN_PERMUTE,
        ImmutableList.copyOf(nodes));
  }

  /** Creates a call that creates permute patterns;
   * for use in {@link #match}. */
  public RexNode patternPermute(RexNode... nodes) {
    return patternPermute(ImmutableList.copyOf(nodes));
  }

  /** Creates a call that creates an exclude pattern;
   * for use in {@link #match}. */
  public RexNode patternExclude(RexNode node) {
    final RelDataType t = getTypeFactory().createSqlType(SqlTypeName.NULL);
    return getRexBuilder().makeCall(t, SqlStdOperatorTable.PATTERN_EXCLUDE,
        ImmutableList.of(node));
  }

  // Methods that create relational expressions

  /** Creates a {@link TableScan} of the table
   * with a given name.
   *
   * <p>Throws if the table does not exist.
   *
   * <p>Returns this builder.
   *
   * @param tableNames Name of table (can optionally be qualified)
   */
  public RelBuilder scan(Iterable<String> tableNames) {
    final List<String> names = ImmutableList.copyOf(tableNames);
    requireNonNull(relOptSchema, "relOptSchema");
    final RelOptTable relOptTable = relOptSchema.getTableForMember(names);
    if (relOptTable == null) {
      throw RESOURCE.tableNotFound(String.join(".", names)).ex();
    }
    final RelNode scan =
        struct.scanFactory.createScan(
            ViewExpanders.toRelContext(viewExpander, cluster),
            relOptTable);
    push(scan);
    rename(relOptTable.getRowType().getFieldNames());

    // When the node is not a TableScan but from expansion,
    // we need to explicitly add the alias.
    if (!(scan instanceof TableScan)) {
      as(Util.last(ImmutableList.copyOf(tableNames)));
    }
    return this;
  }

  /** Creates a {@link TableScan} of the table
   * with a given name.
   *
   * <p>Throws if the table does not exist.
   *
   * <p>Returns this builder.
   *
   * @param tableNames Name of table (can optionally be qualified)
   */
  public RelBuilder scan(String... tableNames) {
    return scan(ImmutableList.copyOf(tableNames));
  }

  /** Creates a {@link Snapshot} of a given snapshot period.
   *
   * <p>Returns this builder.
   *
   * @param period Name of table (can optionally be qualified)
   */
  public RelBuilder snapshot(RexNode period) {
    final Frame frame = stack.pop();
    final RelNode snapshot =
        struct.snapshotFactory.createSnapshot(frame.rel, period);
    stack.push(new Frame(snapshot, frame.fields));
    return this;
  }


  /**
   * Gets column mappings of the operator.
   *
   * @param op operator instance
   * @return column mappings associated with this function
   */
  private static @Nullable Set<RelColumnMapping> getColumnMappings(SqlOperator op) {
    SqlReturnTypeInference inference = op.getReturnTypeInference();
    if (inference instanceof TableFunctionReturnTypeInference) {
      return ((TableFunctionReturnTypeInference) inference).getColumnMappings();
    } else {
      return null;
    }
  }

  /**
   * Creates a RexCall to the {@code CURSOR} function by ordinal.
   *
   * @param inputCount Number of inputs
   * @param ordinal The reference to the relational input
   * @return RexCall to CURSOR function
   */
  public RexNode cursor(int inputCount, int ordinal) {
    if (inputCount <= ordinal || ordinal < 0) {
      throw new IllegalArgumentException("bad input count or ordinal");
    }
    // Refer to the "ordinal"th input as if it were a field
    // (because that's how things are laid out inside a TableFunctionScan)
    final RelNode input = peek(inputCount, ordinal);
    return call(SqlStdOperatorTable.CURSOR,
        getRexBuilder().makeInputRef(input.getRowType(), ordinal));
  }

  /** Creates a {@link TableFunctionScan}. */
  public RelBuilder functionScan(SqlOperator operator,
      int inputCount, RexNode... operands) {
    return functionScan(operator, inputCount, ImmutableList.copyOf(operands));
  }

  /** Creates a {@link TableFunctionScan}. */
  public RelBuilder functionScan(SqlOperator operator,
      int inputCount, Iterable<? extends RexNode> operands) {
    if (inputCount < 0 || inputCount > stack.size()) {
      throw new IllegalArgumentException("bad input count");
    }

    // Gets inputs.
    final List<RelNode> inputs = new ArrayList<>();
    for (int i = 0; i < inputCount; i++) {
      inputs.add(0, build());
    }

    final RexCall call = call(operator, ImmutableList.copyOf(operands));
    final RelNode functionScan =
        struct.tableFunctionScanFactory.createTableFunctionScan(cluster,
            inputs, call, null, getColumnMappings(operator));
    push(functionScan);
    return this;
  }

  /** Creates a {@link Filter} of an array of
   * predicates.
   *
   * <p>The predicates are combined using AND,
   * and optimized in a similar way to the {@link #and} method.
   * If the result is TRUE no filter is created. */
  public RelBuilder filter(RexNode... predicates) {
    return filter(ImmutableSet.of(), ImmutableList.copyOf(predicates));
  }

  /** Creates a {@link Filter} of a list of
   * predicates.
   *
   * <p>The predicates are combined using AND,
   * and optimized in a similar way to the {@link #and} method.
   * If the result is TRUE no filter is created. */
  public RelBuilder filter(Iterable<? extends RexNode> predicates) {
    return filter(ImmutableSet.of(), predicates);
  }

  /** Creates a {@link Filter} of a list of correlation variables
   * and an array of predicates.
   *
   * <p>The predicates are combined using AND,
   * and optimized in a similar way to the {@link #and} method.
   * If the result is TRUE no filter is created. */
  public RelBuilder filter(Iterable<CorrelationId> variablesSet,
      RexNode... predicates) {
    return filter(variablesSet, ImmutableList.copyOf(predicates));
  }

  /**
   * Creates a {@link Filter} of a list of correlation variables
   * and a list of predicates.
   *
   * <p>The predicates are combined using AND,
   * and optimized in a similar way to the {@link #and} method.
   * If simplification is on and the result is TRUE, no filter is created. */
  public RelBuilder filter(Iterable<CorrelationId> variablesSet,
      Iterable<? extends RexNode> predicates) {
    final RexNode conjunctionPredicates;
    if (config.simplify()) {
      conjunctionPredicates = simplifier.simplifyFilterPredicates(predicates);
    } else {
      conjunctionPredicates =
          RexUtil.composeConjunction(simplifier.rexBuilder, predicates);
    }

    if (conjunctionPredicates == null || conjunctionPredicates.isAlwaysFalse()) {
      return empty();
    }
    if (conjunctionPredicates.isAlwaysTrue()) {
      return this;
    }

    final Frame frame = stack.pop();
    final RelNode filter =
        struct.filterFactory.createFilter(frame.rel,
            conjunctionPredicates, ImmutableSet.copyOf(variablesSet));
    stack.push(new Frame(filter, frame.fields));
    return this;
  }

  /** Creates a {@link Project} of the given
   * expressions. */
  public RelBuilder project(RexNode... nodes) {
    return project(ImmutableList.copyOf(nodes));
  }

  /** Creates a {@link Project} of the given list
   * of expressions.
   *
   * <p>Infers names as would {@link #project(Iterable, Iterable)} if all
   * suggested names were null.
   *
   * @param nodes Expressions
   */
  public RelBuilder project(Iterable<? extends RexNode> nodes) {
    return project(nodes, ImmutableList.of());
  }

  /** Creates a {@link Project} of the given list
   * of expressions and field names.
   *
   * @param nodes Expressions
   * @param fieldNames field names for expressions
   */
  public RelBuilder project(Iterable<? extends RexNode> nodes,
      Iterable<? extends @Nullable String> fieldNames) {
    return project(nodes, fieldNames, false);
  }

  /** Creates a {@link Project} of the given list
   * of expressions, using the given names.
   *
   * <p>Names are deduced as follows:
   * <ul>
   *   <li>If the length of {@code fieldNames} is greater than the index of
   *     the current entry in {@code nodes}, and the entry in
   *     {@code fieldNames} is not null, uses it; otherwise
   *   <li>If an expression projects an input field,
   *     or is a cast an input field,
   *     uses the input field name; otherwise
   *   <li>If an expression is a call to
   *     {@link SqlStdOperatorTable#AS}
   *     (see {@link #alias}), removes the call but uses the intended alias.
   * </ul>
   *
   * <p>After the field names have been inferred, makes the
   * field names unique by appending numeric suffixes.
   *
   * @param nodes Expressions
   * @param fieldNames Suggested field names
   * @param force create project even if it is identity
   */
  public RelBuilder project(Iterable<? extends RexNode> nodes,
      Iterable<? extends @Nullable String> fieldNames, boolean force) {
    return project(nodes, fieldNames, force, ImmutableSet.of());
  }

  /**
   * The same with {@link #project(Iterable, Iterable, boolean)}, with additional
   * variablesSet param.
   *
   * @param nodes Expressions
   * @param fieldNames Suggested field names
   * @param force create project even if it is identity
   * @param variablesSet Correlating variables that are set when reading a row
   *                     from the input, and which may be referenced from the
   *                     projection expressions
   */
  public RelBuilder project(Iterable<? extends RexNode> nodes,
      Iterable<? extends @Nullable String> fieldNames, boolean force,
      Iterable<CorrelationId> variablesSet) {
    return project_(nodes, fieldNames, ImmutableList.of(), force, variablesSet);
  }

  /** Creates a {@link Project} of all original fields, plus the given
   * expressions. */
  public RelBuilder projectPlus(RexNode... nodes) {
    return projectPlus(ImmutableList.copyOf(nodes));
  }

  /** Creates a {@link Project} of all original fields, plus the given list of
   * expressions. */
  public RelBuilder projectPlus(Iterable<RexNode> nodes) {
    return project(Iterables.concat(fields(), nodes));
  }

  /** Creates a {@link Project} of all original fields, except the given
   * expressions.
   *
   * @throws IllegalArgumentException if the given expressions contain duplicates
   *    or there is an expression that does not match an existing field
   */
  public RelBuilder projectExcept(RexNode... expressions) {
    return projectExcept(ImmutableList.copyOf(expressions));
  }

  /** Creates a {@link Project} of all original fields, except the given list of
   * expressions.
   *
   * @throws IllegalArgumentException if the given expressions contain duplicates
   *    or there is an expression that does not match an existing field
   */
  public RelBuilder projectExcept(Iterable<RexNode> expressions) {
    List<RexNode> allExpressions = new ArrayList<>(fields());
    Set<RexNode> excludeExpressions = new HashSet<>();
    for (RexNode excludeExp : expressions) {
      if (!excludeExpressions.add(excludeExp)) {
        throw new IllegalArgumentException(
          "Input list contains duplicates. Expression " + excludeExp + " exists multiple times.");
      }
      if (!allExpressions.remove(excludeExp)) {
        throw new IllegalArgumentException("Expression " + excludeExp.toString() + " not found.");
      }
    }
    return this.project(allExpressions);
  }

  /** Creates a {@link Project} of the given list
   * of expressions, using the given names.
   *
   * <p>Names are deduced as follows:
   * <ul>
   *   <li>If the length of {@code fieldNames} is greater than the index of
   *     the current entry in {@code nodes}, and the entry in
   *     {@code fieldNames} is not null, uses it; otherwise
   *   <li>If an expression projects an input field,
   *     or is a cast an input field,
   *     uses the input field name; otherwise
   *   <li>If an expression is a call to
   *     {@link SqlStdOperatorTable#AS}
   *     (see {@link #alias}), removes the call but uses the intended alias.
   * </ul>
   *
   * <p>After the field names have been inferred, makes the
   * field names unique by appending numeric suffixes.
   *
   * @param nodes Expressions
   * @param fieldNames Suggested field names
   * @param hints Hints
   * @param force create project even if it is identity
   */
  private RelBuilder project_(
      Iterable<? extends RexNode> nodes,
      Iterable<? extends @Nullable String> fieldNames,
      Iterable<RelHint> hints,
      boolean force,
      Iterable<CorrelationId> variablesSet) {
    final Frame frame = requireNonNull(peek_(), "frame stack is empty");
    final RelDataType inputRowType = frame.rel.getRowType();
    final List<RexNode> nodeList = Lists.newArrayList(nodes);
    final Set<CorrelationId> variables = ImmutableSet.copyOf(variablesSet);

    // Perform a quick check for identity. We'll do a deeper check
    // later when we've derived column names.
    if (!force && Iterables.isEmpty(fieldNames)
        && RexUtil.isIdentity(nodeList, inputRowType)) {
      return this;
    }

    final List<@Nullable String> fieldNameList = Lists.newArrayList(fieldNames);
    while (fieldNameList.size() < nodeList.size()) {
      fieldNameList.add(null);
    }

    // Do not merge projection when top projection has correlation variables
    bloat:
    if (frame.rel instanceof Project
        && config.bloat() >= 0
        && variables.isEmpty()) {
      final Project project = (Project) frame.rel;
      // Populate field names. If the upper expression is an input ref and does
      // not have a recommended name, use the name of the underlying field.
      for (int i = 0; i < fieldNameList.size(); i++) {
        if (fieldNameList.get(i) == null) {
          final RexNode node = nodeList.get(i);
          if (node instanceof RexInputRef) {
            final RexInputRef ref = (RexInputRef) node;
            fieldNameList.set(i,
                project.getRowType().getFieldNames().get(ref.getIndex()));
          }
        }
      }
      final List<RexNode> newNodes =
          RelOptUtil.pushPastProjectUnlessBloat(nodeList, project,
              config.bloat());
      if (newNodes == null) {
        // The merged expression is more complex than the input expressions.
        // Do not merge.
        break bloat;
      }

      // Carefully build a list of fields, so that table aliases from the input
      // can be seen for fields that are based on a RexInputRef.
      final Frame frame1 = stack.pop();
      final List<Field> fields = new ArrayList<>();
      for (RelDataTypeField f
          : project.getInput().getRowType().getFieldList()) {
        fields.add(new Field(ImmutableSet.of(), f));
      }
      for (Pair<RexNode, Field> pair
          : Pair.zip(project.getProjects(), frame1.fields)) {
        switch (pair.left.getKind()) {
        case INPUT_REF:
          final int i = ((RexInputRef) pair.left).getIndex();
          final Field field = fields.get(i);
          final ImmutableSet<String> aliases = pair.right.left;
          fields.set(i, new Field(aliases, field.right));
          break;
        default:
          break;
        }
      }
      stack.push(new Frame(project.getInput(), ImmutableList.copyOf(fields)));
      final ImmutableSet.Builder<RelHint> mergedHints = ImmutableSet.builder();
      mergedHints.addAll(project.getHints());
      mergedHints.addAll(hints);
      // Keep bottom projection's variablesSet.
      return project_(newNodes, fieldNameList, mergedHints.build(), force,
          ImmutableSet.copyOf(project.getVariablesSet()));
    }

    // Simplify expressions.
    if (config.simplify()) {
      for (int i = 0; i < nodeList.size(); i++) {
        nodeList.set(i, simplifier.simplifyPreservingType(nodeList.get(i)));
      }
    }

    // Replace null names with generated aliases.
    for (int i = 0; i < fieldNameList.size(); i++) {
      if (fieldNameList.get(i) == null) {
        fieldNameList.set(i, inferAlias(nodeList, nodeList.get(i), i));
      }
    }

    final ImmutableList.Builder<Field> fields = ImmutableList.builder();
    final Set<String> uniqueNameList =
        getTypeFactory().getTypeSystem().isSchemaCaseSensitive()
        ? new HashSet<>()
        : new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
    // calculate final names and build field list
    for (int i = 0; i < fieldNameList.size(); ++i) {
      final RexNode node = nodeList.get(i);
      String name = fieldNameList.get(i);
      String originalName = name;
      Field field;
      if (name == null || uniqueNameList.contains(name)) {
        int j = 0;
        if (name == null) {
          j = i;
        }
        do {
          name = SqlValidatorUtil.F_SUGGESTER.apply(originalName, j, j++);
        } while (uniqueNameList.contains(name));
        fieldNameList.set(i, name);
      }
      RelDataTypeField fieldType =
          new RelDataTypeFieldImpl(name, i, node.getType());
      switch (node.getKind()) {
      case INPUT_REF:
        // preserve rel aliases for INPUT_REF fields
        final int index = ((RexInputRef) node).getIndex();
        field = new Field(frame.fields.get(index).left, fieldType);
        break;
      default:
        field = new Field(ImmutableSet.of(), fieldType);
        break;
      }
      uniqueNameList.add(name);
      fields.add(field);
    }
    if (!force && RexUtil.isIdentity(nodeList, inputRowType)) {
      if (fieldNameList.equals(inputRowType.getFieldNames())) {
        // Do not create an identity project if it does not rename any fields
        return this;
      } else {
        // create "virtual" row type for project only rename fields
        stack.pop();
        // Ignore the hints.
        stack.push(new Frame(frame.rel, fields.build()));
      }
      return this;
    }

    // If the expressions are all literals, and the input is a Values with N
    // rows, replace with a Values with same tuple N times.
    if (config.simplifyValues()
        && frame.rel instanceof Values
        && nodeList.stream().allMatch(e -> e instanceof RexLiteral)) {
      final Values values = (Values) build();
      final RelDataTypeFactory.Builder typeBuilder = getTypeFactory().builder();
      Pair.forEach(fieldNameList, nodeList, (name, expr) ->
          typeBuilder.add(requireNonNull(name, "name"), expr.getType()));
      @SuppressWarnings({"unchecked", "rawtypes"})
      final List<RexLiteral> tuple = (List<RexLiteral>) (List) nodeList;
      return values(Collections.nCopies(values.tuples.size(), tuple),
          typeBuilder.build());
    }

    final RelNode project =
        struct.projectFactory.createProject(frame.rel,
            ImmutableList.copyOf(hints),
            ImmutableList.copyOf(nodeList),
            fieldNameList,
            variables);
    stack.pop();
    stack.push(new Frame(project, fields.build()));
    return this;
  }

  /** Creates a {@link Project} of the given
   * expressions and field names, and optionally optimizing.
   *
   * <p>If {@code fieldNames} is null, or if a particular entry in
   * {@code fieldNames} is null, derives field names from the input
   * expressions.
   *
   * <p>If {@code force} is false,
   * and the input is a {@code Project},
   * and the expressions  make the trivial projection ($0, $1, ...),
   * modifies the input.
   *
   * @param nodes       Expressions
   * @param fieldNames  Suggested field names, or null to generate
   * @param force       Whether to create a renaming Project if the
   *                    projections are trivial
   */
  public RelBuilder projectNamed(Iterable<? extends RexNode> nodes,
      @Nullable Iterable<? extends @Nullable String> fieldNames, boolean force) {
    return projectNamed(nodes, fieldNames, force, ImmutableSet.of());
  }

  /** Creates a {@link Project} of the given
   * expressions and field names, and optionally optimizing.
   *
   * <p>If {@code fieldNames} is null, or if a particular entry in
   * {@code fieldNames} is null, derives field names from the input
   * expressions.
   *
   * <p>If {@code force} is false,
   * and the input is a {@code Project},
   * and the expressions  make the trivial projection ($0, $1, ...),
   * modifies the input.
   *
   * @param nodes       Expressions
   * @param fieldNames  Suggested field names, or null to generate
   * @param force       Whether to create a renaming Project if the
   *                    projections are trivial
   * @param variablesSet Correlating variables that are set when reading a row
   *                     from the input, and which may be referenced from the
   *                     projection expressions
   */
  public RelBuilder projectNamed(Iterable<? extends RexNode> nodes,
      @Nullable Iterable<? extends @Nullable String> fieldNames, boolean force,
      Iterable<CorrelationId> variablesSet) {
    @SuppressWarnings("unchecked") final List<? extends RexNode> nodeList =
        nodes instanceof List ? (List) nodes : ImmutableList.copyOf(nodes);
    final List<@Nullable String> fieldNameList =
        fieldNames == null ? null
          : fieldNames instanceof List ? (List<@Nullable String>) fieldNames
          : ImmutableNullableList.copyOf(fieldNames);
    final RelNode input = peek();
    final RelDataType rowType =
        RexUtil.createStructType(cluster.getTypeFactory(), nodeList,
            fieldNameList, SqlValidatorUtil.F_SUGGESTER);
    if (!force
        && RexUtil.isIdentity(nodeList, input.getRowType())) {
      if (input instanceof Project && fieldNames != null) {
        // Rename columns of child projection if desired field names are given.
        final Frame frame = stack.pop();
        final Project childProject = (Project) frame.rel;
        final Project newInput = childProject.copy(childProject.getTraitSet(),
            childProject.getInput(), childProject.getProjects(), rowType);
        stack.push(new Frame(newInput.attachHints(childProject.getHints()), frame.fields));
      }
      if (input instanceof Values && fieldNameList != null) {
        // Rename columns of child values if desired field names are given.
        final Frame frame = stack.pop();
        final Values values = (Values) frame.rel;
        final RelDataTypeFactory.Builder typeBuilder =
            getTypeFactory().builder();
        Pair.forEach(fieldNameList, rowType.getFieldList(), (name, field) ->
            typeBuilder.add(requireNonNull(name, "name"), field.getType()));
        final RelDataType newRowType = typeBuilder.build();
        final RelNode newValues =
            struct.valuesFactory.createValues(cluster, newRowType,
                values.tuples);
        stack.push(new Frame(newValues, frame.fields));
      }
    } else {
      project(nodeList, rowType.getFieldNames(), force, variablesSet);
    }
    return this;
  }

  /**
   * Creates an {@link Uncollect} with given item aliases.
   *
   * @param itemAliases   Operand item aliases, never null
   * @param withOrdinality If {@code withOrdinality}, the output contains an extra
   * {@code ORDINALITY} column
   */
  public RelBuilder uncollect(List<String> itemAliases, boolean withOrdinality) {
    Frame frame = stack.pop();
    stack.push(
        new Frame(
          new Uncollect(
            cluster,
            cluster.traitSetOf(Convention.NONE),
            frame.rel,
            withOrdinality,
            requireNonNull(itemAliases, "itemAliases"))));
    return this;
  }

  /** Ensures that the field names match those given.
   *
   * <p>If all fields have the same name, adds nothing;
   * if any fields do not have the same name, adds a {@link Project}.
   *
   * <p>Note that the names can be short-lived. Other {@code RelBuilder}
   * operations make no guarantees about the field names of the rows they
   * produce.
   *
   * @param fieldNames List of desired field names; may contain null values or
   * have fewer fields than the current row type
   */
  public RelBuilder rename(List<? extends @Nullable String> fieldNames) {
    final List<String> oldFieldNames = peek().getRowType().getFieldNames();
    Preconditions.checkArgument(fieldNames.size() <= oldFieldNames.size(),
        "More names than fields");
    final List<String> newFieldNames = new ArrayList<>(oldFieldNames);
    for (int i = 0; i < fieldNames.size(); i++) {
      final String s = fieldNames.get(i);
      if (s != null) {
        newFieldNames.set(i, s);
      }
    }
    if (oldFieldNames.equals(newFieldNames)) {
      return this;
    }
    if (peek() instanceof Values) {
      // Special treatment for VALUES. Re-build it rather than add a project.
      final Values v = (Values) build();
      final RelDataTypeFactory.Builder b = getTypeFactory().builder();
      for (Pair<String, RelDataTypeField> p
          : Pair.zip(newFieldNames, v.getRowType().getFieldList())) {
        b.add(p.left, p.right.getType());
      }
      return values(v.tuples, b.build());
    }

    return project(fields(), newFieldNames, true);
  }

  /** Infers the alias of an expression.
   *
   * <p>If the expression was created by {@link #alias}, replaces the expression
   * in the project list.
   */
  private @Nullable String inferAlias(List<RexNode> exprList, RexNode expr, int i) {
    switch (expr.getKind()) {
    case INPUT_REF:
      final RexInputRef ref = (RexInputRef) expr;
      return requireNonNull(stack.peek(), "empty frame stack")
          .fields.get(ref.getIndex()).getValue().getName();
    case CAST:
      return inferAlias(exprList, ((RexCall) expr).getOperands().get(0), -1);
    case AS:
      final RexCall call = (RexCall) expr;
      if (i >= 0) {
        exprList.set(i, call.getOperands().get(0));
      }
      NlsString value = (NlsString) ((RexLiteral) call.getOperands().get(1)).getValue();
      return castNonNull(value)
          .getValue();
    default:
      return null;
    }
  }

  /** Creates an {@link Aggregate} that makes the
   * relational expression distinct on all fields. */
  public RelBuilder distinct() {
    return aggregate(groupKey(fields()));
  }

  /** Creates an {@link Aggregate} with an array of
   * calls. */
  public RelBuilder aggregate(GroupKey groupKey, AggCall... aggCalls) {
    return aggregate(groupKey, ImmutableList.copyOf(aggCalls));
  }

  /** Creates an {@link Aggregate} with an array of
   * {@link AggregateCall}s. */
  public RelBuilder aggregate(GroupKey groupKey, List<AggregateCall> aggregateCalls) {
    return aggregate(groupKey,
        aggregateCalls.stream()
            .map(aggregateCall ->
                new AggCallImpl2(aggregateCall,
                    aggregateCall.getArgList().stream()
                        .map(this::field)
                        .collect(Util.toImmutableList())))
            .collect(Collectors.toList()));
  }

  /** Creates an {@link Aggregate} with multiple calls. */
  public RelBuilder aggregate(GroupKey groupKey, Iterable<AggCall> aggCalls) {
    final Registrar registrar =
        new Registrar(fields(), peek().getRowType().getFieldNames());
    final GroupKeyImpl groupKey_ = (GroupKeyImpl) groupKey;
    ImmutableBitSet groupSet =
        ImmutableBitSet.of(registrar.registerExpressions(groupKey_.nodes));
  label:
    if (Iterables.isEmpty(aggCalls)) {
      final RelMetadataQuery mq = peek().getCluster().getMetadataQuery();
      if (groupSet.isEmpty()) {
        final Double minRowCount = mq.getMinRowCount(peek());
        if (minRowCount == null || minRowCount < 1D) {
          // We can't remove "GROUP BY ()" if there's a chance the rel could be
          // empty.
          break label;
        }
      }
      if (registrar.extraNodes.size() == fields().size()) {
        final Boolean unique = mq.areColumnsUnique(peek(), groupSet);
        if (unique != null && unique
            && !config.aggregateUnique()
            && groupKey_.isSimple()) {
          // Rel is already unique.
          return project(fields(groupSet));
        }
      }
      final Double maxRowCount = mq.getMaxRowCount(peek());
      if (maxRowCount != null && maxRowCount <= 1D
          && !config.aggregateUnique()
          && groupKey_.isSimple()) {
        // If there is at most one row, rel is already unique.
        return project(fields(groupSet));
      }
    }

    ImmutableList<ImmutableBitSet> groupSets;
    if (groupKey_.nodeLists != null) {
      final int sizeBefore = registrar.extraNodes.size();
      final List<ImmutableBitSet> groupSetList = new ArrayList<>();
      for (ImmutableList<RexNode> nodeList : groupKey_.nodeLists) {
        final ImmutableBitSet groupSet2 =
            ImmutableBitSet.of(registrar.registerExpressions(nodeList));
        if (!groupSet.contains(groupSet2)) {
          throw new IllegalArgumentException("group set element " + nodeList
              + " must be a subset of group key");
        }
        groupSetList.add(groupSet2);
      }
      final ImmutableSortedMultiset<ImmutableBitSet> groupSetMultiset =
          ImmutableSortedMultiset.copyOf(ImmutableBitSet.COMPARATOR,
              groupSetList);
      if (Iterables.any(aggCalls, RelBuilder::isGroupId)
          || !ImmutableBitSet.ORDERING.isStrictlyOrdered(groupSetMultiset)) {
        return rewriteAggregateWithDuplicateGroupSets(groupSet, groupSetMultiset,
            ImmutableList.copyOf(aggCalls));
      }
      groupSets = ImmutableList.copyOf(groupSetMultiset.elementSet());
      if (registrar.extraNodes.size() > sizeBefore) {
        throw new IllegalArgumentException("group sets contained expressions "
            + "not in group key: "
            + Util.skip(registrar.extraNodes, sizeBefore));
      }
    } else {
      groupSets = ImmutableList.of(groupSet);
    }

    for (AggCall aggCall : aggCalls) {
      ((AggCallPlus) aggCall).register(registrar);
    }
    project(registrar.extraNodes);
    rename(registrar.names);
    final Frame frame = stack.pop();
    RelNode r = frame.rel;
    final List<AggregateCall> aggregateCalls = new ArrayList<>();
    for (AggCall aggCall : aggCalls) {
      aggregateCalls.add(
          ((AggCallPlus) aggCall).aggregateCall(registrar, groupSet, r));
    }

    assert ImmutableBitSet.ORDERING.isStrictlyOrdered(groupSets) : groupSets;
    for (ImmutableBitSet set : groupSets) {
      assert groupSet.contains(set);
    }

    List<Field> inFields = frame.fields;
    if (config.pruneInputOfAggregate()
        && r instanceof Project) {
      final Set<Integer> fieldsUsed =
          RelOptUtil.getAllFields2(groupSet, aggregateCalls);
      // Some parts of the system can't handle rows with zero fields, so
      // pretend that one field is used.
      if (fieldsUsed.isEmpty()) {
        r = ((Project) r).getInput();
      } else if (fieldsUsed.size() < r.getRowType().getFieldCount()) {
        // Some fields are computed but not used. Prune them.
        final Map<Integer, Integer> map = new HashMap<>();
        for (int source : fieldsUsed) {
          map.put(source, map.size());
        }

        groupSet = groupSet.permute(map);
        groupSets =
            ImmutableBitSet.ORDERING.immutableSortedCopy(
                ImmutableBitSet.permute(groupSets, map));

        final Mappings.TargetMapping targetMapping =
            Mappings.target(map, r.getRowType().getFieldCount(),
                fieldsUsed.size());
        final List<AggregateCall> oldAggregateCalls =
            new ArrayList<>(aggregateCalls);
        aggregateCalls.clear();
        for (AggregateCall aggregateCall : oldAggregateCalls) {
          aggregateCalls.add(aggregateCall.transform(targetMapping));
        }
        inFields = Mappings.permute(inFields, targetMapping.inverse());

        final Project project = (Project) r;
        final List<RexNode> newProjects = new ArrayList<>();
        final RelDataTypeFactory.Builder builder =
            cluster.getTypeFactory().builder();
        for (int i : fieldsUsed) {
          newProjects.add(project.getProjects().get(i));
          builder.add(project.getRowType().getFieldList().get(i));
        }
        r = project.copy(cluster.traitSet(), project.getInput(), newProjects, builder.build());
      }
    }

    if (!config.dedupAggregateCalls() || Util.isDistinct(aggregateCalls)) {
      return aggregate_(groupSet, groupSets, r, aggregateCalls,
          registrar.extraNodes, inFields);
    }

    // There are duplicate aggregate calls. Rebuild the list to eliminate
    // duplicates, then add a Project.
    final Set<AggregateCall> callSet = new HashSet<>();
    final List<Pair<Integer, @Nullable String>> projects = new ArrayList<>();
    Util.range(groupSet.cardinality())
        .forEach(i -> projects.add(Pair.of(i, null)));
    final List<AggregateCall> distinctAggregateCalls = new ArrayList<>();
    for (AggregateCall aggregateCall : aggregateCalls) {
      final int i;
      if (callSet.add(aggregateCall)) {
        i = distinctAggregateCalls.size();
        distinctAggregateCalls.add(aggregateCall);
      } else {
        i = distinctAggregateCalls.indexOf(aggregateCall);
        assert i >= 0;
      }
      projects.add(Pair.of(groupSet.cardinality() + i, aggregateCall.name));
    }
    aggregate_(groupSet, groupSets, r, distinctAggregateCalls,
        registrar.extraNodes, inFields);
    final List<RexNode> fields = projects.stream()
        .map(p -> p.right == null ? field(p.left)
            : alias(field(p.left), p.right))
        .collect(Collectors.toList());
    return project(fields);
  }

  /** Finishes the implementation of {@link #aggregate} by creating an
   * {@link Aggregate} and pushing it onto the stack. */
  private RelBuilder aggregate_(ImmutableBitSet groupSet,
      ImmutableList<ImmutableBitSet> groupSets, RelNode input,
      List<AggregateCall> aggregateCalls, List<RexNode> extraNodes,
      List<Field> inFields) {
    final RelNode aggregate =
        struct.aggregateFactory.createAggregate(input,
            ImmutableList.of(), groupSet, groupSets, aggregateCalls);

    // build field list
    final ImmutableList.Builder<Field> fields = ImmutableList.builder();
    final List<RelDataTypeField> aggregateFields =
        aggregate.getRowType().getFieldList();
    int i = 0;
    // first, group fields
    for (Integer groupField : groupSet.asList()) {
      RexNode node = extraNodes.get(groupField);
      final SqlKind kind = node.getKind();
      switch (kind) {
      case INPUT_REF:
        fields.add(inFields.get(((RexInputRef) node).getIndex()));
        break;
      default:
        String name = aggregateFields.get(i).getName();
        RelDataTypeField fieldType =
            new RelDataTypeFieldImpl(name, i, node.getType());
        fields.add(new Field(ImmutableSet.of(), fieldType));
        break;
      }
      i++;
    }
    // second, aggregate fields. retain `i' as field index
    for (int j = 0; j < aggregateCalls.size(); ++j) {
      final AggregateCall call = aggregateCalls.get(j);
      final RelDataTypeField fieldType =
          new RelDataTypeFieldImpl(aggregateFields.get(i + j).getName(), i + j,
              call.getType());
      fields.add(new Field(ImmutableSet.of(), fieldType));
    }
    stack.push(new Frame(aggregate, fields.build()));
    return this;
  }

  /**
   * The {@code GROUP_ID()} function is used to distinguish duplicate groups.
   * However, as Aggregate normalizes group sets to canonical form (i.e.,
   * flatten, sorting, redundancy removal), this information is lost in RelNode.
   * Therefore, it is impossible to implement the function in runtime.
   *
   * <p>To fill this gap, an aggregation query that contains duplicate group
   * sets is rewritten into a Union of Aggregate operators whose group sets are
   * distinct. The number of inputs to the Union is equal to the maximum number
   * of duplicates. In the {@code N}th input to the Union, calls to the
   * {@code GROUP_ID} aggregate function are replaced by the integer literal
   * {@code N}.
   *
   * <p>This method also handles the case where group sets are distinct but
   * there is a call to {@code GROUP_ID}. That call is replaced by the integer
   * literal {@code 0}.
   *
   * <p>Also see the discussion in
   * <a href="https://issues.apache.org/jira/browse/CALCITE-1824">[CALCITE-1824]
   * GROUP_ID returns wrong result</a> and
   * <a href="https://issues.apache.org/jira/browse/CALCITE-4748">[CALCITE-4748]
   * If there are duplicate GROUPING SETS, Calcite should return duplicate
   * rows</a>.
   */
  private RelBuilder rewriteAggregateWithDuplicateGroupSets(
      ImmutableBitSet groupSet,
      ImmutableSortedMultiset<ImmutableBitSet> groupSets,
      List<AggCall> aggregateCalls) {
    final List<String> fieldNamesIfNoRewrite =
        Aggregate.deriveRowType(getTypeFactory(), peek().getRowType(), false,
            groupSet, groupSets.asList(),
            aggregateCalls.stream().map(c -> ((AggCallPlus) c).aggregateCall())
                .collect(Util.toImmutableList())).getFieldNames();

    // If n duplicates exist for a particular grouping, the {@code GROUP_ID()}
    // function produces values in the range 0 to n-1. For each value,
    // we need to figure out the corresponding group sets.
    //
    // For example, "... GROUPING SETS (a, a, b, c, c, c, c)"
    // (i) The max value of the GROUP_ID() function returns is 3
    // (ii) GROUPING SETS (a, b, c) produces value 0,
    //      GROUPING SETS (a, c) produces value 1,
    //      GROUPING SETS (c) produces value 2
    //      GROUPING SETS (c) produces value 3
    final Map<Integer, Set<ImmutableBitSet>> groupIdToGroupSets = new HashMap<>();
    int maxGroupId = 0;
    for (Multiset.Entry<ImmutableBitSet> entry: groupSets.entrySet()) {
      int groupId = entry.getCount() - 1;
      if (groupId > maxGroupId) {
        maxGroupId = groupId;
      }
      for (int i = 0; i <= groupId; i++) {
        groupIdToGroupSets.computeIfAbsent(i,
            k -> Sets.newTreeSet(ImmutableBitSet.COMPARATOR))
            .add(entry.getElement());
      }
    }

    // AggregateCall list without GROUP_ID function
    final List<AggCall> aggregateCallsWithoutGroupId =
        new ArrayList<>(aggregateCalls);
    aggregateCallsWithoutGroupId.removeIf(RelBuilder::isGroupId);

    // For each group id value, we first construct an Aggregate without
    // GROUP_ID() function call, and then create a Project node on top of it.
    // The Project adds literal value for group id in right position.
    final Frame frame = stack.pop();
    for (int groupId = 0; groupId <= maxGroupId; groupId++) {
      // Create the Aggregate node without GROUP_ID() call
      stack.push(frame);
      aggregate(groupKey(groupSet, castNonNull(groupIdToGroupSets.get(groupId))),
          aggregateCallsWithoutGroupId);

      final List<RexNode> selectList = new ArrayList<>();
      final int groupExprLength = groupSet.cardinality();
      // Project fields in group by expressions
      for (int i = 0; i < groupExprLength; i++) {
        selectList.add(field(i));
      }
      // Project fields in aggregate calls
      int groupIdCount = 0;
      for (int i = 0; i < aggregateCalls.size(); i++) {
        if (isGroupId(aggregateCalls.get(i))) {
          selectList.add(
              getRexBuilder().makeExactLiteral(BigDecimal.valueOf(groupId),
                  getTypeFactory().createSqlType(SqlTypeName.BIGINT)));
          groupIdCount++;
        } else {
          selectList.add(field(groupExprLength + i - groupIdCount));
        }
      }
      project(selectList, fieldNamesIfNoRewrite);
    }

    return union(true, maxGroupId + 1);
  }

  private static boolean isGroupId(AggCall c) {
    return ((AggCallPlus) c).op().kind == SqlKind.GROUP_ID;
  }

  private RelBuilder setOp(boolean all, SqlKind kind, int n) {
    List<RelNode> inputs = new ArrayList<>();
    for (int i = 0; i < n; i++) {
      inputs.add(0, build());
    }
    switch (kind) {
    case UNION:
    case INTERSECT:
    case EXCEPT:
      if (n < 1) {
        throw new IllegalArgumentException(
            "bad INTERSECT/UNION/EXCEPT input count");
      }
      break;
    default:
      throw new AssertionError("bad setOp " + kind);
    }

    if (n == 1) {
      return push(inputs.get(0));
    }

    if (config.simplifyValues()
        && kind == UNION
        && inputs.stream().allMatch(r -> r instanceof Values)) {
      List<RelDataType> inputTypes = Util.transform(inputs, RelNode::getRowType);
      RelDataType rowType = getTypeFactory()
          .leastRestrictive(inputTypes);
      requireNonNull(rowType, () -> "leastRestrictive(" + inputTypes + ")");
      final List<List<RexLiteral>> tuples = new ArrayList<>();
      for (RelNode input : inputs) {
        tuples.addAll(((Values) input).tuples);
      }
      final List<List<RexLiteral>> tuples2 =
          all ? tuples : Util.distinctList(tuples);
      return values(tuples2, rowType);
    }

    return push(struct.setOpFactory.createSetOp(kind, inputs, all));
  }

  /** Creates a {@link Union} of the two most recent
   * relational expressions on the stack.
   *
   * @param all Whether to create UNION ALL
   */
  public RelBuilder union(boolean all) {
    return union(all, 2);
  }

  /** Creates a {@link Union} of the {@code n}
   * most recent relational expressions on the stack.
   *
   * @param all Whether to create UNION ALL
   * @param n Number of inputs to the UNION operator
   */
  public RelBuilder union(boolean all, int n) {
    return setOp(all, UNION, n);
  }

  /** Creates an {@link Intersect} of the two most
   * recent relational expressions on the stack.
   *
   * @param all Whether to create INTERSECT ALL
   */
  public RelBuilder intersect(boolean all) {
    return intersect(all, 2);
  }

  /** Creates an {@link Intersect} of the {@code n}
   * most recent relational expressions on the stack.
   *
   * @param all Whether to create INTERSECT ALL
   * @param n Number of inputs to the INTERSECT operator
   */
  public RelBuilder intersect(boolean all, int n) {
    return setOp(all, SqlKind.INTERSECT, n);
  }

  /** Creates a {@link Minus} of the two most recent
   * relational expressions on the stack.
   *
   * @param all Whether to create EXCEPT ALL
   */
  public RelBuilder minus(boolean all) {
    return minus(all, 2);
  }

  /** Creates a {@link Minus} of the {@code n}
   * most recent relational expressions on the stack.
   *
   * @param all Whether to create EXCEPT ALL
   */
  public RelBuilder minus(boolean all, int n) {
    return setOp(all, SqlKind.EXCEPT, n);
  }

  /**
   * Creates a {@link TableScan} on a {@link TransientTable} with the given name, using as type
   * the top of the stack's type.
   *
   * @param tableName table name
   */
  @Experimental
  public RelBuilder transientScan(String tableName) {
    return this.transientScan(tableName, this.peek().getRowType());
  }

  /**
   * Creates a {@link TableScan} on a {@link TransientTable} with the given name and type.
   *
   * @param tableName table name
   * @param rowType row type of the table
   */
  @Experimental
  public RelBuilder transientScan(String tableName, RelDataType rowType) {
    TransientTable transientTable = new ListTransientTable(tableName, rowType);
    requireNonNull(relOptSchema, "relOptSchema");
    RelOptTable relOptTable = RelOptTableImpl.create(
        relOptSchema,
        rowType,
        transientTable,
        ImmutableList.of(tableName));
    RelNode scan =
        struct.scanFactory.createScan(
            ViewExpanders.toRelContext(viewExpander, cluster),
            relOptTable);
    push(scan);
    rename(rowType.getFieldNames());
    return this;
  }

  /**
   * Creates a {@link TableSpool} for the most recent relational expression.
   *
   * @param readType Spool's read type (as described in {@link Spool.Type})
   * @param writeType Spool's write type (as described in {@link Spool.Type})
   * @param table Table to write into
   */
  private RelBuilder tableSpool(Spool.Type readType, Spool.Type writeType,
      RelOptTable table) {
    RelNode spool =
        struct.spoolFactory.createTableSpool(peek(), readType, writeType,
            table);
    replaceTop(spool);
    return this;
  }

  /**
   * Creates a {@link RepeatUnion} associated to a {@link TransientTable} without a maximum number
   * of iterations, i.e. repeatUnion(tableName, all, -1).
   *
   * @param tableName name of the {@link TransientTable} associated to the {@link RepeatUnion}
   * @param all whether duplicates will be considered or not
   */
  @Experimental
  public RelBuilder repeatUnion(String tableName, boolean all) {
    return repeatUnion(tableName, all, -1);
  }

  /**
   * Creates a {@link RepeatUnion} associated to a {@link TransientTable} of the
   * two most recent relational expressions on the stack.
   *
   * <p>Warning: if these relational expressions are not
   * correctly defined, this operation might lead to an infinite loop.
   *
   * <p>The generated {@link RepeatUnion} operates as follows:
   *
   * <ul>
   * <li>Evaluate its left term once, propagating the results into the
   *     {@link TransientTable};
   * <li>Evaluate its right term (which may contain a {@link TableScan} on the
   *     {@link TransientTable}) over and over until it produces no more results
   *     (or until an optional maximum number of iterations is reached). On each
   *     iteration, the results are propagated into the {@link TransientTable},
   *     overwriting the results from the previous one.
   * </ul>
   *
   * @param tableName Name of the {@link TransientTable} associated to the
   *     {@link RepeatUnion}
   * @param all Whether duplicates are considered
   * @param iterationLimit Maximum number of iterations; negative value means no limit
   */
  @Experimental
  public RelBuilder repeatUnion(String tableName, boolean all, int iterationLimit) {
    RelOptTableFinder finder = new RelOptTableFinder(tableName);
    for (int i = 0; i < stack.size(); i++) { // search scan(tableName) in the stack
      peek(i).accept(finder);
      if (finder.relOptTable != null) { // found
        break;
      }
    }
    if (finder.relOptTable == null) {
      throw RESOURCE.tableNotFound(tableName).ex();
    }

    RelNode iterative = tableSpool(Spool.Type.LAZY, Spool.Type.LAZY, finder.relOptTable).build();
    RelNode seed = tableSpool(Spool.Type.LAZY, Spool.Type.LAZY, finder.relOptTable).build();
    RelNode repeatUnion =
        struct.repeatUnionFactory.createRepeatUnion(seed, iterative, all,
            iterationLimit, finder.relOptTable);
    return push(repeatUnion);
  }

  /**
   * Auxiliary class to find a certain RelOptTable based on its name.
   */
  private static final class RelOptTableFinder extends RelHomogeneousShuttle {
    private @MonotonicNonNull RelOptTable relOptTable = null;
    private final String tableName;

    private RelOptTableFinder(String tableName) {
      this.tableName = tableName;
    }

    @Override public RelNode visit(TableScan scan) {
      final RelOptTable scanTable = scan.getTable();
      final List<String> qualifiedName = scanTable.getQualifiedName();
      if (qualifiedName.get(qualifiedName.size() - 1).equals(tableName)) {
        relOptTable = scanTable;
      }
      return super.visit(scan);
    }
  }

  /** Creates a {@link Join} with an array of conditions. */
  public RelBuilder join(JoinRelType joinType, RexNode condition0,
      RexNode... conditions) {
    return join(joinType, Lists.asList(condition0, conditions));
  }

  /** Creates a {@link Join} with multiple
   * conditions. */
  public RelBuilder join(JoinRelType joinType,
      Iterable<? extends RexNode> conditions) {
    return join(joinType, and(conditions),
        ImmutableSet.of());
  }

  /** Creates a {@link Join} with one condition. */
  public RelBuilder join(JoinRelType joinType, RexNode condition) {
    return join(joinType, condition, ImmutableSet.of());
  }

  /** Creates a {@link Join} with correlating variables. */
  public RelBuilder join(JoinRelType joinType, RexNode condition,
      Set<CorrelationId> variablesSet) {
    Frame right = stack.pop();
    final Frame left = stack.pop();
    final RelNode join;
    final boolean correlate = checkIfCorrelated(variablesSet, joinType, left.rel, right.rel);
    RexNode postCondition = literal(true);
    if (config.simplify()) {
      // Normalize expanded versions IS NOT DISTINCT FROM so that simplifier does not
      // transform the expression to something unrecognizable
      if (condition instanceof RexCall) {
        condition = RelOptUtil.collapseExpandedIsNotDistinctFromExpr((RexCall) condition,
            getRexBuilder());
      }
      condition = simplifier.simplifyUnknownAsFalse(condition);
    }
    if (correlate) {
      final CorrelationId id = Iterables.getOnlyElement(variablesSet);
      // Correlate does not have an ON clause.
      switch (joinType) {
      case LEFT:
      case SEMI:
      case ANTI:
        // For a LEFT/SEMI/ANTI, predicate must be evaluated first.
        stack.push(right);
        filter(condition.accept(new Shifter(left.rel, id, right.rel)));
        right = stack.pop();
        break;
      case INNER:
        // For INNER, we can defer.
        postCondition = condition;
        break;
      default:
        throw new IllegalArgumentException("Correlated " + joinType + " join is not supported");
      }
      final ImmutableBitSet requiredColumns = RelOptUtil.correlationColumns(id, right.rel);
      join =
          struct.correlateFactory.createCorrelate(left.rel, right.rel, ImmutableList.of(), id,
              requiredColumns, joinType);
    } else {
      RelNode join0 =
          struct.joinFactory.createJoin(left.rel, right.rel,
              ImmutableList.of(), condition, variablesSet, joinType, false);

      if (join0 instanceof Join && config.pushJoinCondition()) {
        join = RelOptUtil.pushDownJoinConditions((Join) join0, this);
      } else {
        join = join0;
      }
    }
    final ImmutableList.Builder<Field> fields = ImmutableList.builder();
    fields.addAll(left.fields);
    fields.addAll(right.fields);
    stack.push(new Frame(join, fields.build()));
    filter(postCondition);
    return this;
  }

  /** Creates a {@link Correlate}
   * with a {@link CorrelationId} and an array of fields that are used by correlation. */
  public RelBuilder correlate(JoinRelType joinType,
      CorrelationId correlationId, RexNode... requiredFields) {
    return correlate(joinType, correlationId, ImmutableList.copyOf(requiredFields));
  }

  /** Creates a {@link Correlate}
   * with a {@link CorrelationId} and a list of fields that are used by correlation. */
  public RelBuilder correlate(JoinRelType joinType,
      CorrelationId correlationId, Iterable<? extends RexNode> requiredFields) {
    Frame right = stack.pop();

    final Registrar registrar =
        new Registrar(fields(), peek().getRowType().getFieldNames());

    List<Integer> requiredOrdinals =
        registrar.registerExpressions(ImmutableList.copyOf(requiredFields));

    project(registrar.extraNodes);
    rename(registrar.names);
    Frame left = stack.pop();

    final RelNode correlate =
        struct.correlateFactory.createCorrelate(left.rel, right.rel, ImmutableList.of(),
            correlationId, ImmutableBitSet.of(requiredOrdinals), joinType);

    final ImmutableList.Builder<Field> fields = ImmutableList.builder();
    fields.addAll(left.fields);
    fields.addAll(right.fields);
    stack.push(new Frame(correlate, fields.build()));

    return this;
  }

  /** Creates a {@link Join} using USING syntax.
   *
   * <p>For each of the field names, both left and right inputs must have a
   * field of that name. Constructs a join condition that the left and right
   * fields are equal.
   *
   * @param joinType Join type
   * @param fieldNames Field names
   */
  public RelBuilder join(JoinRelType joinType, String... fieldNames) {
    final List<RexNode> conditions = new ArrayList<>();
    for (String fieldName : fieldNames) {
      conditions.add(
          equals(field(2, 0, fieldName),
              field(2, 1, fieldName)));
    }
    return join(joinType, conditions);
  }

  /** Creates a {@link Join} with {@link JoinRelType#SEMI}.
   *
   * <p>A semi-join is a form of join that combines two relational expressions
   * according to some condition, and outputs only rows from the left input for
   * which at least one row from the right input matches. It only outputs
   * columns from the left input, and ignores duplicates on the right.
   *
   * <p>For example, {@code EMP semi-join DEPT} finds all {@code EMP} records
   * that do not have a corresponding {@code DEPT} record, similar to the
   * following SQL:
   *
   * <blockquote><pre>
   * SELECT * FROM EMP
   * WHERE EXISTS (SELECT 1 FROM DEPT
   *     WHERE DEPT.DEPTNO = EMP.DEPTNO)</pre>
   * </blockquote>
   */
  public RelBuilder semiJoin(Iterable<? extends RexNode> conditions) {
    final Frame right = stack.pop();
    final RelNode semiJoin =
        struct.joinFactory.createJoin(peek(),
            right.rel,
            ImmutableList.of(),
            and(conditions),
            ImmutableSet.of(),
            JoinRelType.SEMI,
            false);
    replaceTop(semiJoin);
    return this;
  }

  /** Creates a {@link Join} with {@link JoinRelType#SEMI}.
   *
   * @see #semiJoin(Iterable) */
  public RelBuilder semiJoin(RexNode... conditions) {
    return semiJoin(ImmutableList.copyOf(conditions));
  }

  /** Creates an anti-join.
   *
   * <p>An anti-join is a form of join that combines two relational expressions
   * according to some condition, but outputs only rows from the left input
   * for which no rows from the right input match.
   *
   * <p>For example, {@code EMP anti-join DEPT} finds all {@code EMP} records
   * that do not have a corresponding {@code DEPT} record, similar to the
   * following SQL:
   *
   * <blockquote><pre>
   * SELECT * FROM EMP
   * WHERE NOT EXISTS (SELECT 1 FROM DEPT
   *     WHERE DEPT.DEPTNO = EMP.DEPTNO)</pre>
   * </blockquote>
   */
  public RelBuilder antiJoin(Iterable<? extends RexNode> conditions) {
    final Frame right = stack.pop();
    final RelNode antiJoin =
        struct.joinFactory.createJoin(peek(),
            right.rel,
            ImmutableList.of(),
            and(conditions),
            ImmutableSet.of(),
            JoinRelType.ANTI,
            false);
    replaceTop(antiJoin);
    return this;
  }

  /** Creates an anti-join.
   *
   * @see #antiJoin(Iterable) */
  public RelBuilder antiJoin(RexNode... conditions) {
    return antiJoin(ImmutableList.copyOf(conditions));
  }

  /** Assigns a table alias to the top entry on the stack. */
  public RelBuilder as(final String alias) {
    final Frame pair = stack.pop();
    List<Field> newFields =
        Util.transform(pair.fields, field -> field.addAlias(alias));
    stack.push(new Frame(pair.rel, ImmutableList.copyOf(newFields)));
    return this;
  }

  /** Creates a {@link Values}.
   *
   * <p>The {@code values} array must have the same number of entries as
   * {@code fieldNames}, or an integer multiple if you wish to create multiple
   * rows.
   *
   * <p>If there are zero rows, or if all values of a any column are
   * null, this method cannot deduce the type of columns. For these cases,
   * call {@link #values(Iterable, RelDataType)}.
   *
   * @param fieldNames Field names
   * @param values Values
   */
  public RelBuilder values(@Nullable String[] fieldNames, @Nullable Object... values) {
    if (fieldNames == null
        || fieldNames.length == 0
        || values.length % fieldNames.length != 0
        || values.length < fieldNames.length) {
      throw new IllegalArgumentException(
          "Value count must be a positive multiple of field count");
    }
    final int rowCount = values.length / fieldNames.length;
    for (Ord<@Nullable String> fieldName : Ord.zip(fieldNames)) {
      if (allNull(values, fieldName.i, fieldNames.length)) {
        throw new IllegalArgumentException("All values of field '" + fieldName.e
            + "' (field index " + fieldName.i + ")"
            + " are null; cannot deduce type");
      }
    }
    final ImmutableList<ImmutableList<RexLiteral>> tupleList =
        tupleList(fieldNames.length, values);
    assert tupleList.size() == rowCount;
    final List<String> fieldNameList =
        Util.transformIndexed(Arrays.asList(fieldNames), (name, i) ->
            name != null ? name : SqlUtil.deriveAliasFromOrdinal(i));
    return values(tupleList, fieldNameList);
  }

  private RelBuilder values(List<? extends List<RexLiteral>> tupleList,
      List<String> fieldNames) {
    final RelDataTypeFactory typeFactory = cluster.getTypeFactory();
    final RelDataTypeFactory.Builder builder = typeFactory.builder();
    Ord.forEach(fieldNames, (fieldName, i) -> {
      final RelDataType type = typeFactory.leastRestrictive(
          new AbstractList<RelDataType>() {
            @Override public RelDataType get(int index) {
              return tupleList.get(index).get(i).getType();
            }

            @Override public int size() {
              return tupleList.size();
            }
          });
      assert type != null
          : "can't infer type for field " + i + ", " + fieldName;
      builder.add(fieldName, type);
    });
    final RelDataType rowType = builder.build();
    return values(tupleList, rowType);
  }

  private ImmutableList<ImmutableList<RexLiteral>> tupleList(int columnCount,
      @Nullable Object[] values) {
    final ImmutableList.Builder<ImmutableList<RexLiteral>> listBuilder =
        ImmutableList.builder();
    final List<RexLiteral> valueList = new ArrayList<>();
    for (int i = 0; i < values.length; i++) {
      Object value = values[i];
      valueList.add(literal(value));
      if ((i + 1) % columnCount == 0) {
        listBuilder.add(ImmutableList.copyOf(valueList));
        valueList.clear();
      }
    }
    return listBuilder.build();
  }

  /** Returns whether all values for a given column are null. */
  private static boolean allNull(@Nullable Object[] values, int column, int columnCount) {
    for (int i = column; i < values.length; i += columnCount) {
      if (values[i] != null) {
        return false;
      }
    }
    return true;
  }

  /** Creates a relational expression that reads from an input and throws
   * all of the rows away.
   *
   * <p>Note that this method always pops one relational expression from the
   * stack. {@code values}, in contrast, does not pop any relational
   * expressions, and always produces a leaf.
   *
   * <p>The default implementation creates a {@link Values} with the same
   * specified row type and aliases as the input, and ignores the input entirely.
   * But schema-on-query systems such as Drill might override this method to
   * create a relation expression that retains the input, just to read its
   * schema.
   */
  public RelBuilder empty() {
    final Frame frame = stack.pop();
    final RelNode values =
        struct.valuesFactory.createValues(cluster, frame.rel.getRowType(),
            ImmutableList.of());
    stack.push(new Frame(values, frame.fields));
    return this;
  }

  /** Creates a {@link Values} with a specified row type.
   *
   * <p>This method can handle cases that {@link #values(String[], Object...)}
   * cannot, such as all values of a column being null, or there being zero
   * rows.
   *
   * @param rowType Row type
   * @param columnValues Values
   */
  public RelBuilder values(RelDataType rowType, Object... columnValues) {
    final ImmutableList<ImmutableList<RexLiteral>> tupleList =
        tupleList(rowType.getFieldCount(), columnValues);
    RelNode values =
        struct.valuesFactory.createValues(cluster, rowType,
            ImmutableList.copyOf(tupleList));
    push(values);
    return this;
  }

  /** Creates a {@link Values} with a specified row type.
   *
   * <p>This method can handle cases that {@link #values(String[], Object...)}
   * cannot, such as all values of a column being null, or there being zero
   * rows.
   *
   * @param tupleList Tuple list
   * @param rowType Row type
   */
  public RelBuilder values(Iterable<? extends List<RexLiteral>> tupleList,
      RelDataType rowType) {
    RelNode values =
        struct.valuesFactory.createValues(cluster, rowType,
            copy(tupleList));
    push(values);
    return this;
  }

  /** Creates a {@link Values} with a specified row type and
   * zero rows.
   *
   * @param rowType Row type
   */
  public RelBuilder values(RelDataType rowType) {
    return values(ImmutableList.<ImmutableList<RexLiteral>>of(), rowType);
  }

  /** Converts an iterable of lists into an immutable list of immutable lists
   * with the same contents. Returns the same object if possible. */
  private static <E> ImmutableList<ImmutableList<E>> copy(
      Iterable<? extends List<E>> tupleList) {
    final ImmutableList.Builder<ImmutableList<E>> builder =
        ImmutableList.builder();
    int changeCount = 0;
    for (List<E> literals : tupleList) {
      final ImmutableList<E> literals2 =
          ImmutableList.copyOf(literals);
      builder.add(literals2);
      if (literals != literals2) {
        ++changeCount;
      }
    }
    if (changeCount == 0 && tupleList instanceof ImmutableList) {
      // don't make a copy if we don't have to
      //noinspection unchecked
      return (ImmutableList<ImmutableList<E>>) tupleList;
    }
    return builder.build();
  }

  /** Creates a limit without a sort. */
  public RelBuilder limit(int offset, int fetch) {
    return sortLimit(offset, fetch, ImmutableList.of());
  }

  /** Creates an Exchange by distribution. */
  public RelBuilder exchange(RelDistribution distribution) {
    RelNode exchange =
        struct.exchangeFactory.createExchange(peek(), distribution);
    replaceTop(exchange);
    return this;
  }

  /** Creates a SortExchange by distribution and collation. */
  public RelBuilder sortExchange(RelDistribution distribution,
      RelCollation collation) {
    RelNode exchange =
        struct.sortExchangeFactory.createSortExchange(peek(), distribution,
            collation);
    replaceTop(exchange);
    return this;
  }

  /** Creates a {@link Sort} by field ordinals.
   *
   * <p>Negative fields mean descending: -1 means field(0) descending,
   * -2 means field(1) descending, etc.
   */
  public RelBuilder sort(int... fields) {
    final ImmutableList.Builder<RexNode> builder = ImmutableList.builder();
    for (int field : fields) {
      builder.add(field < 0 ? desc(field(-field - 1)) : field(field));
    }
    return sortLimit(-1, -1, builder.build());
  }

  /** Creates a {@link Sort} by expressions. */
  public RelBuilder sort(RexNode... nodes) {
    return sortLimit(-1, -1, ImmutableList.copyOf(nodes));
  }

  /** Creates a {@link Sort} by expressions. */
  public RelBuilder sort(Iterable<? extends RexNode> nodes) {
    return sortLimit(-1, -1, nodes);
  }

  /** Creates a {@link Sort} by expressions, with limit and offset. */
  public RelBuilder sortLimit(int offset, int fetch, RexNode... nodes) {
    return sortLimit(offset, fetch, ImmutableList.copyOf(nodes));
  }

  /** Creates a {@link Sort} by specifying collations.
   */
  public RelBuilder sort(RelCollation collation) {
    final RelNode sort =
        struct.sortFactory.createSort(peek(), collation, null, null);
    replaceTop(sort);
    return this;
  }

  /** Creates a {@link Sort} by a list of expressions, with limit and offset.
   *
   * @param offset Number of rows to skip; non-positive means don't skip any
   * @param fetch Maximum number of rows to fetch; negative means no limit
   * @param nodes Sort expressions
   */
  public RelBuilder sortLimit(int offset, int fetch,
      Iterable<? extends RexNode> nodes) {
    final @Nullable RexNode offsetNode = offset <= 0 ? null : literal(offset);
    final @Nullable RexNode fetchNode = fetch < 0 ? null : literal(fetch);
    return sortLimit(offsetNode, fetchNode, nodes);
  }

  /** Creates a {@link Sort} by a list of expressions, with limitNode and offsetNode.
   *
   * @param offsetNode RexLiteral means number of rows to skip is deterministic,
   *                   RexDynamicParam means number of rows to skip is dynamic.
   * @param fetchNode  RexLiteral means maximum number of rows to fetch is deterministic,
   *                   RexDynamicParam mean maximum number is dynamic.
   * @param nodes      Sort expressions
   */
  public RelBuilder sortLimit(@Nullable RexNode offsetNode, @Nullable RexNode fetchNode,
      Iterable<? extends RexNode> nodes) {
    if (offsetNode != null) {
      if (!(offsetNode instanceof RexLiteral || offsetNode instanceof RexDynamicParam)) {
        throw new IllegalArgumentException("OFFSET node must be RexLiteral or RexDynamicParam");
      }
    }
    if (fetchNode != null) {
      if (!(fetchNode instanceof RexLiteral || fetchNode instanceof RexDynamicParam)) {
        throw new IllegalArgumentException("FETCH node must be RexLiteral or RexDynamicParam");
      }
    }

    final Registrar registrar = new Registrar(fields(), ImmutableList.of());
    final List<RelFieldCollation> fieldCollations =
        registrar.registerFieldCollations(nodes);
    final int fetch = fetchNode instanceof RexLiteral
        ? RexLiteral.intValue(fetchNode) : -1;
    if (offsetNode == null && fetch == 0 && config.simplifyLimit()) {
      return empty();
    }
    if (offsetNode == null && fetchNode == null && fieldCollations.isEmpty()) {
      return this; // sort is trivial
    }

    if (fieldCollations.isEmpty()) {
      assert registrar.addedFieldCount() == 0;
      RelNode top = peek();
      if (top instanceof Sort) {
        final Sort sort2 = (Sort) top;
        if (sort2.offset == null && sort2.fetch == null) {
          replaceTop(sort2.getInput());
          final RelNode sort =
              struct.sortFactory.createSort(peek(), sort2.collation,
                  offsetNode, fetchNode);
          replaceTop(sort);
          return this;
        }
      }
      if (top instanceof Project) {
        final Project project = (Project) top;
        if (project.getInput() instanceof Sort) {
          final Sort sort2 = (Sort) project.getInput();
          if (sort2.offset == null && sort2.fetch == null) {
            final RelNode sort =
                struct.sortFactory.createSort(sort2.getInput(),
                    sort2.collation, offsetNode, fetchNode);
            replaceTop(
                struct.projectFactory.createProject(sort,
                    project.getHints(),
                    project.getProjects(),
                    Pair.right(project.getNamedProjects()),
                    project.getVariablesSet()));
            return this;
          }
        }
      }
    }
    if (registrar.addedFieldCount() > 0) {
      project(registrar.extraNodes);
    }
    final RelNode sort =
        struct.sortFactory.createSort(peek(),
            RelCollations.of(fieldCollations), offsetNode, fetchNode);
    replaceTop(sort);
    if (registrar.addedFieldCount() > 0) {
      project(registrar.originalExtraNodes);
    }
    return this;
  }

  private static RelFieldCollation collation(RexNode node,
      RelFieldCollation.Direction direction,
      RelFieldCollation.@Nullable NullDirection nullDirection,
      List<RexNode> extraNodes) {
    switch (node.getKind()) {
    case INPUT_REF:
      return new RelFieldCollation(((RexInputRef) node).getIndex(), direction,
          Util.first(nullDirection, direction.defaultNullDirection()));
    case DESCENDING:
      return collation(((RexCall) node).getOperands().get(0),
          RelFieldCollation.Direction.DESCENDING,
          nullDirection, extraNodes);
    case NULLS_FIRST:
      return collation(((RexCall) node).getOperands().get(0), direction,
          RelFieldCollation.NullDirection.FIRST, extraNodes);
    case NULLS_LAST:
      return collation(((RexCall) node).getOperands().get(0), direction,
          RelFieldCollation.NullDirection.LAST, extraNodes);
    default:
      final int fieldIndex = extraNodes.size();
      extraNodes.add(node);
      return new RelFieldCollation(fieldIndex, direction,
          Util.first(nullDirection, direction.defaultNullDirection()));
    }
  }

  private static RexFieldCollation rexCollation(RexNode node,
      RelFieldCollation.Direction direction,
      RelFieldCollation.@Nullable NullDirection nullDirection) {
    switch (node.getKind()) {
    case DESCENDING:
      return rexCollation(((RexCall) node).operands.get(0),
          RelFieldCollation.Direction.DESCENDING, nullDirection);
    case NULLS_LAST:
      return rexCollation(((RexCall) node).operands.get(0),
          direction, RelFieldCollation.NullDirection.LAST);
    case NULLS_FIRST:
      return rexCollation(((RexCall) node).operands.get(0),
          direction, RelFieldCollation.NullDirection.FIRST);
    default:
      final Set<SqlKind> flags = EnumSet.noneOf(SqlKind.class);
      if (direction == RelFieldCollation.Direction.DESCENDING) {
        flags.add(SqlKind.DESCENDING);
      }
      if (nullDirection == RelFieldCollation.NullDirection.FIRST) {
        flags.add(SqlKind.NULLS_FIRST);
      }
      if (nullDirection == RelFieldCollation.NullDirection.LAST) {
        flags.add(SqlKind.NULLS_LAST);
      }
      return new RexFieldCollation(node, flags);
    }
  }

  /**
   * Creates a projection that converts the current relational expression's
   * output to a desired row type.
   *
   * <p>The desired row type and the row type to be converted must have the
   * same number of fields.
   *
   * @param castRowType row type after cast
   * @param rename      if true, use field names from castRowType; if false,
   *                    preserve field names from rel
   */
  public RelBuilder convert(RelDataType castRowType, boolean rename) {
    final RelNode r = build();
    final RelNode r2 =
        RelOptUtil.createCastRel(r, castRowType, rename,
            struct.projectFactory);
    push(r2);
    return this;
  }

  public RelBuilder permute(Mapping mapping) {
    assert mapping.getMappingType().isSingleSource();
    assert mapping.getMappingType().isMandatorySource();
    if (mapping.isIdentity()) {
      return this;
    }
    final List<RexNode> exprList = new ArrayList<>();
    for (int i = 0; i < mapping.getTargetCount(); i++) {
      exprList.add(field(mapping.getSource(i)));
    }
    return project(exprList);
  }

  /** Creates a {@link Match}. */
  public RelBuilder match(RexNode pattern, boolean strictStart,
      boolean strictEnd, Map<String, RexNode> patternDefinitions,
      Iterable<? extends RexNode> measureList, RexNode after,
      Map<String, ? extends SortedSet<String>> subsets, boolean allRows,
      Iterable<? extends RexNode> partitionKeys,
      Iterable<? extends RexNode> orderKeys, RexNode interval) {
    final Registrar registrar =
        new Registrar(fields(), peek().getRowType().getFieldNames());
    final List<RelFieldCollation> fieldCollations =
        registrar.registerFieldCollations(orderKeys);

    final ImmutableBitSet partitionBitSet =
        ImmutableBitSet.of(registrar.registerExpressions(partitionKeys));

    final RelDataTypeFactory.Builder typeBuilder = cluster.getTypeFactory().builder();
    for (RexNode partitionKey : partitionKeys) {
      typeBuilder.add(partitionKey.toString(), partitionKey.getType());
    }
    if (allRows) {
      for (RexNode orderKey : orderKeys) {
        if (!typeBuilder.nameExists(orderKey.toString())) {
          typeBuilder.add(orderKey.toString(), orderKey.getType());
        }
      }

      final RelDataType inputRowType = peek().getRowType();
      for (RelDataTypeField fs : inputRowType.getFieldList()) {
        if (!typeBuilder.nameExists(fs.getName())) {
          typeBuilder.add(fs);
        }
      }
    }

    final ImmutableMap.Builder<String, RexNode> measures = ImmutableMap.builder();
    for (RexNode measure : measureList) {
      List<RexNode> operands = ((RexCall) measure).getOperands();
      String alias = operands.get(1).toString();
      typeBuilder.add(alias, operands.get(0).getType());
      measures.put(alias, operands.get(0));
    }

    final RelNode match =
        struct.matchFactory.createMatch(peek(), pattern,
            typeBuilder.build(), strictStart, strictEnd, patternDefinitions,
            measures.build(), after, subsets, allRows,
            partitionBitSet, RelCollations.of(fieldCollations), interval);
    stack.push(new Frame(match));
    return this;
  }

  /** Creates a Pivot.
   *
   * <p>To achieve the same effect as the SQL
   *
   * <blockquote><pre>{@code
   * SELECT *
   * FROM (SELECT mgr, deptno, job, sal FROM emp)
   * PIVOT (SUM(sal) AS ss, COUNT(*) AS c
   *     FOR (job, deptno)
   *     IN (('CLERK', 10) AS c10, ('MANAGER', 20) AS m20))
   * }</pre></blockquote>
   *
   * <p>use the builder as follows:
   *
   * <blockquote><pre>{@code
   * RelBuilder b;
   * b.scan("EMP");
   * final RelBuilder.GroupKey groupKey = b.groupKey("MGR");
   * final List<RelBuilder.AggCall> aggCalls =
   *     Arrays.asList(b.sum(b.field("SAL")).as("SS"),
   *         b.count().as("C"));
   * final List<RexNode> axes =
   *     Arrays.asList(b.field("JOB"),
   *         b.field("DEPTNO"));
   * final ImmutableMap.Builder<String, List<RexNode>> valueMap =
   *     ImmutableMap.builder();
   * valueMap.put("C10",
   *     Arrays.asList(b.literal("CLERK"), b.literal(10)));
   * valueMap.put("M20",
   *     Arrays.asList(b.literal("MANAGER"), b.literal(20)));
   * b.pivot(groupKey, aggCalls, axes, valueMap.build().entrySet());
   * }</pre></blockquote>
   *
   * <p>Note that the SQL uses a sub-query to project away columns (e.g.
   * {@code HIREDATE}) that it does not reference, so that they do not appear in
   * the {@code GROUP BY}. You do not need to do that in this API, because the
   * {@code groupKey} parameter specifies the keys.
   *
   * <p>Pivot is implemented by desugaring. The above example becomes the
   * following:
   *
   * <blockquote><pre>{@code
   * SELECT mgr,
   *     SUM(sal) FILTER (WHERE job = 'CLERK' AND deptno = 10) AS c10_ss,
   *     COUNT(*) FILTER (WHERE job = 'CLERK' AND deptno = 10) AS c10_c,
   *     SUM(sal) FILTER (WHERE job = 'MANAGER' AND deptno = 20) AS m20_ss,
   *      COUNT(*) FILTER (WHERE job = 'MANAGER' AND deptno = 20) AS m20_c
   * FROM emp
   * GROUP BY mgr
   * }</pre></blockquote>
   *
   * @param groupKey Key columns
   * @param aggCalls Aggregate expressions to compute for each value
   * @param axes Columns to pivot
   * @param values Values to pivot, and the alias for each column group
   *
   * @return this RelBuilder
   */
  public RelBuilder pivot(GroupKey groupKey,
      Iterable<? extends AggCall> aggCalls,
      Iterable<? extends RexNode> axes,
      Iterable<? extends Map.Entry<String,
          ? extends Iterable<? extends RexNode>>> values) {
    final List<RexNode> axisList = ImmutableList.copyOf(axes);
    final List<AggCall> multipliedAggCalls = new ArrayList<>();
    Pair.forEach(values, (alias, expressions) -> {
      final List<RexNode> expressionList = ImmutableList.copyOf(expressions);
      if (expressionList.size() != axisList.size()) {
        throw new IllegalArgumentException("value count must match axis count ["
            + expressionList + "], [" + axisList + "]");
      }
      aggCalls.forEach(aggCall -> {
        final String alias2 = alias + "_" + ((AggCallPlus) aggCall).alias();
        final List<RexNode> filters = new ArrayList<>();
        Pair.forEach(axisList, expressionList, (axis, expression) ->
            filters.add(equals(axis, expression)));
        multipliedAggCalls.add(aggCall.filter(and(filters)).as(alias2));
      });
    });
    return aggregate(groupKey, multipliedAggCalls);
  }

  /**
   * Creates an Unpivot.
   *
   * <p>To achieve the same effect as the SQL
   *
   * <blockquote><pre>{@code
   * SELECT *
   * FROM (SELECT deptno, job, sal, comm FROM emp)
   *   UNPIVOT INCLUDE NULLS (remuneration
   *     FOR remuneration_type IN (comm AS 'commission',
   *                               sal AS 'salary'))
   * }</pre></blockquote>
   *
   * <p>use the builder as follows:
   *
   * <blockquote><pre>{@code
   * RelBuilder b;
   * b.scan("EMP");
   * final List<String> measureNames = Arrays.asList("REMUNERATION");
   * final List<String> axisNames = Arrays.asList("REMUNERATION_TYPE");
   * final Map<List<RexLiteral>, List<RexNode>> axisMap =
   *     ImmutableMap.<List<RexLiteral>, List<RexNode>>builder()
   *         .put(Arrays.asList(b.literal("commission")),
   *             Arrays.asList(b.field("COMM")))
   *         .put(Arrays.asList(b.literal("salary")),
   *             Arrays.asList(b.field("SAL")))
   *         .build();
   * b.unpivot(false, measureNames, axisNames, axisMap);
   * }</pre></blockquote>
   *
   * <p>The query generates two columns: {@code remuneration_type} (an axis
   * column) and {@code remuneration} (a measure column). Axis columns contain
   * values to indicate the source of the row (in this case, {@code 'salary'}
   * if the row came from the {@code sal} column, and {@code 'commission'}
   * if the row came from the {@code comm} column).
   *
   * @param includeNulls Whether to include NULL values in the output
   * @param measureNames Names of columns to be generated to hold pivoted
   *                    measures
   * @param axisNames Names of columns to be generated to hold qualifying values
   * @param axisMap Mapping from the columns that hold measures to the values
   *           that the axis columns will hold in the generated rows
   * @return This RelBuilder
   */
  public RelBuilder unpivot(boolean includeNulls,
      Iterable<String> measureNames, Iterable<String> axisNames,
      Iterable<? extends Map.Entry<? extends List<? extends RexLiteral>,
          ? extends List<? extends RexNode>>> axisMap) {
    // Make immutable copies of all arguments.
    final List<String> measureNameList = ImmutableList.copyOf(measureNames);
    final List<String> axisNameList = ImmutableList.copyOf(axisNames);
    final List<Pair<List<RexLiteral>, List<RexNode>>> map =
        StreamSupport.stream(axisMap.spliterator(), false)
            .map(pair ->
                Pair.<List<RexLiteral>, List<RexNode>>of(
                    ImmutableList.<RexLiteral>copyOf(pair.getKey()),
                    ImmutableList.<RexNode>copyOf(pair.getValue())))
            .collect(Util.toImmutableList());

    // Check that counts match.
    Pair.forEach(map, (valueList, inputMeasureList) -> {
      if (inputMeasureList.size() != measureNameList.size()) {
        throw new IllegalArgumentException("Number of measures ("
            + inputMeasureList.size() + ") must match number of measure names ("
            + measureNameList.size() + ")");
      }
      if (valueList.size() != axisNameList.size()) {
        throw new IllegalArgumentException("Number of axis values ("
            + valueList.size() + ") match match number of axis names ("
            + axisNameList.size() + ")");
      }
    });

    final RelDataType leftRowType = peek().getRowType();
    final BitSet usedFields = new BitSet();
    Pair.forEach(map, (aliases, nodes) ->
        nodes.forEach(node -> {
          if (node instanceof RexInputRef) {
            usedFields.set(((RexInputRef) node).getIndex());
          }
        }));

    // Create "VALUES (('commission'), ('salary')) AS t (remuneration_type)"
    values(ImmutableList.copyOf(Pair.left(map)), axisNameList);

    join(JoinRelType.INNER);

    final ImmutableBitSet unusedFields =
        ImmutableBitSet.range(leftRowType.getFieldCount())
            .except(ImmutableBitSet.fromBitSet(usedFields));
    final List<RexNode> projects = new ArrayList<>(fields(unusedFields));
    Ord.forEach(axisNameList, (dimensionName, d) ->
        projects.add(
            alias(field(leftRowType.getFieldCount() + d),
                dimensionName)));

    final List<RexNode> conditions = new ArrayList<>();
    Ord.forEach(measureNameList, (measureName, m) -> {
      final List<RexNode> caseOperands = new ArrayList<>();
      Pair.forEach(map, (literals, nodes) -> {
        Ord.forEach(literals, (literal, d) ->
            conditions.add(
                equals(field(leftRowType.getFieldCount() + d), literal)));
        caseOperands.add(and(conditions));
        conditions.clear();
        caseOperands.add(nodes.get(m));
      });
      caseOperands.add(literal(null));
      projects.add(
          alias(call(SqlStdOperatorTable.CASE, caseOperands),
              measureName));
    });
    project(projects);

    if (!includeNulls) {
      // Add 'WHERE m1 IS NOT NULL OR m2 IS NOT NULL'
      final BitSet notNullFields = new BitSet();
      Ord.forEach(measureNameList, (measureName, m) -> {
        final int f = unusedFields.cardinality() + axisNameList.size() + m;
        conditions.add(isNotNull(field(f)));
        notNullFields.set(f);
      });
      filter(or(conditions));
      if (measureNameList.size() == 1) {
        // If there is one field, EXCLUDE NULLS will have converted it to NOT
        // NULL.
        final RelDataTypeFactory.Builder builder = getTypeFactory().builder();
        peek().getRowType().getFieldList().forEach(field -> {
          final RelDataType type = field.getType();
          builder.add(field.getName(),
              notNullFields.get(field.getIndex())
                  ? getTypeFactory().createTypeWithNullability(type, false)
                  : type);
        });
        convert(builder.build(), false);
      }
      conditions.clear();
    }

    return this;
  }

  /**
   * Attaches an array of hints to the stack top relational expression.
   *
   * <p>The redundant hints would be eliminated.
   *
   * @param hints Hints
   *
   * @throws AssertionError if the top relational expression does not implement
   * {@link org.apache.calcite.rel.hint.Hintable}
   */
  public RelBuilder hints(RelHint... hints) {
    return hints(ImmutableList.copyOf(hints));
  }

  /**
   * Attaches multiple hints to the stack top relational expression.
   *
   * <p>The redundant hints would be eliminated.
   *
   * @param hints Hints
   *
   * @throws AssertionError if the top relational expression does not implement
   * {@link org.apache.calcite.rel.hint.Hintable}
   */
  public RelBuilder hints(Iterable<RelHint> hints) {
    requireNonNull(hints, "hints");
    final List<RelHint> relHintList = hints instanceof List ? (List<RelHint>) hints
        : Lists.newArrayList(hints);
    if (relHintList.isEmpty()) {
      return this;
    }
    final Frame frame = peek_();
    assert frame != null : "There is no relational expression to attach the hints";
    assert frame.rel instanceof Hintable : "The top relational expression is not a Hintable";
    Hintable hintable = (Hintable) frame.rel;
    replaceTop(hintable.attachHints(relHintList));
    return this;
  }

  /** Clears the stack.
   *
   * <p>The builder's state is now the same as when it was created. */
  public void clear() {
    stack.clear();
  }

  /** Information necessary to create a call to an aggregate function.
   *
   * @see RelBuilder#aggregateCall */
  public interface AggCall {
    /** Returns a copy of this AggCall that applies a filter before aggregating
     * values. */
    AggCall filter(@Nullable RexNode condition);

    /** Returns a copy of this AggCall that sorts its input values by
     * {@code orderKeys} before aggregating, as in SQL's {@code WITHIN GROUP}
     * clause. */
    AggCall sort(Iterable<RexNode> orderKeys);

    /** Returns a copy of this AggCall that sorts its input values by
     * {@code orderKeys} before aggregating, as in SQL's {@code WITHIN GROUP}
     * clause. */
    default AggCall sort(RexNode... orderKeys) {
      return sort(ImmutableList.copyOf(orderKeys));
    }

    /** Returns a copy of this AggCall that makes its input values unique by
     * {@code distinctKeys} before aggregating, as in SQL's
     * {@code WITHIN DISTINCT} clause. */
    AggCall unique(@Nullable Iterable<RexNode> distinctKeys);

    /** Returns a copy of this AggCall that makes its input values unique by
     * {@code distinctKeys} before aggregating, as in SQL's
     * {@code WITHIN DISTINCT} clause. */
    default AggCall unique(RexNode... distinctKeys) {
      return unique(ImmutableList.copyOf(distinctKeys));
    }

    /** Returns a copy of this AggCall that may return approximate results
     * if {@code approximate} is true. */
    AggCall approximate(boolean approximate);

    /** Returns a copy of this AggCall that ignores nulls. */
    AggCall ignoreNulls(boolean ignoreNulls);

    /** Returns a copy of this AggCall with a given alias. */
    AggCall as(@Nullable String alias);

    /** Returns a copy of this AggCall that is optionally distinct. */
    AggCall distinct(boolean distinct);

    /** Returns a copy of this AggCall that is distinct. */
    default AggCall distinct() {
      return distinct(true);
    }

    /** Converts this aggregate call to a windowed aggregate call. */
    OverCall over();
  }

  /** Internal methods shared by all implementations of {@link AggCall}. */
  private interface AggCallPlus extends AggCall {
    /** Returns the aggregate function. */
    SqlAggFunction op();

    /** Returns the alias. */
    @Nullable String alias();

    /** Returns an {@link AggregateCall} that is approximately equivalent
     * to this {@code AggCall} and is good for certain things, such as deriving
     * field names. */
    AggregateCall aggregateCall();

    /** Converts this {@code AggCall} to a good {@link AggregateCall}. */
    AggregateCall aggregateCall(Registrar registrar, ImmutableBitSet groupSet,
        RelNode r);

    /** Registers expressions in operands and filters. */
    void register(Registrar registrar);
  }

  /** Information necessary to create the GROUP BY clause of an Aggregate.
   *
   * @see RelBuilder#groupKey */
  public interface GroupKey {
    /** Assigns an alias to this group key.
     *
     * <p>Used to assign field names in the {@code group} operation. */
    GroupKey alias(@Nullable String alias);

    /** Returns the number of columns in the group key. */
    int groupKeyCount();
  }

  /** Implementation of {@link RelBuilder.GroupKey}. */
  static class GroupKeyImpl implements GroupKey {
    final ImmutableList<RexNode> nodes;
    final @Nullable ImmutableList<ImmutableList<RexNode>> nodeLists;
    final @Nullable String alias;

    GroupKeyImpl(ImmutableList<RexNode> nodes,
        @Nullable ImmutableList<ImmutableList<RexNode>> nodeLists,
        @Nullable String alias) {
      this.nodes = requireNonNull(nodes, "nodes");
      this.nodeLists = nodeLists;
      this.alias = alias;
    }

    @Override public String toString() {
      return alias == null ? nodes.toString() : nodes + " as " + alias;
    }

    @Override public int groupKeyCount() {
      return nodes.size();
    }

    @Override public GroupKey alias(@Nullable String alias) {
      return Objects.equals(this.alias, alias)
          ? this
          : new GroupKeyImpl(nodes, nodeLists, alias);
    }

    boolean isSimple() {
      return nodeLists == null || nodeLists.size() == 1;
    }
  }

  /**
   * Checks for {@link CorrelationId}, then validates the id is not used on left,
   * and finally checks if id is actually used on right.
   *
   * @return true if a correlate id is present and used
   *
   * @throws IllegalArgumentException if the {@link CorrelationId} is used by left side or if the a
   *   {@link CorrelationId} is present and the {@link JoinRelType} is FULL or RIGHT.
   */
  private static boolean checkIfCorrelated(Set<CorrelationId> variablesSet,
      JoinRelType joinType, RelNode leftNode, RelNode rightRel) {
    if (variablesSet.size() != 1) {
      return false;
    }
    CorrelationId id = Iterables.getOnlyElement(variablesSet);
    if (!RelOptUtil.notContainsCorrelation(leftNode, id, Litmus.IGNORE)) {
      throw new IllegalArgumentException("variable " + id
          + " must not be used by left input to correlation");
    }
    switch (joinType) {
    case RIGHT:
    case FULL:
      throw new IllegalArgumentException("Correlated " + joinType + " join is not supported");
    default:
      return !RelOptUtil.correlationColumns(
          Iterables.getOnlyElement(variablesSet),
          rightRel).isEmpty();
    }
  }


  /** Implementation of {@link AggCall}. */
  private class AggCallImpl implements AggCallPlus {
    private final SqlAggFunction aggFunction;
    private final boolean distinct;
    private final boolean approximate;
    private final boolean ignoreNulls;
    private final @Nullable RexNode filter;
    private final @Nullable String alias;
    private final ImmutableList<RexNode> operands; // may be empty
    private final @Nullable ImmutableList<RexNode> distinctKeys; // may be empty or null
    private final ImmutableList<RexNode> orderKeys; // may be empty

    AggCallImpl(SqlAggFunction aggFunction, boolean distinct,
        boolean approximate, boolean ignoreNulls, @Nullable RexNode filter,
        @Nullable String alias, ImmutableList<RexNode> operands,
        @Nullable ImmutableList<RexNode> distinctKeys,
        ImmutableList<RexNode> orderKeys) {
      this.aggFunction = requireNonNull(aggFunction, "aggFunction");
      // If the aggregate function ignores DISTINCT,
      // make the DISTINCT flag FALSE.
      this.distinct = distinct
          && aggFunction.getDistinctOptionality() != Optionality.IGNORED;
      this.approximate = approximate;
      this.ignoreNulls = ignoreNulls;
      this.alias = alias;
      this.operands = requireNonNull(operands, "operands");
      this.distinctKeys = distinctKeys;
      this.orderKeys = requireNonNull(orderKeys, "orderKeys");
      if (filter != null) {
        if (filter.getType().getSqlTypeName() != SqlTypeName.BOOLEAN) {
          throw RESOURCE.filterMustBeBoolean().ex();
        }
        if (filter.getType().isNullable()) {
          filter = call(SqlStdOperatorTable.IS_TRUE, filter);
        }
      }
      this.filter = filter;
    }

    @Override public String toString() {
      final StringBuilder b = new StringBuilder();
      b.append(aggFunction.getName())
          .append('(');
      if (distinct) {
        b.append("DISTINCT ");
      }
      if (operands.size() > 0) {
        b.append(operands.get(0));
        for (int i = 1; i < operands.size(); i++) {
          b.append(", ");
          b.append(operands.get(i));
        }
      }
      b.append(')');
      if (filter != null) {
        b.append(" FILTER (WHERE ").append(filter).append(')');
      }
      if (distinctKeys != null) {
        b.append(" WITHIN DISTINCT (").append(distinctKeys).append(')');
      }
      return b.toString();
    }

    @Override public SqlAggFunction op() {
      return aggFunction;
    }

    @Override public @Nullable String alias() {
      return alias;
    }

    @Override public AggregateCall aggregateCall() {
      // Use dummy values for collation and type. This method only promises to
      // return a call that is "approximately equivalent ... and is good for
      // deriving field names", so dummy values are good enough.
      final RelCollation collation = RelCollations.EMPTY;
      final RelDataType type =
          getTypeFactory().createSqlType(SqlTypeName.BOOLEAN);
      return AggregateCall.create(aggFunction, distinct, approximate,
          ignoreNulls, ImmutableList.of(), -1, null, collation, type, alias);
    }

    @Override public AggregateCall aggregateCall(Registrar registrar,
        ImmutableBitSet groupSet, RelNode r) {
      List<Integer> args =
          registrar.registerExpressions(this.operands);
      final int filterArg = this.filter == null ? -1
          : registrar.registerExpression(this.filter);
      if (this.distinct && !this.aggFunction.isQuantifierAllowed()) {
        throw new IllegalArgumentException("DISTINCT not allowed");
      }
      if (this.filter != null && !this.aggFunction.allowsFilter()) {
        throw new IllegalArgumentException("FILTER not allowed");
      }
      final @Nullable ImmutableBitSet distinctKeys =
          this.distinctKeys == null
              ? null
              : ImmutableBitSet.of(
                  registrar.registerExpressions(this.distinctKeys));
      final RelCollation collation =
          RelCollations.of(this.orderKeys
              .stream()
              .map(orderKey ->
                  collation(orderKey, RelFieldCollation.Direction.ASCENDING,
                      null, Collections.emptyList()))
              .collect(Collectors.toList()));
      if (aggFunction instanceof SqlCountAggFunction && !distinct) {
        args = args.stream()
            .filter(r::fieldIsNullable)
            .collect(Util.toImmutableList());
      }
      return AggregateCall.create(aggFunction, distinct, approximate,
          ignoreNulls, args, filterArg, distinctKeys, collation,
          groupSet.cardinality(), r, null, alias);
    }

    @Override public void register(Registrar registrar) {
      registrar.registerExpressions(operands);
      if (filter != null) {
        registrar.registerExpression(filter);
      }
      if (distinctKeys != null) {
        registrar.registerExpressions(distinctKeys);
      }
      registrar.registerExpressions(orderKeys);
    }

    @Override public OverCall over() {
      return new OverCallImpl(aggFunction, distinct, operands, ignoreNulls,
          alias);
    }

    @Override public AggCall sort(Iterable<RexNode> orderKeys) {
      final ImmutableList<RexNode> orderKeyList =
          ImmutableList.copyOf(orderKeys);
      return orderKeyList.equals(this.orderKeys)
          ? this
          : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls,
              filter, alias, operands, distinctKeys, orderKeyList);
    }

    @Override public AggCall sort(RexNode... orderKeys) {
      return sort(ImmutableList.copyOf(orderKeys));
    }

    @Override public AggCall unique(@Nullable Iterable<RexNode> distinctKeys) {
      final @Nullable ImmutableList<RexNode> distinctKeyList =
          distinctKeys == null ? null : ImmutableList.copyOf(distinctKeys);
      return Objects.equals(distinctKeyList, this.distinctKeys)
          ? this
          : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls,
              filter, alias, operands, distinctKeyList, orderKeys);
    }

    @Override public AggCall approximate(boolean approximate) {
      return approximate == this.approximate
          ? this
          : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls,
              filter, alias, operands, distinctKeys, orderKeys);
    }

    @Override public AggCall filter(@Nullable RexNode condition) {
      return Objects.equals(condition, this.filter)
          ? this
          : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls,
              condition, alias, operands, distinctKeys, orderKeys);
    }

    @Override public AggCall as(@Nullable String alias) {
      return Objects.equals(alias, this.alias)
          ? this
          : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls,
              filter, alias, operands, distinctKeys, orderKeys);
    }

    @Override public AggCall distinct(boolean distinct) {
      return distinct == this.distinct
          ? this
          : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls,
              filter, alias, operands, distinctKeys, orderKeys);
    }

    @Override public AggCall ignoreNulls(boolean ignoreNulls) {
      return ignoreNulls == this.ignoreNulls
          ? this
          : new AggCallImpl(aggFunction, distinct, approximate, ignoreNulls,
              filter, alias, operands, distinctKeys, orderKeys);
    }
  }

  /** Implementation of {@link AggCall} that wraps an
   * {@link AggregateCall}. */
  private class AggCallImpl2 implements AggCallPlus {
    private final AggregateCall aggregateCall;
    private final ImmutableList<RexNode> operands;

    AggCallImpl2(AggregateCall aggregateCall, ImmutableList<RexNode> operands) {
      this.aggregateCall = requireNonNull(aggregateCall, "aggregateCall");
      this.operands = requireNonNull(operands, "operands");
    }

    @Override public OverCall over() {
      return new OverCallImpl(aggregateCall.getAggregation(),
          aggregateCall.isDistinct(), operands, aggregateCall.ignoreNulls(),
          aggregateCall.name);
    }

    @Override public String toString() {
      return aggregateCall.toString();
    }

    @Override public SqlAggFunction op() {
      return aggregateCall.getAggregation();
    }

    @Override public @Nullable String alias() {
      return aggregateCall.name;
    }

    @Override public AggregateCall aggregateCall() {
      return aggregateCall;
    }

    @Override public AggregateCall aggregateCall(Registrar registrar,
        ImmutableBitSet groupSet, RelNode r) {
      return aggregateCall;
    }

    @Override public void register(Registrar registrar) {
      // nothing to do
    }

    @Override public AggCall sort(Iterable<RexNode> orderKeys) {
      throw new UnsupportedOperationException();
    }

    @Override public AggCall sort(RexNode... orderKeys) {
      throw new UnsupportedOperationException();
    }

    @Override public AggCall unique(@Nullable Iterable<RexNode> distinctKeys) {
      throw new UnsupportedOperationException();
    }

    @Override public AggCall approximate(boolean approximate) {
      throw new UnsupportedOperationException();
    }

    @Override public AggCall filter(@Nullable RexNode condition) {
      throw new UnsupportedOperationException();
    }

    @Override public AggCall as(@Nullable String alias) {
      throw new UnsupportedOperationException();
    }

    @Override public AggCall distinct(boolean distinct) {
      throw new UnsupportedOperationException();
    }

    @Override public AggCall ignoreNulls(boolean ignoreNulls) {
      throw new UnsupportedOperationException();
    }
  }

  /** Call to a windowed aggregate function.
   *
   * <p>To create an {@code OverCall}, start with an {@link AggCall} (created
   * by a method such as {@link #aggregateCall}, {@link #sum} or {@link #count})
   * and call its {@link AggCall#over()} method. For example,
   *
   * <pre>{@code
   *      b.scan("EMP")
   *         .project(b.field("DEPTNO"),
   *            b.aggregateCall(SqlStdOperatorTable.ROW_NUMBER)
   *               .over()
   *               .partitionBy()
   *               .orderBy(b.field("EMPNO"))
   *               .rowsUnbounded()
   *               .allowPartial(true)
   *               .nullWhenCountZero(false)
   *               .as("x"))
   * }</pre>
   *
   * <p>Unlike an aggregate call, a windowed aggregate call is an expression
   * that you can use in a {@link Project} or {@link Filter}. So, to finish,
   * call {@link OverCall#toRex()} to convert the {@code OverCall} to a
   * {@link RexNode}; the {@link OverCall#as} method (used in the above example)
   * does the same but also assigns an column alias.
   */
  public interface OverCall {
    /** Performs an action on this OverCall. */
    default <R> R let(Function<OverCall, R> consumer) {
      return consumer.apply(this);
    }

    /** Sets the PARTITION BY clause to an array of expressions. */
    OverCall partitionBy(RexNode... expressions);

    /** Sets the PARTITION BY clause to a list of expressions. */
    OverCall partitionBy(Iterable<? extends RexNode> expressions);

    /** Sets the ORDER BY BY clause to an array of expressions.
     *
     * <p>Use {@link #desc(RexNode)}, {@link #nullsFirst(RexNode)},
     * {@link #nullsLast(RexNode)} to control the sort order. */
    OverCall orderBy(RexNode... expressions);

    /** Sets the ORDER BY BY clause to a list of expressions.
     *
     * <p>Use {@link #desc(RexNode)}, {@link #nullsFirst(RexNode)},
     * {@link #nullsLast(RexNode)} to control the sort order. */
    OverCall orderBy(Iterable<? extends RexNode> expressions);

    /** Sets an unbounded ROWS window,
     * equivalent to SQL {@code ROWS BETWEEN UNBOUNDED PRECEDING AND
     * UNBOUNDED FOLLOWING}. */
    default OverCall rowsUnbounded() {
      return rowsBetween(RexWindowBounds.UNBOUNDED_PRECEDING,
          RexWindowBounds.UNBOUNDED_FOLLOWING);
    }

    /** Sets a ROWS window with a lower bound,
     * equivalent to SQL {@code ROWS BETWEEN lower AND CURRENT ROW}. */
    default OverCall rowsFrom(RexWindowBound lower) {
      return rowsBetween(lower, RexWindowBounds.UNBOUNDED_FOLLOWING);
    }

    /** Sets a ROWS window with an upper bound,
     * equivalent to SQL {@code ROWS BETWEEN CURRENT ROW AND upper}. */
    default OverCall rowsTo(RexWindowBound upper) {
      return rowsBetween(RexWindowBounds.UNBOUNDED_PRECEDING, upper);
    }

    /** Sets a RANGE window with lower and upper bounds,
     * equivalent to SQL {@code ROWS BETWEEN lower ROW AND upper}. */
    OverCall rowsBetween(RexWindowBound lower, RexWindowBound upper);

    /** Sets an unbounded RANGE window,
     * equivalent to SQL {@code RANGE BETWEEN UNBOUNDED PRECEDING AND
     * UNBOUNDED FOLLOWING}. */
    default OverCall rangeUnbounded() {
      return rangeBetween(RexWindowBounds.UNBOUNDED_PRECEDING,
          RexWindowBounds.UNBOUNDED_FOLLOWING);
    }

    /** Sets a RANGE window with a lower bound,
     * equivalent to SQL {@code RANGE BETWEEN lower AND CURRENT ROW}. */
    default OverCall rangeFrom(RexWindowBound lower) {
      return rangeBetween(lower, RexWindowBounds.CURRENT_ROW);
    }

    /** Sets a RANGE window with an upper bound,
     * equivalent to SQL {@code RANGE BETWEEN CURRENT ROW AND upper}. */
    default OverCall rangeTo(RexWindowBound upper) {
      return rangeBetween(RexWindowBounds.UNBOUNDED_PRECEDING, upper);
    }

    /** Sets a RANGE window with lower and upper bounds,
     * equivalent to SQL {@code RANGE BETWEEN lower ROW AND upper}. */
    OverCall rangeBetween(RexWindowBound lower, RexWindowBound upper);

    /** Sets whether to allow partial width windows; default true. */
    OverCall allowPartial(boolean allowPartial);

    /** Sets whether the aggregate function should evaluate to null if no rows
     * are in the window; default false. */
    OverCall nullWhenCountZero(boolean nullWhenCountZero);

    /** Sets the alias of this expression, and converts it to a {@link RexNode};
     * default is the alias that was set via {@link AggCall#as(String)}. */
    RexNode as(String alias);

    /** Converts this expression to a {@link RexNode}. */
    RexNode toRex();
  }

  /** Implementation of {@link OverCall}. */
  private class OverCallImpl implements OverCall {
    private final ImmutableList<RexNode> operands;
    private final boolean ignoreNulls;
    private final @Nullable String alias;
    private final boolean nullWhenCountZero;
    private final boolean allowPartial;
    private final boolean rows;
    private final RexWindowBound lowerBound;
    private final RexWindowBound upperBound;
    private final ImmutableList<RexNode> partitionKeys;
    private final ImmutableList<RexFieldCollation> sortKeys;
    private final SqlAggFunction op;
    private final boolean distinct;

    private OverCallImpl(SqlAggFunction op, boolean distinct,
        ImmutableList<RexNode> operands, boolean ignoreNulls,
        @Nullable String alias, ImmutableList<RexNode> partitionKeys,
        ImmutableList<RexFieldCollation> sortKeys, boolean rows,
        RexWindowBound lowerBound, RexWindowBound upperBound,
        boolean nullWhenCountZero, boolean allowPartial) {
      this.op = op;
      this.distinct = distinct;
      this.operands = operands;
      this.ignoreNulls = ignoreNulls;
      this.alias = alias;
      this.partitionKeys = partitionKeys;
      this.sortKeys = sortKeys;
      this.nullWhenCountZero = nullWhenCountZero;
      this.allowPartial = allowPartial;
      this.rows = rows;
      this.lowerBound = lowerBound;
      this.upperBound = upperBound;
    }

    /** Creates an OverCallImpl with default settings. */
    OverCallImpl(SqlAggFunction op, boolean distinct,
        ImmutableList<RexNode> operands, boolean ignoreNulls,
        @Nullable String alias) {
      this(op, distinct, operands, ignoreNulls, alias, ImmutableList.of(),
          ImmutableList.of(), true, RexWindowBounds.UNBOUNDED_PRECEDING,
          RexWindowBounds.UNBOUNDED_FOLLOWING, false, true);
    }

    @Override public OverCall partitionBy(
        Iterable<? extends RexNode> expressions) {
      return partitionBy_(ImmutableList.copyOf(expressions));
    }

    @Override public OverCall partitionBy(RexNode... expressions) {
      return partitionBy_(ImmutableList.copyOf(expressions));
    }

    private OverCall partitionBy_(ImmutableList<RexNode> partitionKeys) {
      return new OverCallImpl(op, distinct, operands, ignoreNulls, alias,
          partitionKeys, sortKeys, rows, lowerBound, upperBound,
          nullWhenCountZero, allowPartial);
    }

    private OverCall orderBy_(ImmutableList<RexFieldCollation> sortKeys) {
      return new OverCallImpl(op, distinct, operands, ignoreNulls, alias,
          partitionKeys, sortKeys, rows, lowerBound, upperBound,
          nullWhenCountZero, allowPartial);
    }

    @Override public OverCall orderBy(Iterable<? extends RexNode> sortKeys) {
      ImmutableList.Builder<RexFieldCollation> fieldCollations =
          ImmutableList.builder();
      sortKeys.forEach(sortKey ->
          fieldCollations.add(
              rexCollation(sortKey, RelFieldCollation.Direction.ASCENDING,
                  RelFieldCollation.NullDirection.UNSPECIFIED)));
      return orderBy_(fieldCollations.build());
    }

    @Override public OverCall orderBy(RexNode... sortKeys) {
      return orderBy(Arrays.asList(sortKeys));
    }

    @Override public OverCall rowsBetween(RexWindowBound lowerBound,
        RexWindowBound upperBound) {
      return new OverCallImpl(op, distinct, operands, ignoreNulls, alias,
          partitionKeys, sortKeys, true, lowerBound, upperBound,
          nullWhenCountZero, allowPartial);
    }

    @Override public OverCall rangeBetween(RexWindowBound lowerBound,
        RexWindowBound upperBound) {
      return new OverCallImpl(op, distinct, operands, ignoreNulls, alias,
          partitionKeys, sortKeys, false, lowerBound, upperBound,
          nullWhenCountZero, allowPartial);
    }

    @Override public OverCall allowPartial(boolean allowPartial) {
      return new OverCallImpl(op, distinct, operands, ignoreNulls, alias,
          partitionKeys, sortKeys, rows, lowerBound, upperBound,
          nullWhenCountZero, allowPartial);
    }

    @Override public OverCall nullWhenCountZero(boolean nullWhenCountZero) {
      return new OverCallImpl(op, distinct, operands, ignoreNulls, alias,
          partitionKeys, sortKeys, rows, lowerBound, upperBound,
          nullWhenCountZero, allowPartial);
    }

    @Override public RexNode as(String alias) {
      return new OverCallImpl(op, distinct, operands, ignoreNulls, alias,
          partitionKeys, sortKeys, rows, lowerBound, upperBound,
          nullWhenCountZero, allowPartial).toRex();
    }

    @Override public RexNode toRex() {
      final RexCallBinding bind =
          new RexCallBinding(getTypeFactory(), op, operands,
              ImmutableList.of()) {
            @Override public int getGroupCount() {
              return SqlWindow.isAlwaysNonEmpty(lowerBound, upperBound) ? 1 : 0;
            }
          };
      final RelDataType type = op.inferReturnType(bind);
      final RexNode over = getRexBuilder()
          .makeOver(type, op, operands, partitionKeys, sortKeys,
              lowerBound, upperBound, rows, allowPartial, nullWhenCountZero,
              distinct, ignoreNulls);
      return alias == null ? over : alias(over, alias);
    }
  }

  /** Collects the extra expressions needed for {@link #aggregate}.
   *
   * <p>The extra expressions come from the group key and as arguments to
   * aggregate calls, and later there will be a {@link #project} or a
   * {@link #rename(List)} if necessary. */
  private static class Registrar {
    final List<RexNode> originalExtraNodes;
    final List<RexNode> extraNodes;
    final List<@Nullable String> names;

    Registrar(Iterable<RexNode> fields, List<String> fieldNames) {
      originalExtraNodes = ImmutableList.copyOf(fields);
      extraNodes = new ArrayList<>(originalExtraNodes);
      names = new ArrayList<>(fieldNames);
    }

    int registerExpression(RexNode node) {
      switch (node.getKind()) {
      case AS:
        final List<RexNode> operands = ((RexCall) node).operands;
        final int i = registerExpression(operands.get(0));
        names.set(i, RexLiteral.stringValue(operands.get(1)));
        return i;
      case DESCENDING:
      case NULLS_FIRST:
      case NULLS_LAST:
        return registerExpression(((RexCall) node).operands.get(0));
      default:
        final int i2 = extraNodes.indexOf(node);
        if (i2 >= 0) {
          return i2;
        }
        extraNodes.add(node);
        names.add(null);
        return extraNodes.size() - 1;
      }
    }

    List<Integer> registerExpressions(Iterable<? extends RexNode> nodes) {
      final List<Integer> builder = new ArrayList<>();
      for (RexNode node : nodes) {
        builder.add(registerExpression(node));
      }
      return builder;
    }

    List<RelFieldCollation> registerFieldCollations(
        Iterable<? extends RexNode> orderKeys) {
      final List<RelFieldCollation> fieldCollations = new ArrayList<>();
      for (RexNode orderKey : orderKeys) {
        final RelFieldCollation collation =
            collation(orderKey, RelFieldCollation.Direction.ASCENDING, null,
                extraNodes);
        if (!RelCollations.ordinals(fieldCollations)
            .contains(collation.getFieldIndex())) {
          fieldCollations.add(collation);
        }
      }
      return ImmutableList.copyOf(fieldCollations);
    }

    /** Returns the number of fields added. */
    int addedFieldCount() {
      return extraNodes.size() - originalExtraNodes.size();
    }
  }

  /** Builder stack frame.
   *
   * <p>Describes a previously created relational expression and
   * information about how table aliases map into its row type. */
  private static class Frame {
    final RelNode rel;
    final ImmutableList<Field> fields;

    private Frame(RelNode rel, ImmutableList<Field> fields) {
      this.rel = rel;
      this.fields = fields;
    }

    private Frame(RelNode rel) {
      String tableAlias = deriveAlias(rel);
      ImmutableList.Builder<Field> builder = ImmutableList.builder();
      ImmutableSet<String> aliases = tableAlias == null
          ? ImmutableSet.of()
          : ImmutableSet.of(tableAlias);
      for (RelDataTypeField field : rel.getRowType().getFieldList()) {
        builder.add(new Field(aliases, field));
      }
      this.rel = rel;
      this.fields = builder.build();
    }

    @Override public String toString() {
      return rel + ": " + fields;
    }

    private static @Nullable String deriveAlias(RelNode rel) {
      if (rel instanceof TableScan) {
        TableScan scan = (TableScan) rel;
        final List<String> names = scan.getTable().getQualifiedName();
        if (!names.isEmpty()) {
          return Util.last(names);
        }
      }
      return null;
    }

    List<RelDataTypeField> fields() {
      return Pair.right(fields);
    }
  }

  /** A field that belongs to a stack {@link Frame}. */
  private static class Field
      extends Pair<ImmutableSet<String>, RelDataTypeField> {
    Field(ImmutableSet<String> left, RelDataTypeField right) {
      super(left, right);
    }

    Field addAlias(String alias) {
      if (left.contains(alias)) {
        return this;
      }
      final ImmutableSet<String> aliasList =
          ImmutableSet.<String>builder().addAll(left).add(alias).build();
      return new Field(aliasList, right);
    }
  }

  /** Shuttle that shifts a predicate's inputs to the left, replacing early
   * ones with references to a
   * {@link RexCorrelVariable}. */
  private class Shifter extends RexShuttle {
    private final RelNode left;
    private final CorrelationId id;
    private final RelNode right;

    Shifter(RelNode left, CorrelationId id, RelNode right) {
      this.left = left;
      this.id = id;
      this.right = right;
    }

    @Override public RexNode visitInputRef(RexInputRef inputRef) {
      final RelDataType leftRowType = left.getRowType();
      final RexBuilder rexBuilder = getRexBuilder();
      final int leftCount = leftRowType.getFieldCount();
      if (inputRef.getIndex() < leftCount) {
        final RexNode v = rexBuilder.makeCorrel(leftRowType, id);
        return rexBuilder.makeFieldAccess(v, inputRef.getIndex());
      } else {
        return rexBuilder.makeInputRef(right, inputRef.getIndex() - leftCount);
      }
    }
  }

  /** Configuration of RelBuilder.
   *
   * <p>It is immutable, and all fields are public.
   *
   * <p>Start with the {@link #DEFAULT} instance,
   * and call {@code withXxx} methods to set its properties. */
  @Value.Immutable
  public interface Config {
    /** Default configuration. */
    Config DEFAULT = ImmutableRelBuilder.Config.of();

    /** Controls whether to merge two {@link Project} operators when inlining
     * expressions causes complexity to increase.
     *
     * <p>Usually merging projects is beneficial, but occasionally the
     * result is more complex than the original projects. Consider:
     *
     * <pre>
     * P: Project(a+b+c AS x, d+e+f AS y, g+h+i AS z)  # complexity 15
     * Q: Project(x*y*z AS p, x-y-z AS q)              # complexity 10
     * R: Project((a+b+c)*(d+e+f)*(g+h+i) AS s,
     *            (a+b+c)-(d+e+f)-(g+h+i) AS t)        # complexity 34
     * </pre>
     *
     * The complexity of an expression is the number of nodes (leaves and
     * operators). For example, {@code a+b+c} has complexity 5 (3 field
     * references and 2 calls):
     *
     * <pre>
     *       +
     *      /  \
     *     +    c
     *    / \
     *   a   b
     * </pre>
     *
     * <p>A negative value never allows merges.
     *
     * <p>A zero or positive value, {@code bloat}, allows a merge if complexity
     * of the result is less than or equal to the sum of the complexity of the
     * originals plus {@code bloat}.
     *
     * <p>The default value, 100, allows a moderate increase in complexity but
     * prevents cases where complexity would run away into the millions and run
     * out of memory. Moderate complexity is OK; the implementation, say via
     * {@link org.apache.calcite.adapter.enumerable.EnumerableCalc}, will often
     * gather common sub-expressions and compute them only once.
     */
    @Value.Default default int bloat() {
      return 100;
    }

    /** Sets {@link #bloat}. */
    Config withBloat(int bloat);

    /** Whether {@link RelBuilder#aggregate} should eliminate duplicate
     * aggregate calls; default true. */
    @Value.Default default boolean dedupAggregateCalls() {
      return true;
    }

    /** Sets {@link #dedupAggregateCalls}. */
    Config withDedupAggregateCalls(boolean dedupAggregateCalls);

    /** Whether {@link RelBuilder#aggregate} should prune unused
     * input columns; default true. */
    @Value.Default default boolean pruneInputOfAggregate() {
      return true;
    }

    /** Sets {@link #pruneInputOfAggregate}. */
    Config withPruneInputOfAggregate(boolean pruneInputOfAggregate);

    /** Whether to push down join conditions; default false (but
     * {@link SqlToRelConverter#config()} by default sets this to true). */
    @Value.Default default boolean pushJoinCondition() {
      return false;
    }

    /** Sets {@link #pushJoinCondition()}. */
    Config withPushJoinCondition(boolean pushJoinCondition);

    /** Whether to simplify expressions; default true. */
    @Value.Default default boolean simplify() {
      return true;
    }

    /** Sets {@link #simplify}. */
    Config withSimplify(boolean simplify);

    /** Whether to simplify LIMIT 0 to an empty relation; default true. */
    @Value.Default default boolean simplifyLimit() {
      return true;
    }

    /** Sets {@link #simplifyLimit()}. */
    Config withSimplifyLimit(boolean simplifyLimit);

    /** Whether to simplify {@code Union(Values, Values)} or
     * {@code Union(Project(Values))} to {@code Values}; default true. */
    @Value.Default default boolean simplifyValues() {
      return true;
    }

    /** Sets {@link #simplifyValues()}. */
    Config withSimplifyValues(boolean simplifyValues);

    /** Whether to create an Aggregate even if we know that the input is
     * already unique; default false. */
    @Value.Default default boolean aggregateUnique() {
      return false;
    }

    /** Sets {@link #aggregateUnique()}. */
    Config withAggregateUnique(boolean aggregateUnique);
  }

}
