diff options
author | vitya-smirnov <[email protected]> | 2025-10-01 20:51:41 +0300 |
---|---|---|
committer | vitya-smirnov <[email protected]> | 2025-10-01 21:25:50 +0300 |
commit | f3f7b33a285e94cb3e27aaa4d9b23b543ece4106 (patch) | |
tree | 89740eeddb803123f1ed3d6b6f7be2bcd865f68c /yql/essentials/sql/v1/complete | |
parent | 5cfb01d33937d2b2e038abf3b50e04136dcf7496 (diff) |
YQL-20307: Support inline subqueries
- Alter grammar to support inline subqueries.
- Support inline subqueries in `sql/v1` (translator).
- Introduce `sql/v1/proto_ast/parse_tree.h` for reusable parse tree predicates.
- Support inline subqueries in `sql/v1/format`.
- Support inline subqueries in `sql/v1/complete`.
- Add some SQL-tests.
- Pass all tests.
commit_hash:075b2240778d071e1c7542f912d3cc83019ef849
Diffstat (limited to 'yql/essentials/sql/v1/complete')
4 files changed, 60 insertions, 5 deletions
diff --git a/yql/essentials/sql/v1/complete/analysis/global/column.cpp b/yql/essentials/sql/v1/complete/analysis/global/column.cpp index 3f71ae6763d..d8c73e00b7f 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/column.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/column.cpp @@ -295,6 +295,30 @@ namespace NSQLComplete { const TNamedNodes* Nodes_; }; + class TEnclosingSelectVisitor: public TSQLv1NarrowingVisitor { + public: + explicit TEnclosingSelectVisitor(const TParsedInput& input) + : TSQLv1NarrowingVisitor(input) + { + } + + std::any visitSelect_core(SQLv1::Select_coreContext* ctx) override { + if (!IsEnclosing(ctx)) { + return {}; + } + + Enclosing_ = ctx; + return visitChildren(ctx); + } + + SQLv1::Select_coreContext* GetEnclosing() && { + return Enclosing_; + } + + private: + SQLv1::Select_coreContext* Enclosing_ = nullptr; + }; + class TVisitor: public TSQLv1NarrowingVisitor { public: TVisitor(const TParsedInput& input, const TNamedNodes* nodes) @@ -343,11 +367,23 @@ namespace NSQLComplete { const TNamedNodes* Nodes_; }; + antlr4::ParserRuleContext* Enclosing(const TParsedInput& input) { + TEnclosingSelectVisitor visitor(input); + visitor.visit(input.SqlQuery); + + antlr4::ParserRuleContext* ctx = std::move(visitor).GetEnclosing(); + if (!ctx) { + ctx = input.SqlQuery; + } + + return ctx; + } + } // namespace TMaybe<TColumnContext> InferColumnContext(TParsedInput input, const TNamedNodes& nodes) { // TODO: add utility `auto ToMaybe<T>(std::any any) -> TMaybe<T>` - std::any result = TVisitor(input, &nodes).visit(input.SqlQuery); + std::any result = TVisitor(input, &nodes).visit(Enclosing(input)); if (!result.has_value()) { return Nothing(); } diff --git a/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp b/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp index af8c17d3da2..4199da625c2 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp @@ -99,8 +99,6 @@ namespace NSQLComplete { if (auto* expr = ctx->expr()) { (*Names_)[std::move(*id)] = expr; - } else if (auto* subselect = ctx->subselect_stmt()) { - (*Names_)[std::move(*id)] = subselect; } else { (*Names_)[std::move(*id)] = std::monostate(); } diff --git a/yql/essentials/sql/v1/complete/analysis/global/named_node.h b/yql/essentials/sql/v1/complete/analysis/global/named_node.h index 07e1e6f91b9..0050915f523 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/named_node.h +++ b/yql/essentials/sql/v1/complete/analysis/global/named_node.h @@ -13,7 +13,6 @@ namespace NSQLComplete { using TNamedNode = std::variant< SQLv1::ExprContext*, - SQLv1::Subselect_stmtContext*, NYT::TNode, std::monostate>; diff --git a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp index ecb3084dcba..679230c7a24 100644 --- a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp +++ b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp @@ -1,6 +1,6 @@ #include "sql_complete.h" - #include <yql/essentials/sql/v1/complete/syntax/grammar.h> + #include <yql/essentials/sql/v1/complete/name/cache/local/cache.h> #include <yql/essentials/sql/v1/complete/name/cluster/static/discovery.h> #include <yql/essentials/sql/v1/complete/name/object/simple/schema.h> @@ -857,6 +857,8 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "$x = sel#"), expected); UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "$x = (sel#)"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT (sel#)"), expected); + UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM t WHERE (sel#)"), expected); } Y_UNIT_TEST(Upsert) { @@ -1813,6 +1815,26 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, query), expected); } + Y_UNIT_TEST(ColumnAtSubqueryExpresson) { + auto engine = MakeSqlCompletionEngineUT(); + + TVector<TString> input = { + R"sql(SELECT (SELECT # FROM (SELECT 1 AS a));)sql", + R"sql(SELECT 1 + (SELECT # FROM (SELECT 1 AS a));)sql", + R"sql(SELECT * FROM t WHERE (SELECT # FROM (SELECT 1 AS a));)sql", + R"sql(SELECT * FROM t WHERE 1 < (SELECT # FROM (SELECT 1 AS a));)sql", + }; + + TVector<TCandidate> expected = { + {ColumnName, "a"}, + }; + + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[0]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[1]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[2]), expected); + UNIT_ASSERT_VALUES_EQUAL(CompleteTop(expected.size(), engine, input[3]), expected); + } + Y_UNIT_TEST(NoBindingAtQuoted) { auto engine = MakeSqlCompletionEngineUT(); |