| /** |
| * Copyright 2011-2015 Quickstep Technologies LLC. |
| * Copyright 2015 Pivotal Software, Inc. |
| * Copyright 2016, Quickstep Research Group, Computer Sciences Department, |
| * University of Wisconsin—Madison. |
| * |
| * Licensed 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/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; |
| |
| 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::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("unkown"); |
| } |
| |
| 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::kBloomFilter: |
| index_properties_.reset(new BloomFilterIndexProperties()); |
| break; |
| case IndexSubBlockType::kCSBTree: |
| index_properties_.reset(new CSBTreeIndexProperties()); |
| break; |
| case IndexSubBlockType::kSMA: |
| LOG(FATAL) << "Currently cannot create this index subblock type using CREATE INDEX."; |
| 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. |
| **/ |
| ParseStatementSelect(const int line_number, |
| const int column_number, |
| ParseSelect *select_query, |
| PtrVector<ParseSubqueryTableReference> *with_clause) |
| : ParseStatement(line_number, column_number), |
| select_query_(select_query), |
| with_clause_(with_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(); |
| } |
| |
| 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); |
| } |
| } |
| } |
| |
| private: |
| std::unique_ptr<ParseSelect> select_query_; |
| std::unique_ptr<PtrVector<ParseSubqueryTableReference>> with_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_ |