diff options
author | vitya-smirnov <[email protected]> | 2025-07-22 11:57:55 +0300 |
---|---|---|
committer | vitya-smirnov <[email protected]> | 2025-07-22 12:16:44 +0300 |
commit | cf94d8a9ef2bd554213054a9cb6352a20a134a10 (patch) | |
tree | 508577e572363c0a0b6ca1617af0179c0edbeaae /yql/essentials/sql | |
parent | 483d11bf5a8df9991fc6c614908d8f5a750dcca8 (diff) |
YQL-20221: Change binding replace range
Symbol `$` was excluded from the `BindingName`
candidate content as `Replxx` interprets `$` as
a word break. The problem is that Monaco Editor
accounts `$` as a word part and filters out bindings.
This patch makes `$` a word part and adds replace
range to handle this properly at `Replxx`.
commit_hash:ca3959635a6c0e6688bcbe7622a9c2aab6c683eb
Diffstat (limited to 'yql/essentials/sql')
5 files changed, 60 insertions, 15 deletions
diff --git a/yql/essentials/sql/v1/complete/analysis/local/local.cpp b/yql/essentials/sql/v1/complete/analysis/local/local.cpp index 9db61777db7..1d0dd20a282 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/local.cpp +++ b/yql/essentials/sql/v1/complete/analysis/local/local.cpp @@ -26,6 +26,11 @@ namespace NSQLComplete { + enum class ERangeKind { + Replace, + Filter, + }; + template <std::regular_invocable<TParserCallStack> StackPredicate> std::regular_invocable<TMatchedRule> auto RuleAdapted(StackPredicate predicate) { return [=](const TMatchedRule& rule) { @@ -87,8 +92,12 @@ namespace NSQLComplete { TLocalSyntaxContext result; result.IsQuoted = Quotation(input, context); - result.EditRange = EditRange(context); - result.EditRange.Begin += statement_position; + + result.ReplaceRange = EditRange(context, ERangeKind::Replace); + result.ReplaceRange.Begin += statement_position; + + result.FilterRange = EditRange(context, ERangeKind::Filter); + result.FilterRange.Begin += statement_position; if (auto enclosing = context.Enclosing()) { if (enclosing->IsLiteral()) { @@ -356,7 +365,17 @@ namespace NSQLComplete { return isQuoted; } - TEditRange EditRange(const TCursorTokenContext& context) const { + TEditRange EditRange(const TCursorTokenContext& context, ERangeKind kind) const { + if (TMaybe<TRichParsedToken> begin; + kind == ERangeKind::Replace && + ((begin = context.MatchCursorPrefix({"DOLLAR"})) || + (begin = context.MatchCursorPrefix({"DOLLAR", ""})))) { + return { + .Begin = begin->Position, + .Length = context.Cursor.Position - begin->Position, + }; + } + 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 3086c0663fa..e3f13a88a50 100644 --- a/yql/essentials/sql/v1/complete/analysis/local/local.h +++ b/yql/essentials/sql/v1/complete/analysis/local/local.h @@ -76,7 +76,8 @@ namespace NSQLComplete { bool Binding = false; TQuotation IsQuoted; - TEditRange EditRange; + TEditRange ReplaceRange; + TEditRange FilterRange; }; // TODO(YQL-19747): Make it thread-safe to make ISqlCompletionEngine thread-safe. diff --git a/yql/essentials/sql/v1/complete/name_mapping.cpp b/yql/essentials/sql/v1/complete/name_mapping.cpp index fe1f37860e9..29fda533c92 100644 --- a/yql/essentials/sql/v1/complete/name_mapping.cpp +++ b/yql/essentials/sql/v1/complete/name_mapping.cpp @@ -127,10 +127,8 @@ namespace NSQLComplete { return {ECandidateKind::ColumnName, std::move(name.Identifier)}; } - TCandidate ToCandidate(TBindingName name, TLocalSyntaxContext& local) { - if (!local.Binding) { - name.Identifier.prepend('$'); - } + TCandidate ToCandidate(TBindingName name) { + name.Identifier.prepend('$'); return {ECandidateKind::BindingName, std::move(name.Identifier)}; } @@ -149,7 +147,6 @@ namespace NSQLComplete { std::is_same_v<T, TFolderName> || std::is_same_v<T, TTableName> || std::is_same_v<T, TColumnName> || - std::is_same_v<T, TBindingName> || std::is_same_v<T, TUnknownName>; constexpr bool IsDocumented = diff --git a/yql/essentials/sql/v1/complete/sql_complete.cpp b/yql/essentials/sql/v1/complete/sql_complete.cpp index 253e4731835..dfafedd86ab 100644 --- a/yql/essentials/sql/v1/complete/sql_complete.cpp +++ b/yql/essentials/sql/v1/complete/sql_complete.cpp @@ -70,7 +70,7 @@ namespace NSQLComplete { TNameRequest request = NameRequestFrom(input, local, global); if (request.IsEmpty()) { return NThreading::MakeFuture<TCompletion>({ - .CompletedToken = GetCompletedToken(input, local.EditRange), + .CompletedToken = GetCompletedToken(input, local.ReplaceRange), .Candidates = {}, }); } @@ -109,7 +109,7 @@ namespace NSQLComplete { const TLocalSyntaxContext& local, const TGlobalContext& global) const { TNameRequest request = { - .Prefix = TString(GetCompletedToken(input, local.EditRange).Content), + .Prefix = TString(GetCompletedToken(input, local.FilterRange).Content), .Limit = Configuration_.Limit, }; @@ -177,7 +177,7 @@ namespace NSQLComplete { TCompletion ToCompletion(TCompletionInput input, TLocalSyntaxContext local, TNameResponse response) const { TCompletion completion = { - .CompletedToken = GetCompletedToken(input, local.EditRange), + .CompletedToken = GetCompletedToken(input, local.ReplaceRange), .Candidates = ToCandidate(std::move(response.RankedNames), std::move(local)), }; diff --git a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp index c7451c39d53..d1dd837f9f9 100644 --- a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp +++ b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp @@ -1062,19 +1062,47 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) { } { TVector<TCandidate> expected = { - {BindingName, "a"}, - {BindingName, "abac"}, + {BindingName, "$a"}, + {BindingName, "$abac"}, }; UNIT_ASSERT_VALUES_EQUAL(Complete(engine, query + "$"), expected); } { TVector<TCandidate> expected = { - {BindingName, "abac"}, + {BindingName, "$abac"}, }; UNIT_ASSERT_VALUES_EQUAL(Complete(engine, query + "$ab"), expected); } } + Y_UNIT_TEST(BindingEditRange) { + auto engine = MakeSqlCompletionEngineUT(); + { + TString query = R"sql( + $abacaba=0; + SELECT # + )sql"; + TCompletion c = engine->Complete(SharpedInput(query)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(c.CompletedToken.Content, ""); + } + { + TString query = R"sql( + $abacaba=0; + SELECT $# + )sql"; + TCompletion c = engine->Complete(SharpedInput(query)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(c.CompletedToken.Content, "$"); + } + { + TString query = R"sql( + $abacaba=0; + SELECT $aba# + )sql"; + TCompletion c = engine->Complete(SharpedInput(query)).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(c.CompletedToken.Content, "$aba"); + } + } + Y_UNIT_TEST(TableFunction) { auto engine = MakeSqlCompletionEngineUT(); { |