diff options
author | vitya-smirnov <[email protected]> | 2025-06-19 14:48:15 +0300 |
---|---|---|
committer | vitya-smirnov <[email protected]> | 2025-06-19 15:26:22 +0300 |
commit | 460876175ab7e105d4b4513a308493fc73eeedb6 (patch) | |
tree | c0fcf5af3c56825d868f62e72da5ab1f30194324 /yql/essentials/sql | |
parent | 8d42f4f2ab6e419a05a55ba8d71dda34c446c22b (diff) |
YQL-19747: Auto-close backtick on not folder
When table `folder/table` exists. On prefix
``` SELECT * FROM `folder/ ``` users want to
accept ``` table` ``` rather than just `table`.
This patch is about it.
commit_hash:12d36cbf037db91f49136ab8e013b160a28b5b1b
Diffstat (limited to 'yql/essentials/sql')
6 files changed, 39 insertions, 19 deletions
diff --git a/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.cpp b/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.cpp index 445f863a255..0c091b6c4ee 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.cpp +++ b/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.cpp @@ -67,6 +67,10 @@ namespace NSQLComplete { Base->Name == "REAL"; } + size_t TRichParsedToken::End() const { + return Position + Base->Content.size(); + } + TRichParsedToken TokenAt(const TCursorTokenContext& context, size_t index) { return { .Base = &context.Tokens.at(index), diff --git a/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.h b/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.h index 9db544b5234..987bfa90914 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.h +++ b/yql/essentials/sql/v1/complete/analysis/local/cursor_token_context.h @@ -25,6 +25,7 @@ namespace NSQLComplete { size_t Position = 0; bool IsLiteral() const; + size_t End() const; }; struct TCursorTokenContext { diff --git a/yql/essentials/sql/v1/complete/analysis/local/local.cpp b/yql/essentials/sql/v1/complete/analysis/local/local.cpp index 014ac61e803..3841f7276f8 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/local.cpp +++ b/yql/essentials/sql/v1/complete/analysis/local/local.cpp @@ -86,6 +86,7 @@ namespace NSQLComplete { TLocalSyntaxContext result; + result.IsQuoted = Quotation(input, context); result.EditRange = EditRange(context); result.EditRange.Begin += statement_position; @@ -286,11 +287,6 @@ namespace NSQLComplete { object.Path = *path; } - if (auto enclosing = context.Enclosing(); - enclosing.Defined() && enclosing->Base->Name == "ID_QUOTED") { - object.IsQuoted = true; - } - return object; } @@ -341,6 +337,16 @@ namespace NSQLComplete { return AnyOf(candidates.Rules, RuleAdapted(IsLikelyBindingStack)); } + TLocalSyntaxContext::TQuotation Quotation(TCompletionInput input, const TCursorTokenContext& context) const { + TLocalSyntaxContext::TQuotation isQuoted; + if (auto enclosing = context.Enclosing(); + enclosing.Defined() && enclosing->Base->Name == "ID_QUOTED") { + isQuoted.AtLhs = true; + isQuoted.AtRhs = enclosing->End() <= input.Text.size(); + } + return isQuoted; + } + TEditRange EditRange(const TCursorTokenContext& context) const { if (auto enclosing = context.Enclosing()) { return EditRange(*enclosing, context.Cursor); diff --git a/yql/essentials/sql/v1/complete/analysis/local/local.h b/yql/essentials/sql/v1/complete/analysis/local/local.h index c5d73d52018..86de7d1632a 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/local.h +++ b/yql/essentials/sql/v1/complete/analysis/local/local.h @@ -41,7 +41,6 @@ namespace NSQLComplete { TString Cluster; TString Path; THashSet<EObjectKind> Kinds; - bool IsQuoted = false; bool HasCluster() const { return !Cluster.empty(); @@ -52,6 +51,11 @@ namespace NSQLComplete { TString Table; }; + struct TQuotation { + bool AtLhs = false; + bool AtRhs = false; + }; + TKeywords Keywords; TMaybe<TPragma> Pragma; bool Type = false; @@ -61,6 +65,8 @@ namespace NSQLComplete { TMaybe<TCluster> Cluster; TMaybe<TColumn> Column; bool Binding = false; + + TQuotation IsQuoted; TEditRange EditRange; }; diff --git a/yql/essentials/sql/v1/complete/sql_complete.cpp b/yql/essentials/sql/v1/complete/sql_complete.cpp index 36aecf06b20..187756c6975 100644 --- a/yql/essentials/sql/v1/complete/sql_complete.cpp +++ b/yql/essentials/sql/v1/complete/sql_complete.cpp @@ -241,16 +241,19 @@ namespace NSQLComplete { if constexpr (std::is_base_of_v<TFolderName, T>) { name.Indentifier.append('/'); - if (!context.Object || !context.Object->IsQuoted) { + if (!context.IsQuoted.AtLhs) { name.Indentifier.prepend('`'); } return {ECandidateKind::FolderName, std::move(name.Indentifier)}; } if constexpr (std::is_base_of_v<TTableName, T>) { - if (!context.Object || !context.Object->IsQuoted) { + if (!context.IsQuoted.AtLhs) { name.Indentifier.prepend('`'); } + if (!context.IsQuoted.AtRhs) { + name.Indentifier.append('`'); + } 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 1e3b2debdb1..90c2d8faeba 100644 --- a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp +++ b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp @@ -213,7 +213,7 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { auto engine = MakeSqlCompletionEngineUT(); { TVector<TCandidate> expected = { - {TableName, "`maxim"}, + {TableName, "`maxim`"}, {ClusterName, "example"}, {ClusterName, "saurus"}, {Keyword, "ANY"}, @@ -634,7 +634,7 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { } { TVector<TCandidate> expected = { - {TableName, "meta"}, + {TableName, "meta`"}, {FolderName, "service/"}, }; UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM `test/"), expected); @@ -658,13 +658,13 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { } { TVector<TCandidate> expected = { - {TableName, "`maxim"}, + {TableName, "`maxim`"}, }; UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "SELECT * FROM yt:saurus."), expected); } { TVector<TCandidate> expected = { - {TableName, "`people"}, + {TableName, "`people`"}, }; UNIT_ASSERT_VALUES_EQUAL(CompleteTop(1, engine, "SELECT * FROM example."), expected); } @@ -680,7 +680,7 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { auto engine = MakeSqlCompletionEngineUT(); { TVector<TCandidate> expected = { - {TableName, "`maxim"}, + {TableName, "`maxim`"}, {ClusterName, "example"}, {ClusterName, "saurus"}, {Keyword, "ANY"}, @@ -689,14 +689,14 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { } { TVector<TCandidate> expected = { - {TableName, "`people"}, + {TableName, "`people`"}, {FolderName, "`yql/"}, }; UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "USE yt:saurus; SELECT * FROM example."), expected); } { TVector<TCandidate> expected = { - {TableName, "`maxim"}, + {TableName, "`maxim`"}, {ClusterName, "example"}, {ClusterName, "saurus"}, {Keyword, "ANY"}, @@ -706,7 +706,7 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { { TVector<TCandidate> expected = { {BindingName, "$hello"}, - {TableName, "`maxim"}, + {TableName, "`maxim`"}, {ClusterName, "example"}, {ClusterName, "saurus"}, {Keyword, "ANY"}, @@ -722,7 +722,7 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { { TVector<TCandidate> expected = { {BindingName, "$action"}, - {TableName, "`people"}, + {TableName, "`people`"}, {FolderName, "`yql/"}, {ClusterName, "example"}, {ClusterName, "saurus"}, @@ -1401,8 +1401,8 @@ JOIN yt:$cluster_name.test; auto petyaEngine = MakeSqlCompletionEngine(lexer, std::move(petyaService)); TVector<TCandidate> empty; - TVector<TCandidate> aliceExpected = {{TableName, "`alice"}}; - TVector<TCandidate> petyaExpected = {{TableName, "`petya"}}; + TVector<TCandidate> aliceExpected = {{TableName, "`alice`"}}; + TVector<TCandidate> petyaExpected = {{TableName, "`petya`"}}; // Cache is empty UNIT_ASSERT_VALUES_EQUAL(Complete(aliceEngine, "SELECT * FROM "), empty); |