summaryrefslogtreecommitdiffstats
path: root/yql/essentials/sql
diff options
context:
space:
mode:
authorvityaman <[email protected]>2025-06-11 14:10:16 +0300
committerrobot-piglet <[email protected]>2025-06-11 14:25:30 +0300
commit64d942a7a113cfd57860923499139d09807bc610 (patch)
tree7c022060536c3fc361c8932be140610e32f67fd9 /yql/essentials/sql
parenta4f376903fb769e2d40cc68cbb5ae8ce649b3a9c (diff)
YQL-19747: Support table completion at CONCAT
--- - Related to `YQL-19747` - Related to https://github.com/vityaman/ydb/issues/62 --- Pull Request resolved: https://github.com/ytsaurus/ytsaurus/pull/1323 commit_hash:ebab6c3290ba984174c85bba35eeb066b53af5aa
Diffstat (limited to 'yql/essentials/sql')
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/function.cpp51
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/function.h15
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/global.cpp2
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/global.h1
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp29
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp14
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h6
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/use.cpp7
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/ya.make1
-rw-r--r--yql/essentials/sql/v1/complete/sql_complete.cpp14
-rw-r--r--yql/essentials/sql/v1/complete/sql_complete_ut.cpp14
11 files changed, 141 insertions, 13 deletions
diff --git a/yql/essentials/sql/v1/complete/analysis/global/function.cpp b/yql/essentials/sql/v1/complete/analysis/global/function.cpp
new file mode 100644
index 00000000000..16140bc614e
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/analysis/global/function.cpp
@@ -0,0 +1,51 @@
+#include "function.h"
+
+#include "narrowing_visitor.h"
+
+namespace NSQLComplete {
+
+ namespace {
+
+ class TVisitor: public TSQLv1NarrowingVisitor {
+ public:
+ TVisitor(antlr4::TokenStream* tokens, size_t cursorPosition)
+ : TSQLv1NarrowingVisitor(tokens, cursorPosition)
+ {
+ }
+
+ std::any visit(antlr4::tree::ParseTree* tree) override {
+ if (IsEnclosing(tree)) {
+ return TSQLv1NarrowingVisitor::visit(tree);
+ }
+ return {};
+ }
+
+ std::any visitTable_ref(SQLv1::Table_refContext* ctx) override {
+ auto* function = ctx->an_id_expr();
+ auto* lparen = ctx->TOKEN_LPAREN();
+ if (function == nullptr || lparen == nullptr) {
+ return {};
+ }
+
+ if (CursorPosition() <= TextInterval(lparen).b) {
+ return {};
+ }
+
+ return function->getText();
+ }
+ };
+
+ } // namespace
+
+ TMaybe<TString> EnclosingFunction(
+ SQLv1::Sql_queryContext* ctx,
+ antlr4::TokenStream* tokens,
+ size_t cursorPosition) {
+ std::any result = TVisitor(tokens, cursorPosition).visit(ctx);
+ if (!result.has_value()) {
+ return Nothing();
+ }
+ return std::any_cast<std::string>(result);
+ }
+
+} // namespace NSQLComplete
diff --git a/yql/essentials/sql/v1/complete/analysis/global/function.h b/yql/essentials/sql/v1/complete/analysis/global/function.h
new file mode 100644
index 00000000000..bb94e71318e
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/analysis/global/function.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "parse_tree.h"
+
+#include <util/generic/maybe.h>
+#include <util/generic/string.h>
+
+namespace NSQLComplete {
+
+ TMaybe<TString> EnclosingFunction(
+ SQLv1::Sql_queryContext* ctx,
+ antlr4::TokenStream* tokens,
+ size_t cursorPosition);
+
+} // namespace NSQLComplete
diff --git a/yql/essentials/sql/v1/complete/analysis/global/global.cpp b/yql/essentials/sql/v1/complete/analysis/global/global.cpp
index c5f33ae8297..8f5df3f6e76 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/global.cpp
+++ b/yql/essentials/sql/v1/complete/analysis/global/global.cpp
@@ -1,5 +1,6 @@
#include "global.h"
+#include "function.h"
#include "named_node.h"
#include "parse_tree.h"
#include "use.h"
@@ -52,6 +53,7 @@ namespace NSQLComplete {
// TODO(YQL-19747): Add ~ParseContext(Tokens, ParseTree, CursorPosition)
ctx.Use = FindUseStatement(sqlQuery, &Tokens_, input.CursorPosition, env);
ctx.Names = CollectNamedNodes(sqlQuery, &Tokens_, input.CursorPosition);
+ ctx.EnclosingFunction = EnclosingFunction(sqlQuery, &Tokens_, input.CursorPosition);
return ctx;
}
diff --git a/yql/essentials/sql/v1/complete/analysis/global/global.h b/yql/essentials/sql/v1/complete/analysis/global/global.h
index 2c30dbf1cf5..3999aeb4a56 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/global.h
+++ b/yql/essentials/sql/v1/complete/analysis/global/global.h
@@ -18,6 +18,7 @@ namespace NSQLComplete {
struct TGlobalContext {
TMaybe<TUseContext> Use;
TVector<TString> Names;
+ TMaybe<TString> EnclosingFunction;
};
class IGlobalAnalysis {
diff --git a/yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp b/yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp
index 643af6efc9c..58aea33b379 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp
+++ b/yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp
@@ -69,4 +69,33 @@ Y_UNIT_TEST_SUITE(GlobalAnalysisTests) {
UNIT_ASSERT_VALUES_EQUAL(ctx.Names, expected);
}
+ Y_UNIT_TEST(EnclosingFunctionName) {
+ IGlobalAnalysis::TPtr global = MakeGlobalAnalysis();
+ {
+ TString query = "SELECT * FROM Concat(#)";
+ TGlobalContext ctx = global->Analyze(SharpedInput(query), {});
+ UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, "Concat");
+ }
+ {
+ TString query = "SELECT * FROM Concat(a, #)";
+ TGlobalContext ctx = global->Analyze(SharpedInput(query), {});
+ UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, "Concat");
+ }
+ {
+ TString query = "SELECT * FROM Concat(a#)";
+ TGlobalContext ctx = global->Analyze(SharpedInput(query), {});
+ UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, "Concat");
+ }
+ {
+ TString query = "SELECT * FROM Concat(#";
+ TGlobalContext ctx = global->Analyze(SharpedInput(query), {});
+ UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, Nothing());
+ }
+ {
+ TString query = "SELECT * FROM (#)";
+ TGlobalContext ctx = global->Analyze(SharpedInput(query), {});
+ UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, Nothing());
+ }
+ }
+
} // Y_UNIT_TEST_SUITE(GlobalAnalysisTests)
diff --git a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp
index eefb6e70f5e..a26523c94a0 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp
+++ b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp
@@ -12,10 +12,21 @@ namespace NSQLComplete {
return TextInterval(node).a < static_cast<ssize_t>(CursorPosition_);
}
+ std::any TSQLv1NarrowingVisitor::aggregateResult(std::any aggregate, std::any nextResult) {
+ if (nextResult.has_value()) {
+ return nextResult;
+ }
+ return aggregate;
+ }
+
bool TSQLv1NarrowingVisitor::IsEnclosing(antlr4::tree::ParseTree* tree) const {
return TextInterval(tree).properlyContains(CursorInterval());
}
+ ssize_t TSQLv1NarrowingVisitor::CursorPosition() const {
+ return CursorPosition_;
+ }
+
antlr4::misc::Interval TSQLv1NarrowingVisitor::TextInterval(antlr4::tree::ParseTree* tree) const {
auto tokens = tree->getSourceInterval();
if (tokens.b == -1) {
@@ -27,7 +38,8 @@ namespace NSQLComplete {
}
antlr4::misc::Interval TSQLv1NarrowingVisitor::CursorInterval() const {
- return antlr4::misc::Interval(CursorPosition_, CursorPosition_);
+ auto cursor = CursorPosition();
+ return antlr4::misc::Interval(cursor, cursor);
}
} // namespace NSQLComplete
diff --git a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h
index d5375c20322..5a3947b9355 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h
+++ b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h
@@ -9,13 +9,15 @@ namespace NSQLComplete {
TSQLv1NarrowingVisitor(antlr4::TokenStream* tokens, size_t cursorPosition);
protected:
- bool IsEnclosing(antlr4::tree::ParseTree* tree) const;
bool shouldVisitNextChild(antlr4::tree::ParseTree* node, const std::any& /*currentResult*/) override;
+ std::any aggregateResult(std::any aggregate, std::any nextResult) override;
- private:
+ bool IsEnclosing(antlr4::tree::ParseTree* tree) const;
+ ssize_t CursorPosition() const;
antlr4::misc::Interval TextInterval(antlr4::tree::ParseTree* tree) const;
antlr4::misc::Interval CursorInterval() const;
+ private:
antlr4::TokenStream* Tokens_;
size_t CursorPosition_;
};
diff --git a/yql/essentials/sql/v1/complete/analysis/global/use.cpp b/yql/essentials/sql/v1/complete/analysis/global/use.cpp
index 717a35e4e8f..d9a430ec12b 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/use.cpp
+++ b/yql/essentials/sql/v1/complete/analysis/global/use.cpp
@@ -54,13 +54,6 @@ namespace NSQLComplete {
};
}
- std::any aggregateResult(std::any aggregate, std::any nextResult) override {
- if (nextResult.has_value()) {
- return nextResult;
- }
- return aggregate;
- }
-
private:
TMaybe<TString> GetId(SQLv1::Pure_column_or_namedContext* ctx) const {
if (auto* x = ctx->bind_parameter()) {
diff --git a/yql/essentials/sql/v1/complete/analysis/global/ya.make b/yql/essentials/sql/v1/complete/analysis/global/ya.make
index da6f4a17381..b37fa3faa22 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/ya.make
+++ b/yql/essentials/sql/v1/complete/analysis/global/ya.make
@@ -2,6 +2,7 @@ LIBRARY()
SRCS(
evaluate.cpp
+ function.cpp
global.cpp
named_node.cpp
narrowing_visitor.cpp
diff --git a/yql/essentials/sql/v1/complete/sql_complete.cpp b/yql/essentials/sql/v1/complete/sql_complete.cpp
index a7d8181862e..786155912c0 100644
--- a/yql/essentials/sql/v1/complete/sql_complete.cpp
+++ b/yql/essentials/sql/v1/complete/sql_complete.cpp
@@ -79,7 +79,7 @@ namespace NSQLComplete {
TNameRequest NameRequestFrom(
TCompletionInput input,
- const TLocalSyntaxContext& context,
+ const TLocalSyntaxContext& context, // TODO(YQL-19747): rename to `local`
const TGlobalContext& global) const {
TNameRequest request = {
.Prefix = TString(GetCompletedToken(input, context.EditRange).Content),
@@ -134,6 +134,14 @@ namespace NSQLComplete {
request.Constraints.Cluster = std::move(constraints);
}
+ if (auto name = global.EnclosingFunction.Transform(NormalizeName);
+ name && name == "concat") {
+ auto& object = request.Constraints.Object;
+ object = object.Defined() ? object : TObjectNameConstraints();
+ object->Kinds.emplace(EObjectKind::Folder);
+ object->Kinds.emplace(EObjectKind::Table);
+ }
+
return request;
}
@@ -196,14 +204,14 @@ namespace NSQLComplete {
if constexpr (std::is_base_of_v<TFolderName, T>) {
name.Indentifier.append('/');
- if (!context.Object->IsQuoted) {
+ if (!context.Object || !context.Object->IsQuoted) {
name.Indentifier.prepend('`');
}
return {ECandidateKind::FolderName, std::move(name.Indentifier)};
}
if constexpr (std::is_base_of_v<TTableName, T>) {
- if (!context.Object->IsQuoted) {
+ if (!context.Object || !context.Object->IsQuoted) {
name.Indentifier.prepend('`');
}
return {ECandidateKind::TableName, std::move(name.Indentifier)};
diff --git a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp
index 0d80ff816e2..4ecc12e526f 100644
--- a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp
+++ b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp
@@ -1026,6 +1026,20 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) {
}
}
+ Y_UNIT_TEST(TableAsFunctionArgument) {
+ auto engine = MakeSqlCompletionEngineUT();
+
+ UNIT_ASSERT_VALUES_EQUAL(
+ CompleteTop(1, engine, "SELECT * FROM Concat(#)").at(0).Kind, FolderName);
+ UNIT_ASSERT_VALUES_EQUAL(
+ CompleteTop(1, engine, "SELECT * FROM CONCAT(#)").at(0).Kind, FolderName);
+ UNIT_ASSERT_VALUES_EQUAL(
+ CompleteTop(1, engine, "SELECT * FROM CONCAT(a, #)").at(0).Kind, FolderName);
+
+ UNIT_ASSERT_VALUES_UNEQUAL(
+ CompleteTop(1, engine, "SELECT Max(#)").at(0).Kind, FolderName);
+ }
+
Y_UNIT_TEST(Typing) {
const auto queryUtf16 = TUtf16String::FromUtf8(
"SELECT \n"