From f5c9637a8243e75be206e19c5a30dc681177a5bc Mon Sep 17 00:00:00 2001 From: Suguru ARAKAWA Date: Fri, 16 Aug 2024 15:58:16 +0900 Subject: [PATCH] feat: support `COALESCE`. --- .../details/analyze_scalar_expression.cpp | 29 +++++++++- .../analyze_scalar_expression_case_test.cpp | 54 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/mizugaki/analyzer/details/analyze_scalar_expression.cpp b/src/mizugaki/analyzer/details/analyze_scalar_expression.cpp index de44c50..e11ab21 100644 --- a/src/mizugaki/analyzer/details/analyze_scalar_expression.cpp +++ b/src/mizugaki/analyzer/details/analyze_scalar_expression.cpp @@ -678,7 +678,7 @@ class engine { case kind::nullif: return process_nullif(expr, context); case kind::coalesce: - // FIXME: impl coalesce (built-in function) + return process_coalesce(expr, context); case kind::next_value_for: // FIXME: impl next_value_for (built-in function) @@ -812,6 +812,33 @@ class engine { return result; } + [[nodiscard]] std::unique_ptr process_coalesce( + ast::scalar::builtin_function_invocation const& expr, + value_context const&) { + if (expr.arguments().empty()) { + context_.report( + sql_analyzer_code::malformed_syntax, + "COALESCE must have one or more operands", + expr.region()); + return {}; + } + + ::takatori::util::reference_vector operands {}; + operands.reserve(expr.arguments().size()); + for (auto&& argument : expr.arguments()) { + auto r = process(*argument, {}); + if (!r) { + return {}; + } + operands.push_back(r.release()); + } + auto result = context_.create( + expr.region(), + std::move(operands)); + + return result; + } + [[nodiscard]] std::unique_ptr operator()( ast::scalar::builtin_set_function_invocation const& expr, value_context const&) { diff --git a/test/mizugaki/analyzer/details/analyze_scalar_expression_case_test.cpp b/test/mizugaki/analyzer/details/analyze_scalar_expression_case_test.cpp index 7f1a287..cd3af77 100644 --- a/test/mizugaki/analyzer/details/analyze_scalar_expression_case_test.cpp +++ b/test/mizugaki/analyzer/details/analyze_scalar_expression_case_test.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -392,4 +393,57 @@ TEST_F(analyze_scalar_expression_case_test, nullif_invalid) { }); } +TEST_F(analyze_scalar_expression_case_test, coalesce) { + auto r = analyze_scalar_expression( + context(), + ast::scalar::builtin_function_invocation { + ast::scalar::builtin_function_kind::coalesce, + { + literal(number("1")), + }, + }, + {}, + {}); + ASSERT_TRUE(r) << diagnostics(); + expect_no_error(); + + EXPECT_EQ(*r, (tscalar::coalesce { + { + immediate(1), + }, + })); +} + +TEST_F(analyze_scalar_expression_case_test, coalesce_multiple) { + auto r = analyze_scalar_expression( + context(), + ast::scalar::builtin_function_invocation { + ast::scalar::builtin_function_kind::coalesce, + { + literal(number("1")), + literal(number("2")), + literal(number("3")), + }, + }, + {}, + {}); + ASSERT_TRUE(r) << diagnostics(); + expect_no_error(); + + EXPECT_EQ(*r, (tscalar::coalesce { + { + immediate(1), + immediate(2), + immediate(3), + }, + })); +} + +TEST_F(analyze_scalar_expression_case_test, coalesce_invalid) { + invalid(sql_analyzer_code::malformed_syntax, ast::scalar::builtin_function_invocation { + ast::scalar::builtin_function_kind::coalesce, + {}, + }); +} + } // namespace mizugaki::analyzer::details