summaryrefslogtreecommitdiffstats
path: root/yql/essentials/sql
diff options
context:
space:
mode:
authorvitya-smirnov <[email protected]>2025-06-25 15:43:36 +0300
committervitya-smirnov <[email protected]>2025-06-25 16:01:44 +0300
commit59fa891737bd017e3c73b3ee4320333d8f57611c (patch)
tree8c3e49287f11947bdd7d855996823e07af317332 /yql/essentials/sql
parentde5ef0597b0c69b0226eece538677890aec07b16 (diff)
YQL-19747: Hack parsing when at an empty id
There was a problem with parsing a query like `SELECT # FROM t`, as it parsed `FROM` as if it is an expeceted column name, so we failed to parse a table name after `FROM` and therefore can not complete column names, while the are so useful at this position. Also this hack improved parsing other queries, according to changed tests. commit_hash:f5a657022a164d1d4bbf906db4bd2ad67bbcd956
Diffstat (limited to 'yql/essentials/sql')
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/global.cpp22
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp2
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/named_node.cpp4
-rw-r--r--yql/essentials/sql/v1/complete/sql_complete_ut.cpp8
4 files changed, 33 insertions, 3 deletions
diff --git a/yql/essentials/sql/v1/complete/analysis/global/global.cpp b/yql/essentials/sql/v1/complete/analysis/global/global.cpp
index 191814a8e55..555d5283c14 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/global.cpp
+++ b/yql/essentials/sql/v1/complete/analysis/global/global.cpp
@@ -95,6 +95,17 @@ namespace NSQLComplete {
}
TGlobalContext Analyze(TCompletionInput input, TEnvironment env) override {
+ TString recovered;
+ if (IsRecoverable(input)) {
+ recovered = TString(input.Text);
+
+ // - "_" is to parse `SELECT x._ FROM table`
+ // instead of `SELECT x.FROM table`
+ recovered.insert(input.CursorPosition, "_");
+
+ input.Text = recovered;
+ }
+
SQLv1::Sql_queryContext* sqlQuery = Parse(input.Text);
Y_ENSURE(sqlQuery);
@@ -114,6 +125,17 @@ namespace NSQLComplete {
}
private:
+ bool IsRecoverable(TCompletionInput input) const {
+ static const TStringBuf prev = " ";
+ static const TStringBuf next = " .(";
+
+ TStringBuf s = input.Text;
+ size_t i = input.CursorPosition;
+
+ return (i < s.size() && prev.Contains(s[i]) || i == s.size()) &&
+ (i > 0 /* */ && next.Contains(s[i - 1]));
+ }
+
SQLv1::Sql_queryContext* Parse(TStringBuf input) {
Chars_.load(input.Data(), input.Size(), /* lenient = */ false);
Lexer_.reset();
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 5e180fcb431..15aba3ee155 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp
+++ b/yql/essentials/sql/v1/complete/analysis/global/global_ut.cpp
@@ -89,7 +89,7 @@ Y_UNIT_TEST_SUITE(GlobalAnalysisTests) {
{
TString query = "SELECT * FROM Concat(#";
TGlobalContext ctx = global->Analyze(SharpedInput(query), {});
- UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, Nothing());
+ UNIT_ASSERT_VALUES_EQUAL(ctx.EnclosingFunction, "Concat");
}
{
TString query = "SELECT * FROM (#)";
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 14b928c53e5..0896b508432 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp
+++ b/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp
@@ -84,6 +84,10 @@ namespace NSQLComplete {
}
std::any visitBind_parameter(SQLv1::Bind_parameterContext* ctx) override {
+ if (IsEnclosing(ctx)) {
+ return {};
+ }
+
TMaybe<std::string> id = GetId(ctx);
if (id.Empty() || id == "_") {
return {};
diff --git a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp
index 5b99c6a3fe1..aa955bc2cc5 100644
--- a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp
+++ b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp
@@ -905,6 +905,7 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) {
auto engine = MakeSqlCompletionEngineUT();
{
TVector<TCandidate> expected = {
+ {BindingName, "$udf"},
{HintName, "XLOCK"},
};
UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "PROCESS my_table USING $udf(TableRows()) WITH "), expected);
@@ -1105,8 +1106,11 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) {
};
UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT # FROM example.`/people` AS x"), expected);
}
- { // It is parsed into ``` SELECT x.FROM example.`/people` AS x ```
- TVector<TCandidate> expected = {};
+ {
+ TVector<TCandidate> expected = {
+ {ColumnName, "Age"},
+ {ColumnName, "Name"},
+ };
UNIT_ASSERT_VALUES_EQUAL(CompleteTop(2, engine, "SELECT x.# FROM example.`/people` AS x"), expected);
}
{