http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fe838df/parser/preprocessed/SqlParser_gen.hpp ---------------------------------------------------------------------- diff --git a/parser/preprocessed/SqlParser_gen.hpp b/parser/preprocessed/SqlParser_gen.hpp index f6b5247..142059d 100644 --- a/parser/preprocessed/SqlParser_gen.hpp +++ b/parser/preprocessed/SqlParser_gen.hpp @@ -198,6 +198,7 @@ union YYSTYPE quickstep::NumericParseLiteralValue *numeric_literal_value_; quickstep::ParseLiteralValue *literal_value_; quickstep::PtrList<quickstep::ParseScalarLiteral> *literal_value_list_; + quickstep::PtrList<quickstep::PtrList<quickstep::ParseScalarLiteral>> *literal_value_list_multiple_; quickstep::ParseExpression *expression_; @@ -288,7 +289,7 @@ union YYSTYPE quickstep::ParsePriority *opt_priority_clause_; -#line 292 "SqlParser_gen.hpp" /* yacc.c:1915 */ +#line 293 "SqlParser_gen.hpp" /* yacc.c:1915 */ }; typedef union YYSTYPE YYSTYPE;
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fe838df/query_optimizer/ExecutionGenerator.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/ExecutionGenerator.cpp b/query_optimizer/ExecutionGenerator.cpp index 372d576..14d8949 100644 --- a/query_optimizer/ExecutionGenerator.cpp +++ b/query_optimizer/ExecutionGenerator.cpp @@ -1461,70 +1461,72 @@ void ExecutionGenerator::convertInsertTuple( *catalog_database_->getRelationById( input_relation_info->relation->getID()); - // Construct the tuple proto to be inserted. - const QueryContext::tuple_id tuple_index = query_context_proto_->tuples_size(); + for (const std::vector<expressions::ScalarLiteralPtr> &tuple : physical_plan->column_values()) { + // Construct the tuple proto to be inserted. + const QueryContext::tuple_id tuple_index = query_context_proto_->tuples_size(); - S::Tuple *tuple_proto = query_context_proto_->add_tuples(); - for (const E::ScalarLiteralPtr &literal : physical_plan->column_values()) { - tuple_proto->add_attribute_values()->CopyFrom(literal->value().getProto()); - } + S::Tuple *tuple_proto = query_context_proto_->add_tuples(); + for (const E::ScalarLiteralPtr &literal : tuple) { + tuple_proto->add_attribute_values()->CopyFrom(literal->value().getProto()); + } - // FIXME(qzeng): A better way is using a traits struct to look up whether a storage - // block supports ad-hoc insertion instead of hard-coding the block types. - const StorageBlockLayout &storage_block_layout = - input_relation.getDefaultStorageBlockLayout(); - if (storage_block_layout.getDescription().tuple_store_description().sub_block_type() == - TupleStorageSubBlockDescription::COMPRESSED_COLUMN_STORE || - storage_block_layout.getDescription().tuple_store_description().sub_block_type() == - TupleStorageSubBlockDescription::COMPRESSED_PACKED_ROW_STORE) { - THROW_SQL_ERROR() << "INSERT statement is not supported for the relation " - << input_relation.getName() - << ", because its storage blocks do not support ad-hoc insertion"; - } + // FIXME(qzeng): A better way is using a traits struct to look up whether a storage + // block supports ad-hoc insertion instead of hard-coding the block types. + const StorageBlockLayout &storage_block_layout = + input_relation.getDefaultStorageBlockLayout(); + if (storage_block_layout.getDescription().tuple_store_description().sub_block_type() == + TupleStorageSubBlockDescription::COMPRESSED_COLUMN_STORE || + storage_block_layout.getDescription().tuple_store_description().sub_block_type() == + TupleStorageSubBlockDescription::COMPRESSED_PACKED_ROW_STORE) { + THROW_SQL_ERROR() << "INSERT statement is not supported for the relation " + << input_relation.getName() + << ", because its storage blocks do not support ad-hoc insertion"; + } - // Create InsertDestination proto. - const QueryContext::insert_destination_id insert_destination_index = - query_context_proto_->insert_destinations_size(); - S::InsertDestination *insert_destination_proto = query_context_proto_->add_insert_destinations(); + // Create InsertDestination proto. + const QueryContext::insert_destination_id insert_destination_index = + query_context_proto_->insert_destinations_size(); + S::InsertDestination *insert_destination_proto = query_context_proto_->add_insert_destinations(); - insert_destination_proto->set_relation_id(input_relation.getID()); - insert_destination_proto->mutable_layout()->MergeFrom( - input_relation.getDefaultStorageBlockLayout().getDescription()); + insert_destination_proto->set_relation_id(input_relation.getID()); + insert_destination_proto->mutable_layout()->MergeFrom( + input_relation.getDefaultStorageBlockLayout().getDescription()); - if (input_relation.hasPartitionScheme()) { - insert_destination_proto->set_insert_destination_type(S::InsertDestinationType::PARTITION_AWARE); - insert_destination_proto->MutableExtension(S::PartitionAwareInsertDestination::partition_scheme) - ->MergeFrom(input_relation.getPartitionScheme()->getProto()); - } else { - insert_destination_proto->set_insert_destination_type(S::InsertDestinationType::BLOCK_POOL); + if (input_relation.hasPartitionScheme()) { + insert_destination_proto->set_insert_destination_type(S::InsertDestinationType::PARTITION_AWARE); + insert_destination_proto->MutableExtension(S::PartitionAwareInsertDestination::partition_scheme) + ->MergeFrom(input_relation.getPartitionScheme()->getProto()); + } else { + insert_destination_proto->set_insert_destination_type(S::InsertDestinationType::BLOCK_POOL); - const vector<block_id> blocks(input_relation.getBlocksSnapshot()); - for (const block_id block : blocks) { - insert_destination_proto->AddExtension(S::BlockPoolInsertDestination::blocks, block); + const vector<block_id> blocks(input_relation.getBlocksSnapshot()); + for (const block_id block : blocks) { + insert_destination_proto->AddExtension(S::BlockPoolInsertDestination::blocks, block); + } } - } - const QueryPlan::DAGNodeIndex insert_operator_index = - execution_plan_->addRelationalOperator( - new InsertOperator(query_handle_->query_id(), - input_relation, - insert_destination_index, - tuple_index)); - insert_destination_proto->set_relational_op_index(insert_operator_index); + const QueryPlan::DAGNodeIndex insert_operator_index = + execution_plan_->addRelationalOperator( + new InsertOperator(query_handle_->query_id(), + input_relation, + insert_destination_index, + tuple_index)); + insert_destination_proto->set_relational_op_index(insert_operator_index); - CatalogRelation *mutable_relation = - catalog_database_->getRelationByIdMutable(input_relation.getID()); - const QueryPlan::DAGNodeIndex save_blocks_index = - execution_plan_->addRelationalOperator( - new SaveBlocksOperator(query_handle_->query_id(), mutable_relation)); - if (!input_relation_info->isStoredRelation()) { - execution_plan_->addDirectDependency(insert_operator_index, - input_relation_info->producer_operator_index, - true /* is_pipeline_breaker */); + CatalogRelation *mutable_relation = + catalog_database_->getRelationByIdMutable(input_relation.getID()); + const QueryPlan::DAGNodeIndex save_blocks_index = + execution_plan_->addRelationalOperator( + new SaveBlocksOperator(query_handle_->query_id(), mutable_relation)); + if (!input_relation_info->isStoredRelation()) { + execution_plan_->addDirectDependency(insert_operator_index, + input_relation_info->producer_operator_index, + true /* is_pipeline_breaker */); + } + execution_plan_->addDirectDependency(save_blocks_index, + insert_operator_index, + false /* is_pipeline_breaker */); } - execution_plan_->addDirectDependency(save_blocks_index, - insert_operator_index, - false /* is_pipeline_breaker */); } void ExecutionGenerator::convertInsertSelection( http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fe838df/query_optimizer/logical/InsertTuple.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/logical/InsertTuple.cpp b/query_optimizer/logical/InsertTuple.cpp index e5ffa35..e2ce196 100644 --- a/query_optimizer/logical/InsertTuple.cpp +++ b/query_optimizer/logical/InsertTuple.cpp @@ -41,8 +41,10 @@ void InsertTuple::getFieldStringItems( non_container_child_field_names->push_back("input"); non_container_child_fields->push_back(input_); - container_child_field_names->push_back("column_values"); - container_child_fields->push_back(CastSharedPtrVector<OptimizerTreeBase>(column_values_)); + for (const auto &column_values : column_values_) { + container_child_field_names->push_back("column_values"); + container_child_fields->push_back(CastSharedPtrVector<OptimizerTreeBase>(column_values)); + } } } // namespace logical http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fe838df/query_optimizer/logical/InsertTuple.hpp ---------------------------------------------------------------------- diff --git a/query_optimizer/logical/InsertTuple.hpp b/query_optimizer/logical/InsertTuple.hpp index fd0301e..dd35510 100644 --- a/query_optimizer/logical/InsertTuple.hpp +++ b/query_optimizer/logical/InsertTuple.hpp @@ -61,7 +61,7 @@ class InsertTuple : public Logical { /** * @return Column values to be used to compose a new tuple. */ - const std::vector<expressions::ScalarLiteralPtr>& column_values() const { + const std::vector<std::vector<expressions::ScalarLiteralPtr>>& column_values() const { return column_values_; } @@ -83,12 +83,12 @@ class InsertTuple : public Logical { * @brief Creates an InsertTuple logical node. * * @param input The input produces the relation to insert the tuple to. - * @param column_values The column values of the tuple to be inserted. + * @param column_values The column values of the tuples to be inserted. * @return An immutable InsertTuple node. */ static InsertTuplePtr Create( const LogicalPtr &input, - const std::vector<expressions::ScalarLiteralPtr> &column_values) { + const std::vector<std::vector<expressions::ScalarLiteralPtr>> &column_values) { return InsertTuplePtr(new InsertTuple(input, column_values)); } @@ -103,13 +103,13 @@ class InsertTuple : public Logical { private: InsertTuple(const LogicalPtr &input, - const std::vector<expressions::ScalarLiteralPtr> &column_values) + const std::vector<std::vector<expressions::ScalarLiteralPtr>> &column_values) : input_(input), column_values_(column_values) { addChild(input_); } LogicalPtr input_; - std::vector<expressions::ScalarLiteralPtr> column_values_; + std::vector<std::vector<expressions::ScalarLiteralPtr>> column_values_; DISALLOW_COPY_AND_ASSIGN(InsertTuple); }; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fe838df/query_optimizer/physical/InsertTuple.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/physical/InsertTuple.cpp b/query_optimizer/physical/InsertTuple.cpp index 3085389..b209aa0 100644 --- a/query_optimizer/physical/InsertTuple.cpp +++ b/query_optimizer/physical/InsertTuple.cpp @@ -40,8 +40,10 @@ void InsertTuple::getFieldStringItems( non_container_child_field_names->push_back("input"); non_container_child_fields->push_back(input_); - container_child_field_names->push_back("column_values"); - container_child_fields->push_back(CastSharedPtrVector<OptimizerTreeBase>(column_values_)); + for (const auto &column_values : column_values_) { + container_child_field_names->push_back("column_values"); + container_child_fields->push_back(CastSharedPtrVector<OptimizerTreeBase>(column_values)); + } } } // namespace physical http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fe838df/query_optimizer/physical/InsertTuple.hpp ---------------------------------------------------------------------- diff --git a/query_optimizer/physical/InsertTuple.hpp b/query_optimizer/physical/InsertTuple.hpp index 40f2582..10c7c5b 100644 --- a/query_optimizer/physical/InsertTuple.hpp +++ b/query_optimizer/physical/InsertTuple.hpp @@ -69,7 +69,7 @@ class InsertTuple : public Physical { /** * @return Column values to be used to compose a new tuple. */ - const std::vector<expressions::ScalarLiteralPtr>& column_values() const { + const std::vector<std::vector<expressions::ScalarLiteralPtr>>& column_values() const { return column_values_; } @@ -103,7 +103,7 @@ class InsertTuple : public Physical { */ static InsertTuplePtr Create( const PhysicalPtr &input, - const std::vector<expressions::ScalarLiteralPtr> &column_values) { + const std::vector<std::vector<expressions::ScalarLiteralPtr>> &column_values) { return InsertTuplePtr(new InsertTuple(input, column_values)); } @@ -118,13 +118,13 @@ class InsertTuple : public Physical { private: InsertTuple(const PhysicalPtr &input, - const std::vector<expressions::ScalarLiteralPtr> &column_values) + const std::vector<std::vector<expressions::ScalarLiteralPtr>> &column_values) : input_(input), column_values_(column_values) { addChild(input_); } PhysicalPtr input_; - std::vector<expressions::ScalarLiteralPtr> column_values_; + std::vector<std::vector<expressions::ScalarLiteralPtr>> column_values_; DISALLOW_COPY_AND_ASSIGN(InsertTuple); }; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fe838df/query_optimizer/resolver/Resolver.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/resolver/Resolver.cpp b/query_optimizer/resolver/Resolver.cpp index 2991568..0b6dc22 100644 --- a/query_optimizer/resolver/Resolver.cpp +++ b/query_optimizer/resolver/Resolver.cpp @@ -1060,73 +1060,81 @@ L::LogicalPtr Resolver::resolveInsertTuple( // Resolve column values. const std::vector<E::AttributeReferencePtr> relation_attributes = input_logical->getOutputAttributes(); - const PtrList<ParseScalarLiteral> &parse_column_values = + const PtrList<PtrList<ParseScalarLiteral>> &parse_column_values_list = insert_statement.getLiteralValues(); - DCHECK_GT(parse_column_values.size(), 0u); - if (parse_column_values.size() > relation_attributes.size()) { - THROW_SQL_ERROR_AT(insert_statement.relation_name()) - << "The relation " << insert_statement.relation_name()->value() - << " has " << std::to_string(relation_attributes.size()) - << " columns, but " << std::to_string(parse_column_values.size()) - << " values are provided"; - } + std::vector<std::vector<E::ScalarLiteralPtr>> resolved_column_values_list; + DCHECK_GT(parse_column_values_list.size(), 0u); - std::vector<E::ScalarLiteralPtr> resolved_column_values; - std::vector<E::AttributeReferencePtr>::size_type aid = 0; - for (const ParseScalarLiteral &parse_literal_value : parse_column_values) { - E::ScalarLiteralPtr resolved_literal_value; - ExpressionResolutionInfo expr_resolution_info( - name_resolver, - "INSERT statement" /* clause_name */, - nullptr /* select_list_info */); - // When resolving the literal, use the attribute's Type as a hint. - CHECK(E::SomeScalarLiteral::MatchesWithConditionalCast( - resolveExpression(parse_literal_value, - &(relation_attributes[aid]->getValueType()), - &expr_resolution_info), - &resolved_literal_value)); - - // Check that the resolved Type is safely coercible to the attribute's - // Type. - if (!relation_attributes[aid]->getValueType().isSafelyCoercibleFrom( - resolved_literal_value->getValueType())) { - THROW_SQL_ERROR_AT(&parse_literal_value) - << "The assigned value for the column " - << relation_attributes[aid]->attribute_name() << " has the type " - << resolved_literal_value->getValueType().getName() - << ", which cannot be safely coerced to the column's type " - << relation_attributes[aid]->getValueType().getName(); - } + for (const PtrList<ParseScalarLiteral> &parse_column_values : parse_column_values_list) { + DCHECK_GT(parse_column_values.size(), 0u); - // If the Type is not exactly right (but is safely coercible), coerce it. - if (!resolved_literal_value->getValueType().equals( - relation_attributes[aid]->getValueType())) { - resolved_literal_value = E::ScalarLiteral::Create( - relation_attributes[aid]->getValueType().coerceValue( - resolved_literal_value->value(), - resolved_literal_value->getValueType()), - relation_attributes[aid]->getValueType()); + if (parse_column_values.size() > relation_attributes.size()) { + THROW_SQL_ERROR_AT(insert_statement.relation_name()) + << "The relation " << insert_statement.relation_name()->value() + << " has " << std::to_string(relation_attributes.size()) + << " columns, but " << std::to_string(parse_column_values.size()) + << " values are provided"; } - resolved_column_values.push_back(resolved_literal_value); - ++aid; - } + std::vector<E::ScalarLiteralPtr> resolved_column_values; + std::vector<E::AttributeReferencePtr>::size_type aid = 0; + for (const ParseScalarLiteral &parse_literal_value : parse_column_values) { + E::ScalarLiteralPtr resolved_literal_value; + ExpressionResolutionInfo expr_resolution_info( + name_resolver, + "INSERT statement" /* clause_name */, + nullptr /* select_list_info */); + // When resolving the literal, use the attribute's Type as a hint. + CHECK(E::SomeScalarLiteral::MatchesWithConditionalCast( + resolveExpression(parse_literal_value, + &(relation_attributes[aid]->getValueType()), + &expr_resolution_info), + &resolved_literal_value)); + + // Check that the resolved Type is safely coercible to the attribute's + // Type. + if (!relation_attributes[aid]->getValueType().isSafelyCoercibleFrom( + resolved_literal_value->getValueType())) { + THROW_SQL_ERROR_AT(&parse_literal_value) + << "The assigned value for the column " + << relation_attributes[aid]->attribute_name() << " has the type " + << resolved_literal_value->getValueType().getName() + << ", which cannot be safely coerced to the column's type " + << relation_attributes[aid]->getValueType().getName(); + } - while (aid < relation_attributes.size()) { - if (!relation_attributes[aid]->getValueType().isNullable()) { - THROW_SQL_ERROR_AT(insert_statement.relation_name()) - << "Must assign a non-NULL value to column " - << relation_attributes[aid]->attribute_name(); + // If the Type is not exactly right (but is safely coercible), coerce it. + if (!resolved_literal_value->getValueType().equals( + relation_attributes[aid]->getValueType())) { + resolved_literal_value = E::ScalarLiteral::Create( + relation_attributes[aid]->getValueType().coerceValue( + resolved_literal_value->value(), + resolved_literal_value->getValueType()), + relation_attributes[aid]->getValueType()); + } + + resolved_column_values.push_back(resolved_literal_value); + ++aid; + } + + while (aid < relation_attributes.size()) { + if (!relation_attributes[aid]->getValueType().isNullable()) { + THROW_SQL_ERROR_AT(insert_statement.relation_name()) + << "Must assign a non-NULL value to column " + << relation_attributes[aid]->attribute_name(); + } + // Create a NULL value. + resolved_column_values.push_back(E::ScalarLiteral::Create( + relation_attributes[aid]->getValueType().makeNullValue(), + relation_attributes[aid]->getValueType())); + ++aid; } - // Create a NULL value. - resolved_column_values.push_back(E::ScalarLiteral::Create( - relation_attributes[aid]->getValueType().makeNullValue(), - relation_attributes[aid]->getValueType())); - ++aid; + + resolved_column_values_list.push_back(std::move(resolved_column_values)); } - return L::InsertTuple::Create(input_logical, resolved_column_values); + return L::InsertTuple::Create(input_logical, resolved_column_values_list); } L::LogicalPtr Resolver::resolveUpdate(
