/*
 * 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.drill.exec.physical.impl.scan.project;

import java.util.ArrayList;
import java.util.List;

import org.apache.drill.common.exceptions.CustomErrorContext;
import org.apache.drill.common.expression.SchemaPath;
import org.apache.drill.exec.physical.impl.scan.project.AbstractUnresolvedColumn.UnresolvedColumn;
import org.apache.drill.exec.physical.impl.scan.project.AbstractUnresolvedColumn.UnresolvedWildcardColumn;
import org.apache.drill.exec.physical.impl.scan.project.projSet.ProjectionSetBuilder;
import org.apache.drill.exec.physical.rowSet.project.ImpliedTupleRequest;
import org.apache.drill.exec.physical.rowSet.project.RequestedTuple;
import org.apache.drill.exec.physical.rowSet.project.RequestedTuple.RequestedColumn;
import org.apache.drill.exec.physical.rowSet.project.RequestedTupleImpl;
import org.apache.drill.exec.record.metadata.ColumnMetadata;
import org.apache.drill.exec.record.metadata.TupleMetadata;
import org.apache.drill.shaded.guava.com.google.common.annotations.VisibleForTesting;

/**
 * Parses and analyzes the projection list passed to the scanner. The
 * scanner accepts a projection list and a plugin-specific set of items
 * to read. The scan operator produces a series of output batches, which
 * (in the best case) all have the same schema. Since Drill is "schema
 * on read", in practice batch schema may evolve. The framework tries
 * to "smooth" such changes where possible. An output schema adds another
 * level of stability by specifying the set of columns to project (for
 * wildcard queries) and the types of those columns (for all queries.)
 * <p>
 * The projection list is per scan, independent of any tables that the
 * scanner might scan. The projection list is then used as input to the
 * per-table projection planning.
 *
 * <h4>Overview</h4>
 *
 * In most query engines, this kind of projection analysis is done at
 * plan time. But, since Drill is schema-on-read, we don't know the
 * available columns, or their types, until we start scanning a table.
 * The table may provide the schema up-front, or may discover it as
 * the read proceeds. Hence, the job here is to make sense of the
 * project list based on static a-priori information, then to create
 * a list that can be further resolved against an table schema when it
 * appears. This give us two steps:
 * <ul>
 * <li>Scan-level projection: this class, that handles schema for the
 * entire scan operator.</li>
 * <li>Table-level projection: defined elsewhere, that merges the
 * table and scan-level projections.
 * </ul>
 * <p>
 * Accepts the inputs needed to plan a projection, builds the mappings,
 * and constructs the projection mapping object.
 * <p>
 * Builds the per-scan projection plan given a set of projected columns.
 * Determines the output schema, which columns to project from the data
 * source, which are metadata, and so on.
 * <p>
 * An annoying aspect of SQL is that the projection list (the list of
 * columns to appear in the output) is specified after the SELECT keyword.
 * In Relational theory, projection is about columns, selection is about
 * rows...
 *
 * <h4>Projection Mappings</h4>
 *
 * Mappings can be based on three primary use cases:
 * <p><ul>
 * <li><tt>SELECT *</tt>: Project all data source columns, whatever they happen
 * to be. Create columns using names from the data source. The data source
 * also determines the order of columns within the row.</li>
 * <li><tt>SELECT columns</tt>: Similar to SELECT * in that it projects all columns
 * from the data source, in data source order. But, rather than creating
 * individual output columns for each data source column, creates a single
 * column which is an array of Varchars which holds the (text form) of
 * each column as an array element.</li>
 * <li><tt>SELECT a, b, c, ...</tt>: Project a specific set of columns, identified by
 * case-insensitive name. The output row uses the names from the SELECT list,
 * but types from the data source. Columns appear in the row in the order
 * specified by the SELECT.</li>
 * <li<tt>SELECT ...</tt>: SELECT nothing, occurs in <tt>SELECT COUNT(*)</tt>
 * type queries. The provided projection list contains no (table) columns, though
 * it may contain metadata columns.</li>
 * </ul>
 * Names in the SELECT list can reference any of five distinct types of output
 * columns:
 * <p><ul>
 * <li>Wildcard ("*") column: indicates the place in the projection list to insert
 * the table columns once found in the table projection plan.</li>
 * <li>Data source columns: columns from the underlying table. The table
 * projection planner will determine if the column exists, or must be filled
 * in with a null column.</li>
 * <li>The generic data source columns array: <tt>columns</tt>, or optionally
 * specific members of the <tt>columns</tt> array such as <tt>columns[1]</tt>.</li>
 * <li>Implicit columns: <tt>fqn</tt>, <tt>filename</tt>, <tt>filepath</tt>
 * and <tt>suffix</tt>. These reference
 * parts of the name of the file being scanned.</li>
 * <li>Partition columns: <tt>dir0</tt>, <tt>dir1</tt>, ...: These reference
 * parts of the path name of the file.</li>
 * </ul>
 *
 * <h4>Projection with a Schema</h4>
 *
 * The client can provide an <i>output schema</i> that defines the types (and
 * defaults) for the tuple produced by the scan. When a schema is provided,
 * the above use cases are extended as follows:
 * <p><ul>
 * <li><tt>SELECT *</tt> with strict schema: All columns in the output schema
 * are projected, and only those columns. If a reader offers additional columns,
 * those columns are ignored. If the reader omits output columns, the default value
 * (if any) for the column is used.</li>
 * <li><tt>SELECT *</tt> with a non-strict schema: the output tuple contains all
 * columns from the output schema as explained above. In addition, if the reader
 * provides any columns not in the output schema, those columns are appended to
 * the end of the tuple. (That is, the output schema acts as it it were from
 * an imaginary "0th" reader.)</li>
 * <li>Explicit projection: only the requested columns appear, whether from the
 * output schema, the reader, or  as nulls.</li>
 * </ul>
 * <p>
 * @see {@link ImplicitColumnExplorer}, the class from which this class
 * evolved
 */

public class ScanLevelProjection {

  /**
   * Identifies the kind of projection done for this scan.
   */
  public enum ScanProjectionType {

    /**
     * No projection. Occurs for SELECT COUNT(*) ... queries.
     */
    EMPTY,

    /**
     * Wildcard. Occurs for SELECT * ... queries when no output schema is
     * available. The scan projects all columns from all readers, using the
     * type from that reader. Schema "smoothing", if enabled, will attempt
     * to preserve column order, type and mode from one reader to the next.
     */
    WILDCARD,

    /**
     * Explicit projection. Occurs for SELECT a, b, c ... queries, whether or
     * not an output schema is present. In this case, the projection list
     * identifies the set of columns to project and their order. The output
     * schema, if present, specifies data types and modes.
     */
    EXPLICIT,

    /**
     * Wildcard query expanded using an output schema. Occurs for a
     * SELECT * ... query with an output schema. The set of projected columns
     * are those from the output schema, in the order specified by the schema,
     * with names (and name case) specified by the schema. In this mode, the
     * schema is partial: readers may include additional columns which are
     * appended to those provided by the schema.
     * <p>
     * TODO: Provide a strict mode that forces the use of the types and modes
     * from the output schema. In lenient mode, the framework will adjust
     * mode to allow the query to succeed (changing a required mode to
     * optional, say, if the column is not provided by the reader and has
     * no default. Strict mode would fail the query in this case.)
     * <p>
     * TODO: Enable schema smoothing in this case: use that mechanism to
     * smooth over the "extra" reader columns.
     */
    SCHEMA_WILDCARD,

    /**
     * Wldcard query expanded using an output schema in "strict" mode.
     * Only columns from the output schema will be projected. Unlike the
     * {@link SCHEMA_WILDCARD} mode, if a reader offers columns not in the
     * output schema, they will be ignored. That is, a SELECT * query expands
     * to exactly the columns in the schema.
     * <p>
     * TODO: Provide a strict column mode that will fail the query if a projected
     * column is required, has no default, and is not provided by the reader. In
     * the normal lenient mode, the scan framework will adjust the data mode to
     * optional so that the query will run.
     */
    STRICT_SCHEMA_WILDCARD;

    public boolean isWildcard() {
      return this == WILDCARD ||
             this == SCHEMA_WILDCARD ||
             this == STRICT_SCHEMA_WILDCARD;
    }
  }

  /**
   * Interface for add-on parsers, avoids the need to create
   * a single, tightly-coupled parser for all types of columns.
   * The main parser handles wildcards and assumes the rest of
   * the columns are table columns. The add-on parser can tag
   * columns as special, such as to hold metadata.
   */

  public interface ScanProjectionParser {
    void bind(ScanLevelProjection builder);
    boolean parse(RequestedColumn inCol);
    void validate();
    void validateColumn(ColumnProjection col);
    void build();
  }

  public static class Builder {
    private List<SchemaPath> projectionList;
    private List<ScanProjectionParser> parsers = new ArrayList<>();
    private TupleMetadata outputSchema;
    /**
     * Context used with error messages.
     */
    protected CustomErrorContext errorContext;

    /**
     * Specify the set of columns in the SELECT list. Since the column list
     * comes from the query planner, assumes that the planner has checked
     * the list for syntax and uniqueness.
     *
     * @param queryCols list of columns in the SELECT list in SELECT list order
     * @return this builder
     */
    public Builder projection(List<SchemaPath> projectionList) {
      this.projectionList = projectionList;
      return this;
    }

    public Builder parsers(List<ScanProjectionParser> parsers) {
      this.parsers.addAll(parsers);
      return this;
    }

    public Builder outputSchema(TupleMetadata outputSchema) {
      this.outputSchema = outputSchema;
      return this;
    }

    public Builder context(CustomErrorContext context) {
      this.errorContext = context;
      return this;
    }

    public ScanLevelProjection build() {
      return new ScanLevelProjection(this);
    }

    public TupleMetadata outputSchema( ) {
      return outputSchema == null || outputSchema.size() == 0
          ? null : outputSchema;
    }

    public List<SchemaPath> projectionList() {
      if (projectionList == null) {
        projectionList = new ArrayList<>();
        projectionList.add(SchemaPath.STAR_COLUMN);
      }
      return projectionList;
    }
  }

  // Input

  /**
   * Context used with error messages.
   */
  protected final CustomErrorContext errorContext;
  protected final List<SchemaPath> projectionList;
  protected final TupleMetadata outputSchema;

  // Configuration

  protected List<ScanProjectionParser> parsers;

  // Internal state

  protected boolean includesWildcard;
  protected boolean sawWildcard;

  // Output

  protected List<ColumnProjection> outputCols = new ArrayList<>();

  /**
   * Projection definition for the scan a whole. Parsed form of the input
   * projection list.
   */

  protected RequestedTuple outputProjection;

  /**
   * Projection definition passed to each reader. This is the set of
   * columns that the reader is asked to provide.
   */

  protected RequestedTuple readerProjection;
  protected ScanProjectionType projectionType = ScanProjectionType.EMPTY;

  private ScanLevelProjection(Builder builder) {
    this.projectionList = builder.projectionList();
    this.parsers = builder.parsers;
    this.outputSchema = builder.outputSchema();
    this.errorContext = builder.errorContext;
    doParse();
  }

  public static Builder builder() {
    return new Builder();
  }

  /**
   * Builder shortcut, primarily for tests.
   */
  @VisibleForTesting
  public static ScanLevelProjection build(List<SchemaPath> projectionList,
      List<ScanProjectionParser> parsers) {
    return new Builder()
        .projection(projectionList)
        .parsers(parsers)
        .build();
  }

  /**
   * Builder shortcut, primarily for tests.
   */
  @VisibleForTesting
  public static ScanLevelProjection build(List<SchemaPath> projectionList,
      List<ScanProjectionParser> parsers,
      TupleMetadata outputSchema) {
    return new Builder()
        .projection(projectionList)
        .parsers(parsers)
        .outputSchema(outputSchema)
        .build();
  }

  private void doParse() {
    outputProjection = RequestedTupleImpl.parse(projectionList);

    for (ScanProjectionParser parser : parsers) {
      parser.bind(this);
    }

    // First pass: check if a wildcard exists.

    for (RequestedColumn inCol : outputProjection.projections()) {
      if (inCol.isWildcard()) {
        includesWildcard = true;
        break;
      }
    }

    // Second pass: process projected columns.

    for (RequestedColumn inCol : outputProjection.projections()) {
      if (inCol.isWildcard()) {
        mapWildcard(inCol);
      } else {
        mapColumn(inCol);
      }
    }
    verify();
    for (ScanProjectionParser parser : parsers) {
      parser.build();
    }

    buildReaderProjection();
  }

  private void buildReaderProjection() {

    // Create the reader projection which includes either all columns
    // (saw a wildcard) or just the unresolved columns (which excludes
    // implicit columns.)
    //
    // Note that only the wildcard without schema can omit the output
    // projection. With a schema, we want the schema columns (which may
    // or may not correspond to reader columns.)

    if (projectionType != ScanProjectionType.EMPTY &&
        projectionType != ScanProjectionType.EXPLICIT) {

      readerProjection = ImpliedTupleRequest.ALL_MEMBERS;
    } else {

      List<RequestedColumn> outputProj = new ArrayList<>();
      for (ColumnProjection col : outputCols) {
        if (col instanceof AbstractUnresolvedColumn) {
          outputProj.add(((AbstractUnresolvedColumn) col).element());
        }
      }
      readerProjection = RequestedTupleImpl.build(outputProj);
    }
  }

  /**
   * Wildcard is special: add it, then let parsers add any custom
   * columns that are needed. The order is important: we want custom
   * columns to follow table columns.
   */

  private void mapWildcard(RequestedColumn inCol) {

    // Wildcard column: this is a SELECT * query.

    assert includesWildcard;
    if (sawWildcard) {
      throw new IllegalArgumentException("Duplicate * entry in project list");
    }

    // Expand strict schema columns, if provided

    boolean expanded = expandOutputSchema();

    // Remember the wildcard position, if we need to insert it.
    // Ensures that the main wildcard expansion occurs before add-on
    // columns.

    int wildcardPosn = outputCols.size();

    // Parsers can consume the wildcard. But, all parsers must
    // have visibility to the wildcard column.

    for (ScanProjectionParser parser : parsers) {
      if (parser.parse(inCol)) {
        wildcardPosn = -1;
      }
    }

    // Set this flag only after the parser checks.

    sawWildcard = true;

    // If not consumed, put the wildcard column into the projection list as a
    // placeholder to be filled in later with actual table columns.

    if (expanded) {
      projectionType =
          outputSchema.booleanProperty(TupleMetadata.IS_STRICT_SCHEMA_PROP)
          ? ScanProjectionType.STRICT_SCHEMA_WILDCARD
          : ScanProjectionType.SCHEMA_WILDCARD;
    } else if (wildcardPosn != -1) {
      outputCols.add(wildcardPosn, new UnresolvedWildcardColumn(inCol));
      projectionType = ScanProjectionType.WILDCARD;
    }
  }

  private boolean expandOutputSchema() {
    if (outputSchema == null) {
      return false;
    }

    // Expand the wildcard. From the perspective of the reader, this is an explicit
    // projection, so enumerate the columns as though they were in the project list.
    // Take the projection type from the output column's data type. That is,
    // INT[] is projected as ARRAY, etc.

    for (int i = 0; i < outputSchema.size(); i++) {
      ColumnMetadata col = outputSchema.metadata(i);

      // Skip columns tagged as "special"; those that should not expand
      // automatically.

      if (col.booleanProperty(ColumnMetadata.EXCLUDE_FROM_WILDCARD)) {
        continue;
      }
      outputCols.add(new UnresolvedColumn(null, col));
    }
    return true;
  }

  /**
   * Map the column into one of five categories.
   * <ol>
   * <li>Star column (to designate SELECT *)</li>
   * <li>Partition file column (dir0, dir1, etc.)</li>
   * <li>Implicit column (fqn, filepath, filename, suffix)</li>
   * <li>Special <tt>columns</tt> column which holds all columns as
   * an array.</li>
   * <li>Table column. The actual match against the table schema
   * is done later.</li>
   * </ol>
   *
   * Actual mapping is done by parser extensions for all but the
   * basic cases.
   *
   * @param inCol the SELECT column
   */

  private void mapColumn(RequestedColumn inCol) {

    // Give the extensions first crack at each column.
    // Some may want to "sniff" a column, even if they
    // don't fully handle it.

    for (ScanProjectionParser parser : parsers) {
      if (parser.parse(inCol)) {
        return;
      }
    }

    // If the project list has a wildcard, and the column is not one recognized
    // by the specialized parsers above, then just ignore it. It is likely a duplicate
    // column name. In any event, it will be processed by the Project operator on
    // top of this scan.

    if (includesWildcard) {
      return;
    }

    // This is a desired table column.

    addTableColumn(inCol);
  }

  private void addTableColumn(RequestedColumn inCol) {
    ColumnMetadata outputCol = null;
    if (outputSchema != null) {
      outputCol = outputSchema.metadata(inCol.name());
    }
    addTableColumn(new UnresolvedColumn(inCol, outputCol));
  }

  public void addTableColumn(ColumnProjection outCol) {
    outputCols.add(outCol);
    projectionType = ScanProjectionType.EXPLICIT;
  }

  public void addMetadataColumn(ColumnProjection outCol) {
    outputCols.add(outCol);
  }

  /**
   * Once all columns are identified, perform a final pass
   * over the set of columns to do overall validation. Each
   * add-on parser is given an opportunity to do its own
   * validation.
   */

  private void verify() {

    // Let parsers do overall validation.

    for (ScanProjectionParser parser : parsers) {
      parser.validate();
    }

    // Validate column-by-column.

    for (ColumnProjection outCol : outputCols) {
      for (ScanProjectionParser parser : parsers) {
        parser.validateColumn(outCol);
      }
    }
  }

  public CustomErrorContext context() { return errorContext; }

  /**
   * Return the set of columns from the SELECT list
   * @return the SELECT list columns, in SELECT list order
   */

  public List<SchemaPath> requestedCols() { return projectionList; }

  /**
   * The entire set of output columns, in output order. Output order is
   * that specified in the SELECT (for an explicit list of columns) or
   * table order (for SELECT * queries).
   * @return the set of output columns in output order
   */

  public List<ColumnProjection> columns() { return outputCols; }

  public ScanProjectionType projectionType() { return projectionType; }

  /**
   * Return whether this is a SELECT * query
   * @return true if this is a SELECT * query
   */

  public boolean projectAll() { return projectionType.isWildcard(); }

  /**
   * Returns true if the projection list is empty. This usually
   * indicates a <tt>SELECT COUNT(*)</tt> query (though the scan
   * operator does not have the context to know that an empty
   * list does, in fact, imply a count-only query...)
   *
   * @return true if no table columns are projected, false
   * if at least one column is projected (or the query contained
   * the wildcard)
   */

  public boolean isEmptyProjection() { return projectionType == ScanProjectionType.EMPTY; }

  public RequestedTuple rootProjection() { return outputProjection; }

  public ProjectionSetBuilder projectionSet() {
    return new ProjectionSetBuilder()
      .outputSchema(outputSchema)
      .parsedProjection(readerProjection)
      .errorContext(errorContext);
  }

  public boolean hasOutputSchema() { return outputSchema != null; }

  public TupleMetadata outputSchema() { return outputSchema; }

  @Override
  public String toString() {
    return new StringBuilder()
        .append("[")
        .append(getClass().getSimpleName())
        .append(" projection=")
        .append(outputCols.toString())
        .append("]")
        .toString();
  }
}
