From 8e03bca57798a971c7b407600200497a9913cc84 Mon Sep 17 00:00:00 2001 From: Suguru ARAKAWA Date: Wed, 21 Aug 2024 23:26:22 +0900 Subject: [PATCH] feat: support `INSERT INTO ~ DEFAULT VALUES`. --- .../analyzer/details/analyze_statement.cpp | 49 ++++++++++--- .../details/analyze_statement_insert_test.cpp | 69 ++++++++++++++++--- 2 files changed, 100 insertions(+), 18 deletions(-) diff --git a/src/mizugaki/analyzer/details/analyze_statement.cpp b/src/mizugaki/analyzer/details/analyze_statement.cpp index 77e1696..3a64eb2 100644 --- a/src/mizugaki/analyzer/details/analyze_statement.cpp +++ b/src/mizugaki/analyzer/details/analyze_statement.cpp @@ -145,8 +145,6 @@ class engine { auto info = std::move(*info_opt); auto index = info.primary_index(); - auto graph = std::make_unique<::takatori::relation::graph_type>(); - auto destination_columns = create_vector<::yugawara::storage::column const*>(); auto columns_context = create_vector(); @@ -201,14 +199,12 @@ class engine { } } + // empty source means "INSERT INTO ~ DEFAULT VALUES" if (!stmt.expression()) { - // FIXME: impl treat "DEFAULT VALUES" clause - context_.report( - sql_analyzer_code::unsupported_feature, - "DEFAULT VALUES clause is yet not supported", - stmt.region()); - return {}; + return process_insert_default_values(stmt, info); } + + auto graph = std::make_unique<::takatori::relation::graph_type>(); auto source = analyze_query_expression( context_, *graph, @@ -305,6 +301,43 @@ class engine { return graph; } + [[nodiscard]] result_type process_insert_default_values( + ast::statement::insert_statement const& stmt, + relation_info const& relation) { + auto index = relation.primary_index(); + auto write_operator = compute_write_type(stmt); + if (!write_operator) { + return {}; + } + + if (context_.options()->prefer_write_statement()) { + auto write_tuples = create_vector(1); + write_tuples.emplace_back(::takatori::util::reference_vector {}); + return context_.create( + stmt.region(), + *write_operator, + factory_(index), + std::vector {}, + std::move(write_tuples)); + } + + auto graph = std::make_unique<::takatori::relation::graph_type>(); + auto rows = create_vector(1); + rows.emplace_back(::takatori::util::reference_vector {}); + auto&& op_values = graph->insert(context_.create( + stmt.table_name()->region(), + std::vector {}, + std::move(rows))); + auto&& op_write = graph->insert(context_.create( + stmt.table_name()->region(), + *write_operator, + factory_(index), + std::vector {}, + std::vector {})); + op_write.input().connect_to(op_values.output()); + return graph; + } + [[nodiscard]] std::optional compute_write_type( ast::statement::insert_statement const& stmt) { using from = ast::statement::insert_statement_option; diff --git a/test/mizugaki/analyzer/details/analyze_statement_insert_test.cpp b/test/mizugaki/analyzer/details/analyze_statement_insert_test.cpp index 6515de6..4976019 100644 --- a/test/mizugaki/analyzer/details/analyze_statement_insert_test.cpp +++ b/test/mizugaki/analyzer/details/analyze_statement_insert_test.cpp @@ -220,6 +220,65 @@ TEST_F(analyze_statement_insert_test, as_write_statement) { } } +TEST_F(analyze_statement_insert_test, default_values) { + options_.prefer_write_statement() = false; + auto table = install_table("testing"); + + auto r = analyze_statement(context(), ast::statement::insert_statement { + id("testing"), + {}, + {}, + }); + auto alternative = std::get_if(&r); + ASSERT_TRUE(alternative) << diagnostics(); + expect_no_error(); + + auto&& graph = **alternative; + ASSERT_EQ(graph.size(), 2); + + auto first = find_first(graph); + ASSERT_TRUE(first); + ASSERT_EQ(first->columns().size(), 0); + ASSERT_EQ(first->rows().size(), 1); + ASSERT_EQ(first->rows()[0].elements().size(), 0); + + auto last = find_last(graph); + ASSERT_TRUE(last); + EXPECT_EQ(find_next(*first).get(), last.get()); + + EXPECT_EQ(last->operator_kind(), tstatement::write_kind::insert); + EXPECT_EQ(&extract<::yugawara::storage::index>(last->destination()).table(), table.get()); + + ASSERT_EQ(last->keys().size(), 0); + ASSERT_EQ(last->columns().size(), 0); +} + +TEST_F(analyze_statement_insert_test, default_values_as_write_statement) { + options_.prefer_write_statement() = true; + auto table = install_table("testing"); + + auto r = analyze_statement(context(), ast::statement::insert_statement { + id("testing"), + {}, + {}, + }); + auto alternative = std::get_if(&r); + ASSERT_TRUE(alternative) << diagnostics(); + expect_no_error(); + + ASSERT_EQ((*alternative)->kind(), tstatement::statement_kind::write); + auto&& stmt = downcast(**alternative); + + EXPECT_EQ(stmt.operator_kind(), tstatement::write_kind::insert); + EXPECT_EQ(&extract<::yugawara::storage::index>(stmt.destination()).table(), table.get()); + + auto&& columns = stmt.columns(); + ASSERT_EQ(columns.size(), 0); + auto&& tuples = stmt.tuples(); + ASSERT_EQ(tuples.size(), 1); + ASSERT_EQ(tuples[0].elements().size(), 0); +} + TEST_F(analyze_statement_insert_test, values_null) { options_.prefer_write_statement() = false; auto table = install_table("testing"); @@ -422,14 +481,4 @@ TEST_F(analyze_statement_insert_test, inconsistent_query) { }); } -TEST_F(analyze_statement_insert_test, default_values) { - options_.prefer_write_statement() = false; - auto table = install_table("testing"); - invalid(sql_analyzer_code::unsupported_feature, ast::statement::insert_statement { - id("testing"), - {}, - {}, // default values - }); -} - } // namespace mizugaki::analyzer::details