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

#ifndef QUICKSTEP_PARSER_PARSE_STATEMENT_HPP_
#define QUICKSTEP_PARSER_PARSE_STATEMENT_HPP_

#include <memory>
#include <string>
#include <vector>

#include "parser/ParseAssignment.hpp"
#include "parser/ParseAttributeDefinition.hpp"
#include "parser/ParseBasicExpressions.hpp"
#include "parser/ParseBlockProperties.hpp"
#include "parser/ParseIndexProperties.hpp"
#include "parser/ParseKeyValue.hpp"
#include "parser/ParsePartitionClause.hpp"
#include "parser/ParsePredicate.hpp"
#include "parser/ParsePriority.hpp"
#include "parser/ParseSelect.hpp"
#include "parser/ParseString.hpp"
#include "parser/ParseSubqueryTableReference.hpp"
#include "parser/ParseTreeNode.hpp"
#include "storage/StorageBlockInfo.hpp"
#include "utility/Macros.hpp"
#include "utility/PtrList.hpp"
#include "utility/PtrVector.hpp"

#include "glog/logging.h"

namespace quickstep {

/** \addtogroup Parser
 *  @{
 */

/**
 * @brief Abstract base class for all complete SQL commands.
 **/
class ParseStatement : public ParseTreeNode {
 public:
  /**
   * @brief The possible types of SQL statements.
   **/
  enum StatementType {
    kCreateTable,
    kCreateIndex,
    kDropTable,
    kSelect,
    kInsert,
    kCopyFrom,
    kUpdate,
    kDelete,
    kQuit,
    kCommand
  };

  /**
   * @brief Virtual destructor.
   **/
  ~ParseStatement() override {
  }

  /**
   * @brief Identify the type of this SQL statement.
   *
   * @return The type of this statement.
   **/
  virtual StatementType getStatementType() const = 0;

  /**
   * @brief Get the priority of the SQL statement. Note that the priority is
   *        an unsigned non-zero integer.
   *
   * @return The priority of the SQL statement. The default priority is 1.
   **/
  virtual const std::uint64_t getPriority() const {
    return 1;
  }

 protected:
  ParseStatement(const int line_number, const int column_number)
      : ParseTreeNode(line_number, column_number) {
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ParseStatement);
};

/**
 * @brief The parsed representation of a CREATE TABLE statement.
 **/
class ParseStatementCreateTable : public ParseStatement {
 public:
  /**
   * @brief Constructor.
   *
   * @param relation_name The name of the relation to create.
   * @param attribute_definition_list The list of definitions for the
   *        attributes in the new relation, which becomes owned by this
   *        ParseStatementCreateTable.
   * @param opt_block_properties Optional physical properties of the block.
   **/
  ParseStatementCreateTable(const int line_number,
                            const int column_number,
                            ParseString *relation_name,
                            PtrList<ParseAttributeDefinition> *attribute_definition_list,
                            ParseBlockProperties *opt_block_properties,
                            ParsePartitionClause *opt_partition_clause)
      : ParseStatement(line_number, column_number),
        relation_name_(relation_name),
        attribute_definition_list_(attribute_definition_list),
        opt_block_properties_(opt_block_properties),
        opt_partition_clause_(opt_partition_clause) {
  }

  ~ParseStatementCreateTable() override {
  }

  StatementType getStatementType() const override {
    return kCreateTable;
  }

  std::string getName() const override { return "CreateTableStatement"; }

  /**
   * @brief Get the name of the relation to create.
   *
   * @return The new relation's name.
   **/
  const ParseString* relation_name() const {
    return relation_name_.get();
  }

  /**
   * @brief Get the list of attribute definitions.
   *
   * @return The list of attribute definitions for the new relation.
   **/
  const PtrList<ParseAttributeDefinition>& attribute_definition_list() const {
    return *attribute_definition_list_;
  }

  /**
   * @brief Get a pointer to the BlockProperties.
   *
   * @return The BlockProperties or nullptr if not specified.
   **/
  const ParseBlockProperties* opt_block_properties() const {
    return opt_block_properties_.get();
  }

  /**
   * @brief Get a pointer to the PartitionClause.
   *
   * @return The PartitionClause or nullptr if not specified.
   **/
  const ParsePartitionClause* opt_partition_clause() const {
    return opt_partition_clause_.get();
  }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    inline_field_names->push_back("relation_name");
    inline_field_values->push_back(relation_name_->value());

    container_child_field_names->push_back("attribute_list");
    container_child_fields->emplace_back();
    for (const ParseAttributeDefinition& attribute_definition : *attribute_definition_list_) {
      container_child_fields->back().push_back(&attribute_definition);
    }

    if (opt_block_properties_) {
      container_child_field_names->push_back("block_properties");
      container_child_fields->emplace_back();
      container_child_fields->back().push_back(opt_block_properties_.get());
    }

    if (opt_partition_clause_) {
      container_child_field_names->push_back("partition_clause");
      container_child_fields->emplace_back();
      container_child_fields->back().push_back(opt_partition_clause_.get());
    }
  }

 private:
  std::unique_ptr<ParseString> relation_name_;
  std::unique_ptr<PtrList<ParseAttributeDefinition> > attribute_definition_list_;
  std::unique_ptr<ParseBlockProperties> opt_block_properties_;
  std::unique_ptr<ParsePartitionClause> opt_partition_clause_;

  DISALLOW_COPY_AND_ASSIGN(ParseStatementCreateTable);
};

  /**
   * @brief The parsed representation of a CREATE INDEX statement.
   **/
class ParseStatementCreateIndex : public ParseStatement {
 public:
    /**
     * @brief Constructor.
     *
     * @param index_name The name of the index to create.
     * @param relation_name The name of the relation to create index upon.
     * @param attribute_name_list A list of attributes of the relation
     *        on which the index has to be created. If specified as null,
     *        then index is created on all the attributes.
     * @param index_type The type of index to create.
     **/
    ParseStatementCreateIndex(const int line_number,
                              const int column_number,
                              ParseString *index_name,
                              ParseString *relation_name,
                              PtrList<ParseAttribute> *attribute_list,
                              ParseString *index_type)
        : ParseStatement(line_number, column_number),
          index_name_(index_name),
          relation_name_(relation_name),
          attribute_list_(attribute_list),
          index_type_(index_type) {
      initializeIndexType();
    }

    /**
     * @brief Constructor.
     *
     * @param index_name The name of the index to create.
     * @param relation_name The name of the relation to create index upon.
     * @param attribute_name_list A list of attributes of the relation
     *        on which the index has to be created. If specified as null,
     *        then index is created on all the attributes.
     * @param index_type The type of index to create.
     * @param index_properties_line_number
     * @param index_properties_column_number
     * @param opt_index_properties Optional index properties that were specified.
     **/
    ParseStatementCreateIndex(const int line_number,
                              const int column_number,
                              ParseString *index_name,
                              ParseString *relation_name,
                              PtrList<ParseAttribute> *attribute_list,
                              ParseString *index_type,
                              const int index_properties_line_number,
                              const int index_properties_column_number,
                              PtrList<ParseKeyValue> *opt_index_properties)
        : ParseStatement(line_number, column_number),
          index_name_(index_name),
          relation_name_(relation_name),
          attribute_list_(attribute_list),
          index_type_(index_type) {
      initializeIndexType();
      custom_properties_node_.reset(new ParseIndexProperties(index_properties_line_number,
                                                                   index_properties_column_number,
                                                                   opt_index_properties));
      index_properties_->addCustomProperties(custom_properties_node_->getKeyValueList());
    }

    ~ParseStatementCreateIndex() override {
    }

    StatementType getStatementType() const override {
      return kCreateIndex;
    }

    std::string getName() const override { return "CreateIndexStatement"; }

    /**
     * @brief Get the name of the index to create.
     *
     * @return The index's name.
     **/
    const ParseString* index_name() const {
      return index_name_.get();
    }

    /**
     * @brief Get the name of the relation to create index upon.
     *
     * @return The relation's name.
     **/
    const ParseString* relation_name() const {
      return relation_name_.get();
    }

    /**
     * @brief Get the list of attributes on which index is supposed to be defined.
     *
     * @return The list of attributes on which index is to be built.
     **/
    const PtrList<ParseAttribute>* attribute_list() const {
      return attribute_list_.get();
    }

    /**
     * @brief Get the type of the index to be created.
     *
     * @return The index's type.
     **/
    const ParseString* index_type() const {
      return index_type_.get();
    }

    /**
     * @brief Get the index properties associated with this index type.
     *
     * @return The index properties for this type.
     **/
    const IndexProperties* getIndexProperties() const {
      return index_properties_.get();
    }

    const ParseIndexProperties* getCustomPropertiesNode() const {
      return custom_properties_node_.get();
    }

    bool hasCustomProperties() const {
      return custom_properties_node_ != nullptr;
    }

 protected:
    void getFieldStringItems(
       std::vector<std::string> *inline_field_names,
       std::vector<std::string> *inline_field_values,
       std::vector<std::string> *non_container_child_field_names,
       std::vector<const ParseTreeNode*> *non_container_child_fields,
       std::vector<std::string> *container_child_field_names,
       std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
      inline_field_names->push_back("index_name");
      inline_field_values->push_back(index_name_->value());

      inline_field_names->push_back("relation_name");
      inline_field_values->push_back(relation_name_->value());

      inline_field_names->push_back("index_type");
      const int index_type_enum_val = std::stoi(index_type_->value());
      switch (index_type_enum_val) {
        case IndexSubBlockType::kBitWeavingV:  // Fall through.
        case IndexSubBlockType::kBitWeavingH:
          inline_field_values->push_back("bitweaving");
          break;
        case IndexSubBlockType::kCSBTree:
          inline_field_values->push_back("cs_b_tree");
          break;
        case IndexSubBlockType::kBloomFilter:
          inline_field_values->push_back("bloom_filter");
          break;
        case IndexSubBlockType::kSMA:
          inline_field_values->push_back("sma");
          break;
        default:
          inline_field_values->push_back("unknown");
      }

      if (attribute_list_ != nullptr) {
        container_child_field_names->push_back("attribute_list");
        container_child_fields->emplace_back();
        for (const ParseAttribute &attribute : *attribute_list_) {
          container_child_fields->back().push_back(&attribute);
        }
      }

      if (custom_properties_node_ != nullptr) {
        container_child_field_names->push_back("index_property_list");
        container_child_fields->emplace_back();
        container_child_fields->back().push_back(custom_properties_node_.get());
      }
    }

 private:
    std::unique_ptr<ParseString> index_name_;
    std::unique_ptr<ParseString> relation_name_;
    std::unique_ptr<PtrList<ParseAttribute>> attribute_list_;
    std::unique_ptr<ParseString> index_type_;
    std::unique_ptr<IndexProperties> index_properties_;
    // Optional custom properties for the index can be specified during creation.
    std::unique_ptr<const ParseIndexProperties> custom_properties_node_;

    void initializeIndexType() {
      const int index_type_enum_val = std::stoi(index_type_->value());
      switch (index_type_enum_val) {
        case IndexSubBlockType::kBitWeavingV:  // Fall through.
        case IndexSubBlockType::kBitWeavingH:
          index_properties_.reset(new BitWeavingIndexProperties());
          break;
        case IndexSubBlockType::kBloomFilter:
          index_properties_.reset(new BloomFilterIndexProperties());
          break;
        case IndexSubBlockType::kCSBTree:
          index_properties_.reset(new CSBTreeIndexProperties());
          break;
        case IndexSubBlockType::kSMA:
          index_properties_.reset(new SMAIndexProperties());
          break;
        default:
          LOG(FATAL) << "Unknown index subblock type.";
          break;
      }
    }

    DISALLOW_COPY_AND_ASSIGN(ParseStatementCreateIndex);
};

/**
 * @brief The parsed representation of a DROP TABLE statement.
 **/
class ParseStatementDropTable : public ParseStatement {
 public:
  /**
   * @brief Constructor.
   *
   * @param line_number Line number of the first token of this node in the SQL statement.
   * @param column_number Column number of the first token of this node in the SQL statement.
   * @param relation_name The name of the relation to drop.
   **/
  ParseStatementDropTable(const int line_number, const int column_number, ParseString *relation_name)
      : ParseStatement(line_number, column_number),
        relation_name_(relation_name) {
  }

  /**
   * @brief Destructor.
   */
  ~ParseStatementDropTable() override {
  }

  StatementType getStatementType() const override {
    return kDropTable;
  }

  std::string getName() const override { return "DropTableStatement"; }

  /**
   * @brief Get the name of the relation to drop.
   *
   * @return The name of the relation to drop.
   **/
  const ParseString* relation_name() const {
    return relation_name_.get();
  }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    inline_field_names->push_back("relation_name");
    inline_field_values->push_back(relation_name_->value());
  }

 private:
  std::unique_ptr<ParseString> relation_name_;

  DISALLOW_COPY_AND_ASSIGN(ParseStatementDropTable);
};

/**
 * @brief The parsed representation of a SELECT statement.
 **/
class ParseStatementSelect : public ParseStatement {
 public:
  /**
   * @brief Constructor.
   * @note Takes ownership of all pointers.
   *
   * @param line_number Line number of the first token of this node in the SQL statement.
   * @param column_number Column number of the first token of this node in the SQL statement.
   * @param select_query The top-level SELECT query.
   * @param with_clause The WITH clause of common table query expressions.
   * @param priority_clause The PRIORITY clause of this query. If not valid or
   *        not present, this is NULL.
   **/
  ParseStatementSelect(const int line_number,
                       const int column_number,
                       ParseSelect *select_query,
                       PtrVector<ParseSubqueryTableReference> *with_clause,
                       ParsePriority *priority_clause)
      : ParseStatement(line_number, column_number),
        select_query_(select_query),
        with_clause_(with_clause),
        priority_clause_(priority_clause) {
  }

  /**
   * @brief Destructor.
   */
  ~ParseStatementSelect() override {
  }

  StatementType getStatementType() const override {
    return kSelect;
  }

  std::string getName() const override { return "SelectStatement"; }

  /**
   * @return Gets the top-level SELECT query.
   */
  const ParseSelect* select_query() const {
    return select_query_.get();
  }

  /**
   * @brief Gets the WITH table queries.
   *
   * @return The parsed WITH table list.
   */
  const PtrVector<ParseSubqueryTableReference>* with_clause() const {
    return with_clause_.get();
  }

  const std::uint64_t getPriority() const override {
    if (priority_clause_ != nullptr) {
      DCHECK(priority_clause_->priority_expression() != nullptr);
      return priority_clause_->priority_expression()->long_value();
    }
    return 1;
  }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    non_container_child_field_names->push_back("select_query");
    non_container_child_fields->push_back(select_query_.get());

    if (with_clause_ != nullptr && !with_clause_->empty()) {
      container_child_field_names->push_back("with_clause");
      container_child_fields->emplace_back();
      for (const ParseSubqueryTableReference &common_subquery : *with_clause_) {
        container_child_fields->back().push_back(&common_subquery);
      }
    }

    if (priority_clause_ != nullptr) {
      non_container_child_field_names->push_back("priority");
      non_container_child_fields->push_back(priority_clause_.get());
    }
  }

 private:
  std::unique_ptr<ParseSelect> select_query_;
  std::unique_ptr<PtrVector<ParseSubqueryTableReference>> with_clause_;
  std::unique_ptr<ParsePriority> priority_clause_;

  DISALLOW_COPY_AND_ASSIGN(ParseStatementSelect);
};

/**
 * @brief The parsed representation of an INSERT statement.
 *
 * This is an abstract class where each of its subclass represents a concrete
 * type of insert operation.
 **/
class ParseStatementInsert : public ParseStatement {
 public:
  enum class InsertType {
    kTuple = 0,
    kSelection
  };

  /**
   * @brief Constructor.
   *
   * @param line_number Line number of the first token of this node in the SQL statement.
   * @param column_number Column number of the first token of this node in the SQL statement.
   * @param relation_name The name of the relation to insert into.
   **/
  ParseStatementInsert(const int line_number,
                       const int column_number,
                       const ParseString *relation_name)
      : ParseStatement(line_number, column_number),
        relation_name_(relation_name) {
  }

  /**
   * @brief Get the insert type of this insert statement.
   *
   * @return The insert type of this insert statement.
   */
  virtual InsertType getInsertType() const = 0;

  std::string getName() const override { return "InsertStatement"; }

  StatementType getStatementType() const override {
    return kInsert;
  }

  /**
   * @brief Get the name of the relation to insert into.
   *
   * @return The name of the relation to insert into.
   **/
  const ParseString* relation_name() const {
    return relation_name_.get();
  }

 private:
  std::unique_ptr<const ParseString> relation_name_;

  DISALLOW_COPY_AND_ASSIGN(ParseStatementInsert);
};


/**
 * @brief The parsed representation of an INSERT ... VALUES ... statement.
 **/
class ParseStatementInsertTuple : public ParseStatementInsert {
 public:
  /**
   * @brief Constructor.
   *
   * @param line_number Line number of the first token of this node in the SQL statement.
   * @param column_number Column number of the first token of this node in the SQL statement.
   * @param relation_name The name of the relation to insert into.
   * @param literal_values A list of literal values (in attribute-definition
   *        order) to insert into the specified relation as a new tuple.
   *        Becomes owned by this ParseStatementInsert.
   **/
  ParseStatementInsertTuple(const int line_number,
                            const int column_number,
                            const ParseString *relation_name,
                            PtrList<ParseScalarLiteral> *literal_values)
      : ParseStatementInsert(line_number, column_number, relation_name),
        literal_values_(literal_values) {
  }

  ~ParseStatementInsertTuple() override {
  }

  InsertType getInsertType() const override {
    return InsertType::kTuple;
  }

  /**
   * @brief Get the parsed literal attribute values to insert.
   *
   * @return The list of literal values to insert.
   **/
  const PtrList<ParseScalarLiteral>& getLiteralValues() const {
    return *literal_values_;
  }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    inline_field_names->push_back("relation_name");
    inline_field_values->push_back(relation_name()->value());

    container_child_field_names->push_back("tuple");
    container_child_fields->emplace_back();
    for (const ParseScalarLiteral& literal_value : *literal_values_) {
      container_child_fields->back().push_back(&literal_value);
    }
  }

 private:
  std::unique_ptr<PtrList<ParseScalarLiteral> > literal_values_;

  DISALLOW_COPY_AND_ASSIGN(ParseStatementInsertTuple);
};

/**
 * @brief The parsed representation of an INSERT ... SELECT ... statement.
 **/
class ParseStatementInsertSelection : public ParseStatementInsert {
 public:
  /**
   * @brief Constructor.
   *
   * @param line_number Line number of the first token of this node in the SQL statement.
   * @param column_number Column number of the first token of this node in the SQL statement.
   * @param relation_name The name of the relation to insert into.
   * @param select_query The SELECT query for generating insertion tuples.
   * @param with_clause The WITH clause of common table query expressions.
   **/
  ParseStatementInsertSelection(const int line_number,
                                const int column_number,
                                const ParseString *relation_name,
                                ParseSelect *select_query,
                                PtrVector<ParseSubqueryTableReference> *with_clause)
      : ParseStatementInsert(line_number, column_number, relation_name),
        select_query_(select_query),
        with_clause_(with_clause) {
  }

  ~ParseStatementInsertSelection() override {
  }

  InsertType getInsertType() const override {
    return InsertType::kSelection;
  }

  /**
   * @return Gets the SELECT query.
   */
  const ParseSelect* select_query() const {
    return select_query_.get();
  }

  /**
   * @brief Gets the WITH table queries.
   *
   * @return The parsed WITH table list.
   */
  const PtrVector<ParseSubqueryTableReference>* with_clause() const {
    return with_clause_.get();
  }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    inline_field_names->push_back("relation_name");
    inline_field_values->push_back(relation_name()->value());

    non_container_child_field_names->push_back("select_query");
    non_container_child_fields->push_back(select_query_.get());

    if (with_clause_ != nullptr && !with_clause_->empty()) {
      container_child_field_names->push_back("with_clause");
      container_child_fields->emplace_back();
      for (const ParseSubqueryTableReference &common_subquery : *with_clause_) {
        container_child_fields->back().push_back(&common_subquery);
      }
    }
  }

 private:
  std::unique_ptr<ParseSelect> select_query_;
  std::unique_ptr<PtrVector<ParseSubqueryTableReference>> with_clause_;

  DISALLOW_COPY_AND_ASSIGN(ParseStatementInsertSelection);
};

/**
 * @brief Optional parameters for a COPY FROM statement.
 **/
struct ParseCopyFromParams : public ParseTreeNode {
  /**
   * @brief Constructor, sets default values.
   **/
  ParseCopyFromParams(const int line_number, const int column_number)
      : ParseTreeNode(line_number, column_number),
        escape_strings(true) {
  }

  std::string getName() const override { return "CopyFromParams"; }

  /**
   * @brief Sets the column delimiter.
   *
   * @param delimiter_in The column delimiter string.
   */
  void set_delimiter(ParseString* delimiter_in) {
    delimiter.reset(delimiter_in);
  }

  /**
   * @brief The string which terminates individual attribute values in the
   *        input file. Can be NULL.
   **/
  std::unique_ptr<ParseString> delimiter;

  /**
   * @brief If true, replace C-style escape sequences in strings from the input
   *        text file.
   **/
  bool escape_strings;

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    if (delimiter != nullptr) {
      inline_field_names->push_back("delimiter");
      inline_field_values->push_back(delimiter->value());
    }

    inline_field_names->push_back("escape_string");
    inline_field_values->push_back(escape_strings ? "true" : "false");
  }
};

/**
 * @brief The parsed representation of a COPY FROM statement.
 **/
class ParseStatementCopyFrom : public ParseStatement {
 public:
  /**
   * @brief Constructor.
   *
   * @param line_number Line number of the first token of this node in the SQL statement.
   * @param column_number Column number of the first token of this node in the SQL statement.
   * @param relation_name The name of the relation to insert into.
   * @param source_filename The name of the text file to bulk insert from.
   * @param params The optional parameters of the COPY FROM statement (should
   *        be supplied with defaults if not otherwise set).
   **/
  ParseStatementCopyFrom(const int line_number,
                         const int column_number,
                         ParseString *relation_name,
                         ParseString *source_filename,
                         ParseCopyFromParams *params)
      : ParseStatement(line_number, column_number),
        relation_name_(relation_name),
        source_filename_(source_filename),
        params_(params) {
  }

  /**
   * @brief Destructor.
   */
  ~ParseStatementCopyFrom() override {
  }

  StatementType getStatementType() const override {
    return kCopyFrom;
  }

  std::string getName() const override { return "CopyFromStatement"; }

  /**
   * @brief Get the name of the relation to insert into.
   *
   * @return The name of the relation to insert into.
   **/
  const ParseString* relation_name() const {
    return relation_name_.get();
  }

  /**
   * @brief Get the name of the text file to copy from.
   *
   * @return The name of the text file to copy from.
   **/
  const ParseString* source_filename() const {
    return source_filename_.get();
  }

  /**
   * @brief Get the additional COPY FROM parameters.
   *
   * @return The string which terminates individual attribute values in the
   *         input file.
   **/
  const ParseCopyFromParams* params() const {
    return params_.get();
  }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    inline_field_names->push_back("relation_name");
    inline_field_values->push_back(relation_name_->value());

    inline_field_names->push_back("source_file");
    inline_field_values->push_back(source_filename_->value());

    if (params_ != nullptr) {
      non_container_child_field_names->push_back("params");
      non_container_child_fields->push_back(params_.get());
    }
  }

 private:
  std::unique_ptr<ParseString> relation_name_;
  std::unique_ptr<ParseString> source_filename_;
  std::unique_ptr<ParseCopyFromParams> params_;

  DISALLOW_COPY_AND_ASSIGN(ParseStatementCopyFrom);
};


/**
 * @brief The parsed representation of an UPDATE statement.
 **/
class ParseStatementUpdate : public ParseStatement {
 public:
  /**
   * @brief Constructor.
   *
   * @param line_number Line number of the first token of this node in the SQL statement.
   * @param column_number Column number of the first token of this node in the SQL statement.
   * @param relation_name The name of the relation to update.
   * @param assignments A list of assignment for the attributes in the
   *        relation, which becomes owned by this ParseStatementUpdate.
   * @param where_predicate An optional predicate from a WHERE clause in the
   *        UPDATE statement (may be NULL if no predicate). Becomes owned by
   *        this ParseStatementUpdate if non-NULL.
   **/
  ParseStatementUpdate(const int line_number,
                       const int column_number,
                       ParseString *relation_name,
                       PtrList<ParseAssignment> *assignments,
                       ParsePredicate *where_predicate)
      : ParseStatement(line_number, column_number),
        relation_name_(relation_name),
        assignments_(assignments),
        where_predicate_(where_predicate) {
  }

  /**
   * @brief Destructor.
   */
  ~ParseStatementUpdate() override {
  }

  StatementType getStatementType() const override {
    return kUpdate;
  }

  std::string getName() const override { return "UpdateStatement"; }

  /**
   * @brief Get the name of the relation to update.
   *
   * @return The name of the relation to update.
   **/
  const ParseString* relation_name() const {
    return relation_name_.get();
  }

  /**
   * @brief Get the assignments to perform in the update.
   *
   * @return A list of assignments to perform in the update.
   **/
  const PtrList<ParseAssignment>& assignments() const {
    return *assignments_;
  }

  /**
   * @brief Determine whether this update statement has a WHERE predicate.
   *
   * @return Whether there is a WHERE predicate in this statement.
   **/
  bool hasWherePredicate() const {
    return where_predicate_.get() != nullptr;
  }

  /**
   * @brief Get the where predicate.
   * @warning Always call hasWherePredicate() first.
   *
   * @return The where predicate for this update.
   **/
  const ParsePredicate& where_predicate() const {
    DCHECK(hasWherePredicate());
    return *where_predicate_;
  }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    inline_field_names->push_back("relation_name");
    inline_field_values->push_back(relation_name_->value());

    container_child_field_names->push_back("assignment");
    container_child_fields->emplace_back();
    for (const ParseAssignment& assignment_item : *assignments_) {
      container_child_fields->back().push_back(&assignment_item);
    }

    if (where_predicate_ != nullptr) {
      non_container_child_field_names->push_back("where_predicate");
      non_container_child_fields->push_back(where_predicate_.get());
    }
  }

 private:
  std::unique_ptr<ParseString> relation_name_;
  std::unique_ptr<PtrList<ParseAssignment> > assignments_;
  std::unique_ptr<ParsePredicate> where_predicate_;

  DISALLOW_COPY_AND_ASSIGN(ParseStatementUpdate);
};

/**
 * @brief The parsed representation of a DELETE statement.
 **/
class ParseStatementDelete : public ParseStatement {
 public:
  /**
   * @brief Constructor
   *
   * @param line_number Line number of the first token of this node in the SQL statement.
   * @param column_number Column number of the first token of this node in the SQL statement.
   * @param relation_name The name of the relation to delete from.
   * @param where_predicate An optional predicate from a WHERE clause in the
   *        DELETE statement (may be NULL if no predicate). Becomes owned by
   *        this ParseStatementDelete if non-NULL.
   **/
  ParseStatementDelete(const int line_number,
                       const int column_number,
                       ParseString *relation_name,
                       ParsePredicate *where_predicate)
      : ParseStatement(line_number, column_number), relation_name_(relation_name), where_predicate_(where_predicate) {
  }

  /**
   * @brief Destructor.
   */
  ~ParseStatementDelete() override {
  }

  StatementType getStatementType() const override {
    return kDelete;
  }

  std::string getName() const override { return "DeleteStatement"; }

  /**
   * @brief Get the name of the relation to delete from.
   *
   * @return The name of the relation to delete from.
   **/
  const ParseString* relation_name() const {
    return relation_name_.get();
  }

  /**
   * @brief Get the where predicate.
   *
   * @return The where predicate for this delete statement.
   **/
  const ParsePredicate* where_predicate() const {
    return where_predicate_.get();
  }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    inline_field_names->push_back("relation_name");
    inline_field_values->push_back(relation_name_->value());

    if (where_predicate_ != nullptr) {
      non_container_child_field_names->push_back("where_predicate");
      non_container_child_fields->push_back(where_predicate_.get());
    }
  }

 private:
  std::unique_ptr<ParseString> relation_name_;
  std::unique_ptr<ParsePredicate> where_predicate_;

  DISALLOW_COPY_AND_ASSIGN(ParseStatementDelete);
};

/**
 * @brief The parsed representation of a QUIT statement, which terminates a
 *        quickstep session.
 **/
class ParseStatementQuit : public ParseStatement {
 public:
  /**
   * @brief Constructor.
   *
   * @param line_number Line number of the first token of this node in the SQL statement.
   * @param column_number Column number of the first token of this node in the SQL statement.
   */
  ParseStatementQuit(const int line_number, const int column_number)
      : ParseStatement(line_number, column_number) {
  }

  StatementType getStatementType() const override {
    return kQuit;
  }

  std::string getName() const override { return "QuitStatement"; }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ParseStatementQuit);
};

/**
 * @brief Class to hold the parsed command name and an optional argument string.
 * @details Commands are non-sql statements which can be issued to quickstep.
 *          They are entered into the CLI as '.command-name command-string\n'.
 *          The command string is split up into words using whitespace as
 *          a delimiter.
 */
class ParseCommand : public ParseStatement {
 public:
  ParseCommand(const int line_number,
               const int column_number,
               ParseString *command,
               PtrVector<ParseString> *arguments)
      : ParseStatement(line_number, column_number),
        command_(command),
        arguments_(arguments) {  }

  /**
   * @return The name of this class.
   */
  std::string getName() const override {
    return "ParseCommand";
  }

  /**
   * @brief All ParseCommands are ParseStatements of the type command.
   */
  StatementType getStatementType() const override {
    return kCommand;
  }

  /**
   * @return The name of the command.
   */
  const ParseString* command() const {
    return command_.get();
  }

  /**
   * @return The optional argument strings to the command. Possibly empty.
   */
  const PtrVector<ParseString>* arguments() const {
    return arguments_.get();
  }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    inline_field_names->push_back("command");
    inline_field_values->push_back(command_->value());

    for (const ParseString &argument : *arguments_) {
      non_container_child_field_names->push_back("argument");
      non_container_child_fields->push_back(&argument);
    }
  }

 private:
  std::unique_ptr<ParseString> command_;
  std::unique_ptr<PtrVector<ParseString>> arguments_;

  DISALLOW_COPY_AND_ASSIGN(ParseCommand);
};

/** @} */

}  // namespace quickstep

#endif  // QUICKSTEP_PARSER_PARSE_STATEMENT_HPP_
