summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvityaman <[email protected]>2025-05-27 11:56:16 +0300
committerrobot-piglet <[email protected]>2025-05-27 12:09:17 +0300
commit04c43eb2d8297ffe7b7b7a5b4ca48980d01fca96 (patch)
tree4230ea5e52fbdbfd3068624004cdc054e1952268
parent844ea8aaa5c094d9210b9535d06d98cc5bb56afa (diff)
YQL-19747: Support immediate string named expressions
--- - Related to `YQL-19747` - Related to https://github.com/vityaman/ydb/issues/50 --- Pull Request resolved: https://github.com/ytsaurus/ytsaurus/pull/1292 commit_hash:a6d543bc18b2f9239bf0b33afd8497a7919fe4b3
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/evaluate.cpp52
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/evaluate.h11
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/global.cpp8
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/global.h3
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/use.cpp36
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/use.h3
-rw-r--r--yql/essentials/sql/v1/complete/analysis/global/ya.make1
-rw-r--r--yql/essentials/sql/v1/complete/core/environment.cpp1
-rw-r--r--yql/essentials/sql/v1/complete/core/environment.h16
-rw-r--r--yql/essentials/sql/v1/complete/core/ya.make5
-rw-r--r--yql/essentials/sql/v1/complete/sql_complete.cpp6
-rw-r--r--yql/essentials/sql/v1/complete/sql_complete.h4
-rw-r--r--yql/essentials/sql/v1/complete/sql_complete_ut.cpp56
13 files changed, 180 insertions, 22 deletions
diff --git a/yql/essentials/sql/v1/complete/analysis/global/evaluate.cpp b/yql/essentials/sql/v1/complete/analysis/global/evaluate.cpp
new file mode 100644
index 00000000000..b938eaf0631
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/analysis/global/evaluate.cpp
@@ -0,0 +1,52 @@
+#include "evaluate.h"
+
+namespace NSQLComplete {
+
+ namespace {
+
+ class TVisitor: public SQLv1Antlr4BaseVisitor {
+ public:
+ explicit TVisitor(const TEnvironment* env)
+ : Env_(env)
+ {
+ }
+
+ std::any visitBind_parameter(SQLv1::Bind_parameterContext* ctx) override {
+ std::string id = GetId(ctx);
+ if (const NYT::TNode* node = Env_->Parameters.FindPtr(id)) {
+ return *node;
+ }
+ return defaultResult();
+ }
+
+ std::any defaultResult() override {
+ return NYT::TNode();
+ }
+
+ private:
+ std::string GetId(SQLv1::Bind_parameterContext* ctx) const {
+ if (auto* x = ctx->an_id_or_type()) {
+ return x->getText();
+ } else if (auto* x = ctx->TOKEN_TRUE()) {
+ return x->getText();
+ } else if (auto* x = ctx->TOKEN_FALSE()) {
+ return x->getText();
+ } else {
+ Y_ABORT("You should change implementation according grammar changes");
+ }
+ }
+
+ const TEnvironment* Env_;
+ };
+
+ NYT::TNode EvaluateG(antlr4::ParserRuleContext* ctx, const TEnvironment& env) {
+ return std::any_cast<NYT::TNode>(TVisitor(&env).visit(ctx));
+ }
+
+ } // namespace
+
+ NYT::TNode Evaluate(SQLv1::Bind_parameterContext* ctx, const TEnvironment& env) {
+ return EvaluateG(ctx, env);
+ }
+
+} // namespace NSQLComplete
diff --git a/yql/essentials/sql/v1/complete/analysis/global/evaluate.h b/yql/essentials/sql/v1/complete/analysis/global/evaluate.h
new file mode 100644
index 00000000000..03cbcdc798b
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/analysis/global/evaluate.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "parse_tree.h"
+
+#include <yql/essentials/sql/v1/complete/core/environment.h>
+
+namespace NSQLComplete {
+
+ NYT::TNode Evaluate(SQLv1::Bind_parameterContext* ctx, const TEnvironment& env);
+
+} // 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 a216b03de1a..9acb3310fac 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/global.cpp
+++ b/yql/essentials/sql/v1/complete/analysis/global/global.cpp
@@ -42,13 +42,13 @@ namespace NSQLComplete {
Parser_.setErrorHandler(std::make_shared<TErrorStrategy>());
}
- TGlobalContext Analyze(TCompletionInput input) override {
+ TGlobalContext Analyze(TCompletionInput input, TEnvironment env) override {
SQLv1::Sql_queryContext* sqlQuery = Parse(input.Text);
Y_ENSURE(sqlQuery);
TGlobalContext ctx;
- ctx.Use = FindUseStatement(sqlQuery, &Tokens_, input.CursorPosition);
+ ctx.Use = FindUseStatement(sqlQuery, &Tokens_, input.CursorPosition, env);
return ctx;
}
@@ -70,9 +70,9 @@ namespace NSQLComplete {
class TGlobalAnalysis: public IGlobalAnalysis {
public:
- TGlobalContext Analyze(TCompletionInput input) override {
+ TGlobalContext Analyze(TCompletionInput input, TEnvironment env) override {
const bool isAnsiLexer = IsAnsiQuery(TString(input.Text));
- return GetSpecialized(isAnsiLexer).Analyze(std::move(input));
+ return GetSpecialized(isAnsiLexer).Analyze(std::move(input), std::move(env));
}
private:
diff --git a/yql/essentials/sql/v1/complete/analysis/global/global.h b/yql/essentials/sql/v1/complete/analysis/global/global.h
index a5249bc3a48..97c55738e45 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/global.h
+++ b/yql/essentials/sql/v1/complete/analysis/global/global.h
@@ -1,6 +1,7 @@
#pragma once
#include <yql/essentials/sql/v1/complete/core/input.h>
+#include <yql/essentials/sql/v1/complete/core/environment.h>
#include <util/generic/ptr.h>
#include <util/generic/maybe.h>
@@ -22,7 +23,7 @@ namespace NSQLComplete {
using TPtr = THolder<IGlobalAnalysis>;
virtual ~IGlobalAnalysis() = default;
- virtual TGlobalContext Analyze(TCompletionInput input) = 0;
+ virtual TGlobalContext Analyze(TCompletionInput input, TEnvironment env) = 0;
};
IGlobalAnalysis::TPtr MakeGlobalAnalysis();
diff --git a/yql/essentials/sql/v1/complete/analysis/global/use.cpp b/yql/essentials/sql/v1/complete/analysis/global/use.cpp
index da7dc6a5751..2fd7fab6614 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/use.cpp
+++ b/yql/essentials/sql/v1/complete/analysis/global/use.cpp
@@ -1,14 +1,20 @@
#include "use.h"
+#include "evaluate.h"
+
namespace NSQLComplete {
namespace {
class TVisitor: public SQLv1Antlr4BaseVisitor {
public:
- TVisitor(antlr4::TokenStream* tokens, size_t cursorPosition)
+ TVisitor(
+ antlr4::TokenStream* tokens,
+ size_t cursorPosition,
+ const TEnvironment* env)
: Tokens_(tokens)
, CursorPosition_(cursorPosition)
+ , Env_(env)
{
}
@@ -33,7 +39,9 @@ namespace NSQLComplete {
}
if (SQLv1::Pure_column_or_namedContext* ctx = expr->pure_column_or_named()) {
- cluster = ctx->getText();
+ if (auto id = GetId(ctx)) {
+ cluster = std::move(*id);
+ }
}
if (cluster.empty()) {
@@ -76,8 +84,27 @@ namespace NSQLComplete {
return antlr4::misc::Interval(CursorPosition_, CursorPosition_);
}
+ TMaybe<TString> GetId(SQLv1::Pure_column_or_namedContext* ctx) const {
+ if (auto* x = ctx->bind_parameter()) {
+ return GetId(x);
+ } else if (auto* x = ctx->an_id()) {
+ return x->getText();
+ } else {
+ Y_ABORT("You should change implementation according grammar changes");
+ }
+ }
+
+ TMaybe<TString> GetId(SQLv1::Bind_parameterContext* ctx) const {
+ NYT::TNode node = Evaluate(ctx, *Env_);
+ if (!node.HasValue() || !node.IsString()) {
+ return Nothing();
+ }
+ return node.AsString();
+ }
+
antlr4::TokenStream* Tokens_;
size_t CursorPosition_;
+ const TEnvironment* Env_;
};
} // namespace
@@ -85,8 +112,9 @@ namespace NSQLComplete {
TMaybe<TUseContext> FindUseStatement(
SQLv1::Sql_queryContext* ctx,
antlr4::TokenStream* tokens,
- size_t cursorPosition) {
- std::any result = TVisitor(tokens, cursorPosition).visit(ctx);
+ size_t cursorPosition,
+ const TEnvironment& env) {
+ std::any result = TVisitor(tokens, cursorPosition, &env).visit(ctx);
if (!result.has_value()) {
return Nothing();
}
diff --git a/yql/essentials/sql/v1/complete/analysis/global/use.h b/yql/essentials/sql/v1/complete/analysis/global/use.h
index 54f3557fd62..0cdb9b15469 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/use.h
+++ b/yql/essentials/sql/v1/complete/analysis/global/use.h
@@ -12,6 +12,7 @@ namespace NSQLComplete {
TMaybe<TUseContext> FindUseStatement(
SQLv1::Sql_queryContext* ctx,
antlr4::TokenStream* tokens,
- size_t cursorPosition);
+ size_t cursorPosition,
+ const TEnvironment& env);
} // namespace NSQLComplete
diff --git a/yql/essentials/sql/v1/complete/analysis/global/ya.make b/yql/essentials/sql/v1/complete/analysis/global/ya.make
index a28d99f94c2..a8aa1eb7214 100644
--- a/yql/essentials/sql/v1/complete/analysis/global/ya.make
+++ b/yql/essentials/sql/v1/complete/analysis/global/ya.make
@@ -1,6 +1,7 @@
LIBRARY()
SRCS(
+ evaluate.cpp
global.cpp
use.cpp
)
diff --git a/yql/essentials/sql/v1/complete/core/environment.cpp b/yql/essentials/sql/v1/complete/core/environment.cpp
new file mode 100644
index 00000000000..89f179533be
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/core/environment.cpp
@@ -0,0 +1 @@
+#include "environment.h"
diff --git a/yql/essentials/sql/v1/complete/core/environment.h b/yql/essentials/sql/v1/complete/core/environment.h
new file mode 100644
index 00000000000..0f0299a9353
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/core/environment.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <library/cpp/yson/node/node.h>
+
+#include <util/generic/string.h>
+#include <util/generic/hash.h>
+
+namespace NSQLComplete {
+
+ struct TEnvironment {
+ // Given `{ "$x": "{ "Data": "foo" }" }`,
+ // it will contain `{ "$x": "foo" }`
+ THashMap<TString, NYT::TNode> Parameters;
+ };
+
+} // namespace NSQLComplete
diff --git a/yql/essentials/sql/v1/complete/core/ya.make b/yql/essentials/sql/v1/complete/core/ya.make
index 8bc457f8f95..599810301ca 100644
--- a/yql/essentials/sql/v1/complete/core/ya.make
+++ b/yql/essentials/sql/v1/complete/core/ya.make
@@ -1,7 +1,12 @@
LIBRARY()
SRCS(
+ environment.cpp
input.cpp
)
+PEERDIR(
+ library/cpp/yson/node
+)
+
END()
diff --git a/yql/essentials/sql/v1/complete/sql_complete.cpp b/yql/essentials/sql/v1/complete/sql_complete.cpp
index 2e155ff6f3b..22fc6b31062 100644
--- a/yql/essentials/sql/v1/complete/sql_complete.cpp
+++ b/yql/essentials/sql/v1/complete/sql_complete.cpp
@@ -26,10 +26,10 @@ namespace NSQLComplete {
}
TCompletion Complete(TCompletionInput input) override {
- return CompleteAsync(std::move(input)).ExtractValueSync();
+ return CompleteAsync(std::move(input), {}).ExtractValueSync();
}
- virtual NThreading::TFuture<TCompletion> CompleteAsync(TCompletionInput input) override {
+ virtual NThreading::TFuture<TCompletion> CompleteAsync(TCompletionInput input, TEnvironment env) override {
if (
input.CursorPosition < input.Text.length() &&
IsUTF8ContinuationByte(input.Text.at(input.CursorPosition)) ||
@@ -42,7 +42,7 @@ namespace NSQLComplete {
TLocalSyntaxContext context = SyntaxAnalysis_->Analyze(input);
auto keywords = context.Keywords;
- TGlobalContext global = GlobalAnalysis_->Analyze(input);
+ TGlobalContext global = GlobalAnalysis_->Analyze(input, std::move(env));
TNameRequest request = NameRequestFrom(input, context, global);
if (request.IsEmpty()) {
diff --git a/yql/essentials/sql/v1/complete/sql_complete.h b/yql/essentials/sql/v1/complete/sql_complete.h
index a600efcdac9..f72a228f62a 100644
--- a/yql/essentials/sql/v1/complete/sql_complete.h
+++ b/yql/essentials/sql/v1/complete/sql_complete.h
@@ -1,6 +1,7 @@
#pragma once
#include <yql/essentials/sql/v1/complete/core/input.h>
+#include <yql/essentials/sql/v1/complete/core/environment.h>
#include <yql/essentials/sql/v1/complete/name/service/name_service.h>
#include <yql/essentials/sql/v1/lexer/lexer.h>
@@ -52,7 +53,8 @@ namespace NSQLComplete {
virtual ~ISqlCompletionEngine() = default;
virtual TCompletion Complete(TCompletionInput input) = 0; // TODO(YQL-19747): migrate YDB CLI to CompleteAsync
- virtual NThreading::TFuture<TCompletion> CompleteAsync(TCompletionInput input) = 0;
+ virtual NThreading::TFuture<TCompletion>
+ CompleteAsync(TCompletionInput input, TEnvironment env = {}) = 0;
};
using TLexerSupplier = std::function<NSQLTranslation::ILexer::TPtr(bool ansi)>;
diff --git a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp
index dc5690853f5..60a77a422d9 100644
--- a/yql/essentials/sql/v1/complete/sql_complete_ut.cpp
+++ b/yql/essentials/sql/v1/complete/sql_complete_ut.cpp
@@ -127,8 +127,8 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) {
return MakeSqlCompletionEngine(std::move(lexer), std::move(service));
}
- TVector<TCandidate> Complete(ISqlCompletionEngine::TPtr& engine, TString sharped) {
- return engine->CompleteAsync(SharpedInput(sharped)).GetValueSync().Candidates;
+ TVector<TCandidate> Complete(ISqlCompletionEngine::TPtr& engine, TString sharped, TEnvironment env = {}) {
+ return engine->CompleteAsync(SharpedInput(sharped), std::move(env)).GetValueSync().Candidates;
}
TVector<TCandidate> CompleteTop(size_t limit, ISqlCompletionEngine::TPtr& engine, TString sharped) {
@@ -196,6 +196,41 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) {
UNIT_ASSERT_VALUES_EQUAL(Complete(engine, "USE "), expected);
}
+ Y_UNIT_TEST(UseClusterResultion) {
+ auto engine = MakeSqlCompletionEngineUT();
+ {
+ TVector<TCandidate> expected = {
+ {TableName, "`maxim`"},
+ {ClusterName, "example"},
+ {ClusterName, "yt:saurus"},
+ {Keyword, "ANY"},
+ };
+ UNIT_ASSERT_VALUES_EQUAL(
+ Complete(
+ engine,
+ "USE yt:$cluster_name; SELECT * FROM ",
+ {.Parameters = {{"cluster_name", "saurus"}}}),
+ expected);
+ }
+ {
+ TVector<TCandidate> expected = {
+ {FolderName, "`.sys/`"},
+ {FolderName, "`local/`"},
+ {FolderName, "`prod/`"},
+ {FolderName, "`test/`"},
+ {ClusterName, "example"},
+ {ClusterName, "yt:saurus"},
+ {Keyword, "ANY"},
+ };
+ UNIT_ASSERT_VALUES_EQUAL(
+ Complete(
+ engine,
+ "USE yt:$cluster_name; SELECT * FROM ",
+ {.Parameters = {}}),
+ expected);
+ }
+ }
+
Y_UNIT_TEST(Alter) {
TVector<TCandidate> expected = {
{Keyword, "ASYNC REPLICATION"},
@@ -981,12 +1016,17 @@ Y_UNIT_TEST_SUITE(SqlCompleteTests) {
}
Y_UNIT_TEST(Tabbing) {
- TString query =
- "SELECT \n"
- " 123467, \"Hello, {name}! 编码\"}, \n"
- " (1 + (5 * 1 / 0)), MIN(identifier), \n"
- " Bool(field), Math::Sin(var) \n"
- "FROM `local/test/space/table` JOIN test;";
+ TString query = R"(
+USE example;
+
+SELECT
+ 123467, \"Hello, {name}! 编码\"},
+ (1 + (5 * 1 / 0)), MIN(identifier),
+ Bool(field), Math::Sin(var)
+FROM `local/test/space/table`
+JOIN yt:$cluster_name.test;
+)";
+
query += query + ";";
query += query + ";";