Skip to content

Commit 16630d4

Browse files
vityamanrobot-piglet
authored andcommitted
YQL-19747: Support USE statement
Introduce global analysis which will be extended with more ParseTree analysis later. --- - Related to `YQL-19747` - Related to vityaman#40 --- Pull Request resolved: ytsaurus/ytsaurus#1281 commit_hash:848fb3fdd6bc9612769c47d66198fca018ff465f
1 parent 2cca5c2 commit 16630d4

File tree

14 files changed

+387
-16
lines changed

14 files changed

+387
-16
lines changed

yql/essentials/parser/antlr_ast/gen/v1_antlr4/ya.make

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@ COPY_FILE(
2525
RUN_ANTLR4(
2626
${SQL_GRAMMAR}
2727
-no-listener
28+
-visitor
2829
-package NALADefaultAntlr4
2930
-lib .
3031
IN
3132
${SQL_GRAMMAR}
3233
${ARCADIA_BUILD_ROOT}/${MODDIR}/org/antlr/v4/tool/templates/codegen/Cpp/Cpp.stg
3334
${ARCADIA_BUILD_ROOT}/${MODDIR}/org/antlr/v4/tool/templates/codegen/Cpp/Files.stg
34-
OUT SQLv1Antlr4Parser.cpp SQLv1Antlr4Lexer.cpp SQLv1Antlr4Parser.h SQLv1Antlr4Lexer.h
35+
OUT SQLv1Antlr4Parser.cpp SQLv1Antlr4Parser.h
36+
SQLv1Antlr4Lexer.cpp SQLv1Antlr4Lexer.h
37+
SQLv1Antlr4Visitor.cpp SQLv1Antlr4Visitor.h
38+
SQLv1Antlr4BaseVisitor.cpp SQLv1Antlr4BaseVisitor.h
3539
OUTPUT_INCLUDES contrib/libs/antlr4_cpp_runtime/src/antlr4-runtime.h
3640
CWD ${ARCADIA_BUILD_ROOT}/${MODDIR}
3741
)
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#include "global.h"
2+
3+
#include "parse_tree.h"
4+
#include "use.h"
5+
6+
#include <yql/essentials/sql/v1/complete/antlr4/pipeline.h>
7+
#include <yql/essentials/sql/v1/complete/syntax/ansi.h>
8+
9+
namespace NSQLComplete {
10+
11+
class TErrorStrategy: public antlr4::DefaultErrorStrategy {
12+
public:
13+
antlr4::Token* singleTokenDeletion(antlr4::Parser* /* recognizer */) override {
14+
return nullptr;
15+
}
16+
};
17+
18+
template <bool IsAnsiLexer>
19+
class TSpecializedGlobalAnalysis: public IGlobalAnalysis {
20+
public:
21+
using TDefaultYQLGrammar = TAntlrGrammar<
22+
NALADefaultAntlr4::SQLv1Antlr4Lexer,
23+
NALADefaultAntlr4::SQLv1Antlr4Parser>;
24+
25+
using TAnsiYQLGrammar = TAntlrGrammar<
26+
NALAAnsiAntlr4::SQLv1Antlr4Lexer,
27+
NALAAnsiAntlr4::SQLv1Antlr4Parser>;
28+
29+
using G = std::conditional_t<
30+
IsAnsiLexer,
31+
TAnsiYQLGrammar,
32+
TDefaultYQLGrammar>;
33+
34+
TSpecializedGlobalAnalysis()
35+
: Chars_()
36+
, Lexer_(&Chars_)
37+
, Tokens_(&Lexer_)
38+
, Parser_(&Tokens_)
39+
{
40+
Lexer_.removeErrorListeners();
41+
Parser_.removeErrorListeners();
42+
Parser_.setErrorHandler(std::make_shared<TErrorStrategy>());
43+
}
44+
45+
TGlobalContext Analyze(TCompletionInput input) override {
46+
SQLv1::Sql_queryContext* sqlQuery = Parse(input.Text);
47+
Y_ENSURE(sqlQuery);
48+
49+
TGlobalContext ctx;
50+
51+
ctx.Use = FindUseStatement(sqlQuery, &Tokens_, input.CursorPosition);
52+
53+
return ctx;
54+
}
55+
56+
private:
57+
SQLv1::Sql_queryContext* Parse(TStringBuf input) {
58+
Chars_.load(input.Data(), input.Size(), /* lenient = */ false);
59+
Lexer_.reset();
60+
Tokens_.setTokenSource(&Lexer_);
61+
Parser_.reset();
62+
return Parser_.sql_query();
63+
}
64+
65+
antlr4::ANTLRInputStream Chars_;
66+
G::TLexer Lexer_;
67+
antlr4::CommonTokenStream Tokens_;
68+
TDefaultYQLGrammar::TParser Parser_;
69+
};
70+
71+
class TGlobalAnalysis: public IGlobalAnalysis {
72+
public:
73+
TGlobalContext Analyze(TCompletionInput input) override {
74+
const bool isAnsiLexer = IsAnsiQuery(TString(input.Text));
75+
return GetSpecialized(isAnsiLexer).Analyze(std::move(input));
76+
}
77+
78+
private:
79+
IGlobalAnalysis& GetSpecialized(bool isAnsiLexer) {
80+
if (isAnsiLexer) {
81+
return AnsiAnalysis_;
82+
}
83+
return DefaultAnalysis_;
84+
}
85+
86+
TSpecializedGlobalAnalysis</* IsAnsiLexer = */ false> DefaultAnalysis_;
87+
TSpecializedGlobalAnalysis</* IsAnsiLexer = */ true> AnsiAnalysis_;
88+
};
89+
90+
IGlobalAnalysis::TPtr MakeGlobalAnalysis() {
91+
return MakeHolder<TGlobalAnalysis>();
92+
}
93+
94+
} // namespace NSQLComplete
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#pragma once
2+
3+
#include <yql/essentials/sql/v1/complete/core/input.h>
4+
5+
#include <util/generic/ptr.h>
6+
#include <util/generic/maybe.h>
7+
#include <util/generic/string.h>
8+
9+
namespace NSQLComplete {
10+
11+
struct TUseContext {
12+
TString Provider;
13+
TString Cluster;
14+
};
15+
16+
struct TGlobalContext {
17+
TMaybe<TUseContext> Use;
18+
};
19+
20+
class IGlobalAnalysis {
21+
public:
22+
using TPtr = THolder<IGlobalAnalysis>;
23+
24+
virtual ~IGlobalAnalysis() = default;
25+
virtual TGlobalContext Analyze(TCompletionInput input) = 0;
26+
};
27+
28+
IGlobalAnalysis::TPtr MakeGlobalAnalysis();
29+
30+
} // namespace NSQLComplete
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
3+
#ifdef TOKEN_QUERY // Conflict with the winnt.h
4+
#undef TOKEN_QUERY
5+
#endif
6+
#include <yql/essentials/parser/antlr_ast/gen/v1_antlr4/SQLv1Antlr4Lexer.h>
7+
#include <yql/essentials/parser/antlr_ast/gen/v1_antlr4/SQLv1Antlr4Parser.h>
8+
#include <yql/essentials/parser/antlr_ast/gen/v1_antlr4/SQLv1Antlr4BaseVisitor.h>
9+
#include <yql/essentials/parser/antlr_ast/gen/v1_ansi_antlr4/SQLv1Antlr4Lexer.h>
10+
#include <yql/essentials/parser/antlr_ast/gen/v1_ansi_antlr4/SQLv1Antlr4Parser.h>
11+
12+
namespace NSQLComplete {
13+
14+
using SQLv1 = NALADefaultAntlr4::SQLv1Antlr4Parser;
15+
16+
using NALADefaultAntlr4::SQLv1Antlr4BaseVisitor;
17+
18+
} // namespace NSQLComplete
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#include "use.h"
2+
3+
namespace NSQLComplete {
4+
5+
namespace {
6+
7+
class TVisitor: public SQLv1Antlr4BaseVisitor {
8+
public:
9+
TVisitor(antlr4::TokenStream* tokens, size_t cursorPosition)
10+
: Tokens_(tokens)
11+
, CursorPosition_(cursorPosition)
12+
{
13+
}
14+
15+
std::any visitSql_stmt_core(SQLv1::Sql_stmt_coreContext* ctx) override {
16+
if (ctx->use_stmt() || IsEnclosing(ctx)) {
17+
return visitChildren(ctx);
18+
}
19+
return {};
20+
}
21+
22+
std::any visitUse_stmt(SQLv1::Use_stmtContext* ctx) override {
23+
SQLv1::Cluster_exprContext* expr = ctx->cluster_expr();
24+
if (!expr) {
25+
return {};
26+
}
27+
28+
std::string provider;
29+
std::string cluster;
30+
31+
if (SQLv1::An_idContext* ctx = expr->an_id()) {
32+
provider = ctx->getText();
33+
}
34+
35+
if (SQLv1::Pure_column_or_namedContext* ctx = expr->pure_column_or_named()) {
36+
cluster = ctx->getText();
37+
}
38+
39+
if (cluster.empty()) {
40+
return {};
41+
}
42+
43+
return TUseContext{
44+
.Provider = std::move(provider),
45+
.Cluster = std::move(cluster),
46+
};
47+
}
48+
49+
std::any aggregateResult(std::any aggregate, std::any nextResult) override {
50+
if (nextResult.has_value()) {
51+
return nextResult;
52+
}
53+
return aggregate;
54+
}
55+
56+
bool shouldVisitNextChild(antlr4::tree::ParseTree* node, const std::any& /*currentResult*/) override {
57+
return TextInterval(node).a < static_cast<ssize_t>(CursorPosition_);
58+
}
59+
60+
private:
61+
bool IsEnclosing(antlr4::tree::ParseTree* tree) const {
62+
return TextInterval(tree).properlyContains(CursorInterval());
63+
}
64+
65+
antlr4::misc::Interval TextInterval(antlr4::tree::ParseTree* tree) const {
66+
auto tokens = tree->getSourceInterval();
67+
if (tokens.b == -1) {
68+
tokens.b = tokens.a;
69+
}
70+
return antlr4::misc::Interval(
71+
Tokens_->get(tokens.a)->getStartIndex(),
72+
Tokens_->get(tokens.b)->getStopIndex());
73+
}
74+
75+
antlr4::misc::Interval CursorInterval() const {
76+
return antlr4::misc::Interval(CursorPosition_, CursorPosition_);
77+
}
78+
79+
antlr4::TokenStream* Tokens_;
80+
size_t CursorPosition_;
81+
};
82+
83+
} // namespace
84+
85+
TMaybe<TUseContext> FindUseStatement(
86+
SQLv1::Sql_queryContext* ctx,
87+
antlr4::TokenStream* tokens,
88+
size_t cursorPosition) {
89+
std::any result = TVisitor(tokens, cursorPosition).visit(ctx);
90+
if (!result.has_value()) {
91+
return Nothing();
92+
}
93+
return std::any_cast<TUseContext>(result);
94+
}
95+
96+
} // namespace NSQLComplete
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include "global.h"
4+
#include "parse_tree.h"
5+
6+
#include <util/generic/ptr.h>
7+
#include <util/generic/maybe.h>
8+
#include <util/generic/string.h>
9+
10+
namespace NSQLComplete {
11+
12+
TMaybe<TUseContext> FindUseStatement(
13+
SQLv1::Sql_queryContext* ctx,
14+
antlr4::TokenStream* tokens,
15+
size_t cursorPosition);
16+
17+
} // namespace NSQLComplete
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
LIBRARY()
2+
3+
SRCS(
4+
global.cpp
5+
use.cpp
6+
)
7+
8+
PEERDIR(
9+
yql/essentials/sql/v1/complete/core
10+
yql/essentials/parser/antlr_ast/gen/v1_antlr4
11+
yql/essentials/parser/antlr_ast/gen/v1_ansi_antlr4
12+
)
13+
14+
END()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
LIBRARY()
2+
3+
END()
4+
5+
RECURSE(
6+
global
7+
)

yql/essentials/sql/v1/complete/antlr4/c3t.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "c3i.h"
4+
#include "pipeline.h"
45

56
#include <yql/essentials/sql/v1/complete/text/word.h>
67

@@ -15,14 +16,6 @@
1516

1617
namespace NSQLComplete {
1718

18-
template <class Lexer, class Parser>
19-
struct TAntlrGrammar {
20-
using TLexer = Lexer;
21-
using TParser = Parser;
22-
23-
TAntlrGrammar() = delete;
24-
};
25-
2619
template <class G>
2720
class TC3Engine: public IC3Engine {
2821
public:
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
namespace NSQLComplete {
4+
5+
template <class Lexer, class Parser>
6+
struct TAntlrGrammar {
7+
using TLexer = Lexer;
8+
using TParser = Parser;
9+
10+
TAntlrGrammar() = delete;
11+
};
12+
13+
} // namespace NSQLComplete

0 commit comments

Comments
 (0)