Skip to content

Commit 31e4a3f

Browse files
committed
feat: support exists predicate in analyzer.
1 parent bd5b67c commit 31e4a3f

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

src/mizugaki/analyzer/details/analyze_scalar_expression.cpp

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include <yugawara/extension/scalar/aggregate_function_call.h>
3333
#include <yugawara/extension/scalar/subquery.h>
34+
#include <yugawara/extension/scalar/exists.h>
3435

3536
#include <mizugaki/ast/scalar/dispatch.h>
3637
#include <mizugaki/ast/literal/boolean.h>
@@ -712,9 +713,6 @@ class engine {
712713
return result;
713714
}
714715

715-
// FIXME: impl pattern_match_predicate,
716-
// FIXME: impl table_predicate,
717-
718716
[[nodiscard]] std::unique_ptr<tscalar::expression> operator()(
719717
ast::scalar::pattern_match_predicate const& expr,
720718
value_context const& context) {
@@ -778,6 +776,43 @@ class engine {
778776
return {};
779777
}
780778

779+
[[nodiscard]] std::unique_ptr<tscalar::expression> operator()(
780+
ast::scalar::table_predicate const& expr,
781+
value_context const& context) {
782+
using kind = ast::scalar::table_operator;
783+
switch (*expr.operator_kind()) {
784+
case kind::exists:
785+
return process_exists(expr, context);
786+
case kind::unique:
787+
break;
788+
}
789+
context_.report(
790+
sql_analyzer_code::unsupported_feature,
791+
string_builder {}
792+
<< "unsupported table predicate: " << expr.operator_kind()
793+
<< string_builder::to_string,
794+
expr.operator_kind().region());
795+
return {};
796+
}
797+
798+
[[nodiscard]] std::unique_ptr<tscalar::expression> process_exists(
799+
ast::scalar::table_predicate const& expr,
800+
value_context const&) {
801+
::takatori::relation::graph_type subgraph {};
802+
auto query = analyze_query_expression(
803+
context_,
804+
subgraph,
805+
*expr.operand(),
806+
scope_,
807+
{}); // NOTE: don't propagate value context into subqueries
808+
if (!query) {
809+
return {};
810+
}
811+
auto result = context_.create<::yugawara::extension::scalar::exists>(
812+
expr.region(),
813+
std::move(subgraph));
814+
return result;
815+
}
781816

782817
// FIXME: impl <type predicate>
783818

test/mizugaki/analyzer/details/analyze_scalar_expression_subquery_test.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <takatori/relation/values.h>
1010

1111
#include <yugawara/extension/scalar/subquery.h>
12+
#include <yugawara/extension/scalar/exists.h>
1213

1314
#include <yugawara/binding/extract.h>
1415

@@ -17,6 +18,7 @@
1718

1819
#include <mizugaki/ast/scalar/value_constructor.h>
1920
#include <mizugaki/ast/scalar/subquery.h>
21+
#include <mizugaki/ast/scalar/table_predicate.h>
2022
#include <mizugaki/ast/query/query.h>
2123
#include <mizugaki/ast/query/table_reference.h>
2224
#include <mizugaki/ast/query/table_value_constructor.h>
@@ -151,4 +153,45 @@ TEST_F(analyze_scalar_expression_subquery_test, row_subquery_unsupported) {
151153
});
152154
}
153155

156+
TEST_F(analyze_scalar_expression_subquery_test, table_predicate_exists) {
157+
auto r = analyze_scalar_expression(
158+
context(),
159+
ast::scalar::table_predicate {
160+
ast::scalar::table_operator::exists,
161+
ast::query::table_value_constructor {
162+
ast::scalar::value_constructor {
163+
literal(number("1")),
164+
},
165+
},
166+
},
167+
scope,
168+
{});
169+
ASSERT_TRUE(r) << diagnostics();
170+
171+
auto&& exists = downcast<::yugawara::extension::scalar::exists>(*r);
172+
auto&& subgraph = exists.query_graph();
173+
ASSERT_EQ(subgraph.size(), 1);
174+
175+
auto&& subquery_output = exists.find_output_port();
176+
ASSERT_TRUE(subquery_output);
177+
ASSERT_FALSE(subquery_output->opposite());
178+
ASSERT_TRUE(subgraph.contains(subquery_output->owner()));
179+
180+
// values -
181+
auto&& values = downcast<trelation::values>(subquery_output->owner());
182+
auto&& values_columns = values.columns();
183+
ASSERT_EQ(values_columns.size(), 1);
184+
}
185+
186+
TEST_F(analyze_scalar_expression_subquery_test, table_predicate_unique_unsupported) {
187+
invalid(sql_analyzer_code::unsupported_feature, ast::scalar::table_predicate {
188+
ast::scalar::table_operator::unique,
189+
ast::query::table_value_constructor {
190+
ast::scalar::value_constructor {
191+
literal(number("1")),
192+
},
193+
},
194+
});
195+
}
196+
154197
} // namespace mizugaki::analyzer::details

0 commit comments

Comments
 (0)