summaryrefslogtreecommitdiffstats
path: root/yql/essentials/sql
diff options
context:
space:
mode:
authorvitya-smirnov <[email protected]>2025-07-22 11:57:55 +0300
committervitya-smirnov <[email protected]>2025-07-22 12:16:44 +0300
commitcf94d8a9ef2bd554213054a9cb6352a20a134a10 (patch)
tree508577e572363c0a0b6ca1617af0179c0edbeaae /yql/essentials/sql
parent483d11bf5a8df9991fc6c614908d8f5a750dcca8 (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')
-rw-r--r--yql/essentials/sql/v1/complete/analysis/local/local.cpp25
-rw-r--r--yql/essentials/sql/v1/complete/analysis/local/local.h3
-rw-r--r--yql/essentials/sql/v1/complete/name_mapping.cpp7
-rw-r--r--yql/essentials/sql/v1/complete/sql_complete.cpp6
-rw-r--r--yql/essentials/sql/v1/complete/sql_complete_ut.cpp34
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();
{