diff options
| author | vitya-smirnov <[email protected]> | 2025-06-26 16:37:42 +0300 | 
|---|---|---|
| committer | vitya-smirnov <[email protected]> | 2025-06-26 17:24:30 +0300 | 
| commit | 633c9e434ac33037ba01b36a8f2937034903fe9f (patch) | |
| tree | e620cfd34faf4354d3d25d05b564def09445118a | |
| parent | e99c3783c2970a70b35b1c67ba177fe940936aae (diff) | |
YQL-19747: Refactor SQL completion engine
Some refactorings to compact the code:
- YQL-19747: Pass TParsedInput to visitor
- YQL-19747: Add TParsedInput
- YQL-19747: Cosmetics
- YQL-19747: Refactor configuration
- YQL-19747: Refactor name to candidate mapping
commit_hash:44dfe7dc7bcc627ef9c20696077f2d962a3014f6
24 files changed, 336 insertions, 297 deletions
diff --git a/yql/essentials/sql/v1/complete/analysis/global/column.cpp b/yql/essentials/sql/v1/complete/analysis/global/column.cpp index 9a9fd7f18a2..5cecb40fb13 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/column.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/column.cpp @@ -220,8 +220,8 @@ namespace NSQLComplete {          class TVisitor: public TSQLv1NarrowingVisitor {          public: -            TVisitor(antlr4::TokenStream* tokens, size_t cursorPosition) -                : TSQLv1NarrowingVisitor(tokens, cursorPosition) +            TVisitor(const TParsedInput& input) +                : TSQLv1NarrowingVisitor(input)              {              } @@ -247,12 +247,9 @@ namespace NSQLComplete {      } // namespace -    TMaybe<TColumnContext> InferColumnContext( -        SQLv1::Sql_queryContext* ctx, -        antlr4::TokenStream* tokens, -        size_t cursorPosition) { +    TMaybe<TColumnContext> InferColumnContext(TParsedInput input) {          // TODO: add utility `auto ToMaybe<T>(std::any any) -> TMaybe<T>` -        std::any result = TVisitor(tokens, cursorPosition).visit(ctx); +        std::any result = TVisitor(input).visit(input.SqlQuery);          if (!result.has_value()) {              return Nothing();          } diff --git a/yql/essentials/sql/v1/complete/analysis/global/column.h b/yql/essentials/sql/v1/complete/analysis/global/column.h index 790dbee1d15..306626ba061 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/column.h +++ b/yql/essentials/sql/v1/complete/analysis/global/column.h @@ -1,13 +1,10 @@  #pragma once  #include "global.h" -#include "parse_tree.h" +#include "input.h"  namespace NSQLComplete { -    TMaybe<TColumnContext> InferColumnContext( -        SQLv1::Sql_queryContext* ctx, -        antlr4::TokenStream* tokens, -        size_t cursorPosition); +    TMaybe<TColumnContext> InferColumnContext(TParsedInput input);  } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/function.cpp b/yql/essentials/sql/v1/complete/analysis/global/function.cpp index 16140bc614e..0bd9740796a 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/function.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/function.cpp @@ -8,8 +8,8 @@ namespace NSQLComplete {          class TVisitor: public TSQLv1NarrowingVisitor {          public: -            TVisitor(antlr4::TokenStream* tokens, size_t cursorPosition) -                : TSQLv1NarrowingVisitor(tokens, cursorPosition) +            TVisitor(const TParsedInput& input) +                : TSQLv1NarrowingVisitor(input)              {              } @@ -37,11 +37,8 @@ namespace NSQLComplete {      } // namespace -    TMaybe<TString> EnclosingFunction( -        SQLv1::Sql_queryContext* ctx, -        antlr4::TokenStream* tokens, -        size_t cursorPosition) { -        std::any result = TVisitor(tokens, cursorPosition).visit(ctx); +    TMaybe<TString> EnclosingFunction(TParsedInput input) { +        std::any result = TVisitor(input).visit(input.SqlQuery);          if (!result.has_value()) {              return Nothing();          } diff --git a/yql/essentials/sql/v1/complete/analysis/global/function.h b/yql/essentials/sql/v1/complete/analysis/global/function.h index bb94e71318e..77f1478c5cc 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/function.h +++ b/yql/essentials/sql/v1/complete/analysis/global/function.h @@ -1,15 +1,12 @@  #pragma once -#include "parse_tree.h" +#include "input.h"  #include <util/generic/maybe.h>  #include <util/generic/string.h>  namespace NSQLComplete { -    TMaybe<TString> EnclosingFunction( -        SQLv1::Sql_queryContext* ctx, -        antlr4::TokenStream* tokens, -        size_t cursorPosition); +    TMaybe<TString> EnclosingFunction(TParsedInput input);  } // 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 f11447c1f12..5bdba0714b3 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/global.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/global.cpp @@ -2,6 +2,7 @@  #include "column.h"  #include "function.h" +#include "input.h"  #include "named_node.h"  #include "parse_tree.h"  #include "use.h" @@ -87,18 +88,10 @@ namespace NSQLComplete {      template <bool IsAnsiLexer>      class TSpecializedGlobalAnalysis: public IGlobalAnalysis {      public: -        using TDefaultYQLGrammar = TAntlrGrammar< -            NALADefaultAntlr4::SQLv1Antlr4Lexer, -            NALADefaultAntlr4::SQLv1Antlr4Parser>; - -        using TAnsiYQLGrammar = TAntlrGrammar< -            NALAAnsiAntlr4::SQLv1Antlr4Lexer, -            NALAAnsiAntlr4::SQLv1Antlr4Parser>; - -        using G = std::conditional_t< +        using TLexer = std::conditional_t<              IsAnsiLexer, -            TAnsiYQLGrammar, -            TDefaultYQLGrammar>; +            NALAAnsiAntlr4::SQLv1Antlr4Lexer, +            NALADefaultAntlr4::SQLv1Antlr4Lexer>;          TSpecializedGlobalAnalysis()              : Chars_() @@ -128,11 +121,17 @@ namespace NSQLComplete {              TGlobalContext ctx; -            // TODO(YQL-19747): Add ~ParseContext(Tokens, ParseTree, CursorPosition) -            ctx.Use = FindUseStatement(sqlQuery, &Tokens_, input.CursorPosition, env); -            ctx.Names = CollectNamedNodes(sqlQuery, &Tokens_, input.CursorPosition); -            ctx.EnclosingFunction = EnclosingFunction(sqlQuery, &Tokens_, input.CursorPosition); -            ctx.Column = InferColumnContext(sqlQuery, &Tokens_, input.CursorPosition); +            TParsedInput parsed = { +                .Original = input, +                .Tokens = &Tokens_, +                .Parser = &Parser_, +                .SqlQuery = sqlQuery, +            }; + +            ctx.Use = FindUseStatement(parsed, env); +            ctx.Names = CollectNamedNodes(parsed); +            ctx.EnclosingFunction = EnclosingFunction(parsed); +            ctx.Column = InferColumnContext(parsed);              if (ctx.Use && ctx.Column) {                  EnrichTableClusters(*ctx.Column, *ctx.Use); @@ -176,9 +175,9 @@ namespace NSQLComplete {          }          antlr4::ANTLRInputStream Chars_; -        G::TLexer Lexer_; +        TLexer Lexer_;          antlr4::CommonTokenStream Tokens_; -        TDefaultYQLGrammar::TParser Parser_; +        SQLv1 Parser_;      };      class TGlobalAnalysis: public IGlobalAnalysis { diff --git a/yql/essentials/sql/v1/complete/analysis/global/input.cpp b/yql/essentials/sql/v1/complete/analysis/global/input.cpp new file mode 100644 index 00000000000..018d9c796f3 --- /dev/null +++ b/yql/essentials/sql/v1/complete/analysis/global/input.cpp @@ -0,0 +1 @@ +#include "input.h" diff --git a/yql/essentials/sql/v1/complete/analysis/global/input.h b/yql/essentials/sql/v1/complete/analysis/global/input.h new file mode 100644 index 00000000000..3f40ec1f31d --- /dev/null +++ b/yql/essentials/sql/v1/complete/analysis/global/input.h @@ -0,0 +1,16 @@ +#pragma once + +#include "parse_tree.h" + +#include <yql/essentials/sql/v1/complete/core/input.h> + +namespace NSQLComplete { + +    struct TParsedInput { +        TCompletionInput Original; +        antlr4::CommonTokenStream* Tokens; +        SQLv1* Parser; +        SQLv1::Sql_queryContext* SqlQuery; +    }; + +} // namespace NSQLComplete 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 0896b508432..57223e73405 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/named_node.cpp @@ -14,11 +14,8 @@ namespace NSQLComplete {          class TVisitor: public TSQLv1NarrowingVisitor {          public: -            TVisitor( -                antlr4::TokenStream* tokens, -                size_t cursorPosition, -                THashSet<TString>* names) -                : TSQLv1NarrowingVisitor(tokens, cursorPosition) +            TVisitor(const TParsedInput& input, THashSet<TString>* names) +                : TSQLv1NarrowingVisitor(input)                  , Names_(names)              {              } @@ -110,12 +107,9 @@ namespace NSQLComplete {      } // namespace -    TVector<TString> CollectNamedNodes( -        SQLv1::Sql_queryContext* ctx, -        antlr4::TokenStream* tokens, -        size_t cursorPosition) { +    TVector<TString> CollectNamedNodes(TParsedInput input) {          THashSet<TString> names; -        TVisitor(tokens, cursorPosition, &names).visit(ctx); +        TVisitor(input, &names).visit(input.SqlQuery);          return TVector<TString>(begin(names), end(names));      } diff --git a/yql/essentials/sql/v1/complete/analysis/global/named_node.h b/yql/essentials/sql/v1/complete/analysis/global/named_node.h index 119fbc4d5f6..55466765013 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/named_node.h +++ b/yql/essentials/sql/v1/complete/analysis/global/named_node.h @@ -1,15 +1,12 @@  #pragma once -#include "parse_tree.h" +#include "input.h"  #include <util/generic/string.h>  #include <util/generic/vector.h>  namespace NSQLComplete { -    TVector<TString> CollectNamedNodes( -        SQLv1::Sql_queryContext* ctx, -        antlr4::TokenStream* tokens, -        size_t cursorPosition); +    TVector<TString> CollectNamedNodes(TParsedInput input);  } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp index f1cd303062c..95f5e1c13bd 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.cpp @@ -2,9 +2,9 @@  namespace NSQLComplete { -    TSQLv1NarrowingVisitor::TSQLv1NarrowingVisitor(antlr4::TokenStream* tokens, size_t cursorPosition) -        : Tokens_(tokens) -        , CursorPosition_(cursorPosition) +    TSQLv1NarrowingVisitor::TSQLv1NarrowingVisitor(const TParsedInput& input) +        : Tokens_(input.Tokens) +        , CursorPosition_(input.Original.CursorPosition)      {      } diff --git a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h index 1ad4bbe2274..759ad5bd37c 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h +++ b/yql/essentials/sql/v1/complete/analysis/global/narrowing_visitor.h @@ -1,13 +1,13 @@  #pragma once  #include "base_visitor.h" -#include "parse_tree.h" +#include "input.h"  namespace NSQLComplete {      class TSQLv1NarrowingVisitor: public TSQLv1BaseVisitor {      public: -        TSQLv1NarrowingVisitor(antlr4::TokenStream* tokens, size_t cursorPosition); +        TSQLv1NarrowingVisitor(const TParsedInput& input);      protected:          bool shouldVisitNextChild(antlr4::tree::ParseTree* node, const std::any& /*currentResult*/) override; diff --git a/yql/essentials/sql/v1/complete/analysis/global/use.cpp b/yql/essentials/sql/v1/complete/analysis/global/use.cpp index d9a430ec12b..ce592b724c3 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/use.cpp +++ b/yql/essentials/sql/v1/complete/analysis/global/use.cpp @@ -9,11 +9,8 @@ namespace NSQLComplete {          class TVisitor: public TSQLv1NarrowingVisitor {          public: -            TVisitor( -                antlr4::TokenStream* tokens, -                size_t cursorPosition, -                const TEnvironment* env) -                : TSQLv1NarrowingVisitor(tokens, cursorPosition) +            TVisitor(const TParsedInput& input, const TEnvironment* env) +                : TSQLv1NarrowingVisitor(input)                  , Env_(env)              {              } @@ -78,12 +75,9 @@ namespace NSQLComplete {      } // namespace -    TMaybe<TUseContext> FindUseStatement( -        SQLv1::Sql_queryContext* ctx, -        antlr4::TokenStream* tokens, -        size_t cursorPosition, -        const TEnvironment& env) { -        std::any result = TVisitor(tokens, cursorPosition, &env).visit(ctx); +    // TODO(YQL-19747): Use any to maybe conversion function +    TMaybe<TUseContext> FindUseStatement(TParsedInput input, const TEnvironment& env) { +        std::any result = TVisitor(input, &env).visit(input.SqlQuery);          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 0cdb9b15469..964519e4e99 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/use.h +++ b/yql/essentials/sql/v1/complete/analysis/global/use.h @@ -1,7 +1,7 @@  #pragma once  #include "global.h" -#include "parse_tree.h" +#include "input.h"  #include <util/generic/ptr.h>  #include <util/generic/maybe.h> @@ -9,10 +9,6 @@  namespace NSQLComplete { -    TMaybe<TUseContext> FindUseStatement( -        SQLv1::Sql_queryContext* ctx, -        antlr4::TokenStream* tokens, -        size_t cursorPosition, -        const TEnvironment& env); +    TMaybe<TUseContext> FindUseStatement(TParsedInput input, 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 b67f290a3be..25c83108230 100644 --- a/yql/essentials/sql/v1/complete/analysis/global/ya.make +++ b/yql/essentials/sql/v1/complete/analysis/global/ya.make @@ -6,6 +6,7 @@ SRCS(      evaluate.cpp      function.cpp      global.cpp +    input.cpp      named_node.cpp      narrowing_visitor.cpp      parse_tree.cpp diff --git a/yql/essentials/sql/v1/complete/configuration.cpp b/yql/essentials/sql/v1/complete/configuration.cpp new file mode 100644 index 00000000000..9dbba885b2c --- /dev/null +++ b/yql/essentials/sql/v1/complete/configuration.cpp @@ -0,0 +1,62 @@ +#include "configuration.h" + +#include <yql/essentials/sql/v1/complete/syntax/grammar.h> + +namespace NSQLComplete { + +    TConfiguration MakeConfiguration(THashSet<TString> allowedStmts) { +        allowedStmts.emplace("sql_stmt"); + +        TConfiguration config; +        for (const std::string& name : GetSqlGrammar().GetAllRules()) { +            if (name.ends_with("_stmt") && !allowedStmts.contains(name)) { +                config.IgnoredRules_.emplace(name); +            } +        } +        return config; +    } + +    TConfiguration MakeYDBConfiguration() { +        TConfiguration config; +        config.IgnoredRules_ = { +            "use_stmt", +            "import_stmt", +            "export_stmt", +        }; +        return config; +    } + +    TConfiguration MakeYQLConfiguration() { +        auto config = MakeConfiguration(/* allowedStmts = */ { +            "lambda_stmt", +            "pragma_stmt", +            "select_stmt", +            "named_nodes_stmt", +            "drop_table_stmt", +            "use_stmt", +            "into_table_stmt", +            "commit_stmt", +            "declare_stmt", +            "import_stmt", +            "export_stmt", +            "do_stmt", +            "define_action_or_subquery_stmt", +            "if_stmt", +            "for_stmt", +            "values_stmt", +        }); + +        config.DisabledPreviousByToken_ = {}; + +        config.ForcedPreviousByToken_ = { +            {"PARALLEL", {}}, +            {"TABLESTORE", {}}, +            {"FOR", {"EVALUATE"}}, +            {"IF", {"EVALUATE"}}, +            {"EXTERNAL", {"USING"}}, +        }; + +        return config; +    } + +} // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/configuration.h b/yql/essentials/sql/v1/complete/configuration.h new file mode 100644 index 00000000000..620207bfcf2 --- /dev/null +++ b/yql/essentials/sql/v1/complete/configuration.h @@ -0,0 +1,28 @@ +#pragma once + +#include <util/generic/string.h> +#include <util/generic/hash.h> +#include <util/generic/hash_set.h> + +namespace NSQLComplete { + +    struct TConfiguration { +        friend class TSqlCompletionEngine; +        friend TConfiguration MakeYDBConfiguration(); +        friend TConfiguration MakeYQLConfiguration(); +        friend TConfiguration MakeConfiguration(THashSet<TString> allowedStmts); + +    public: +        size_t Limit = 256; + +    private: +        THashSet<TString> IgnoredRules_; +        THashMap<TString, THashSet<TString>> DisabledPreviousByToken_; +        THashMap<TString, THashSet<TString>> ForcedPreviousByToken_; +    }; + +    TConfiguration MakeYDBConfiguration(); + +    TConfiguration MakeYQLConfiguration(); + +} // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/service/name_service.h b/yql/essentials/sql/v1/complete/name/service/name_service.h index e4971b86250..a5d793835ee 100644 --- a/yql/essentials/sql/v1/complete/name/service/name_service.h +++ b/yql/essentials/sql/v1/complete/name/service/name_service.h @@ -78,7 +78,7 @@ namespace NSQLComplete {      struct TBindingName: TIndentifier {      }; -    struct TUnkownName { +    struct TUnknownName {          TString Content;          TString Type;      }; @@ -94,7 +94,7 @@ namespace NSQLComplete {          TClusterName,          TColumnName,          TBindingName, -        TUnkownName>; +        TUnknownName>;      struct TNameConstraints {          TMaybe<TPragmaName::TConstraints> Pragma; diff --git a/yql/essentials/sql/v1/complete/name/service/ranking/ranking.cpp b/yql/essentials/sql/v1/complete/name/service/ranking/ranking.cpp index d8e0e0ff1bb..09edce52123 100644 --- a/yql/essentials/sql/v1/complete/name/service/ranking/ranking.cpp +++ b/yql/essentials/sql/v1/complete/name/service/ranking/ranking.cpp @@ -118,7 +118,7 @@ namespace NSQLComplete {                  if constexpr (std::is_base_of_v<TIndentifier, T>) {                      return name.Indentifier;                  } -                if constexpr (std::is_base_of_v<TUnkownName, T>) { +                if constexpr (std::is_base_of_v<TUnknownName, T>) {                      return name.Content;                  }              }, name); diff --git a/yql/essentials/sql/v1/complete/name/service/schema/name_service.cpp b/yql/essentials/sql/v1/complete/name/service/schema/name_service.cpp index 736f7c3090e..3b13ec93784 100644 --- a/yql/essentials/sql/v1/complete/name/service/schema/name_service.cpp +++ b/yql/essentials/sql/v1/complete/name/service/schema/name_service.cpp @@ -130,7 +130,7 @@ namespace NSQLComplete {                      local.Indentifier = std::move(entry.Name);                      name = std::move(local);                  } else { -                    TUnkownName local; +                    TUnknownName local;                      local.Content = std::move(entry.Name);                      local.Type = std::move(entry.Type);                      name = std::move(local); diff --git a/yql/essentials/sql/v1/complete/name_mapping.cpp b/yql/essentials/sql/v1/complete/name_mapping.cpp new file mode 100644 index 00000000000..541188ea8c8 --- /dev/null +++ b/yql/essentials/sql/v1/complete/name_mapping.cpp @@ -0,0 +1,147 @@ +#include "name_mapping.h" + +#include <yql/essentials/sql/v1/complete/syntax/format.h> + +namespace NSQLComplete { + +    TCandidate ToCandidate(TKeyword name, TLocalSyntaxContext& context) { +        TVector<TString>& seq = context.Keywords[name.Content]; +        seq.insert(std::begin(seq), name.Content); + +        TCandidate candidate = { +            .Kind = ECandidateKind::Keyword, +            .Content = FormatKeywords(seq), +        }; + +        if (candidate.Content.EndsWith('(')) { +            candidate.Content += ')'; +            candidate.CursorShift = 1; +        } + +        return candidate; +    } + +    TCandidate ToCandidate(TPragmaName name) { +        return {ECandidateKind::PragmaName, std::move(name.Indentifier)}; +    } + +    TCandidate ToCandidate(TTypeName name) { +        TCandidate candidate = { +            .Kind = ECandidateKind::TypeName, +            .Content = std::move(name.Indentifier), +        }; + +        switch (name.Kind) { +            case TTypeName::EKind::Simple: { +            } break; +            case TTypeName::EKind::Container: { +                candidate.Content += "<>"; +                candidate.CursorShift = 1; +            } break; +            case TTypeName::EKind::Parameterized: { +                candidate.Content += "()"; +                candidate.CursorShift = 1; +            } break; +        } + +        return candidate; +    } + +    TCandidate ToCandidate(TFunctionName name) { +        TCandidate candidate = { +            .Kind = ECandidateKind::FunctionName, +            .Content = std::move(name.Indentifier), +        }; + +        candidate.Content += "()"; +        candidate.CursorShift = 1; + +        return candidate; +    } + +    TCandidate ToCandidate(THintName name) { +        return {ECandidateKind::HintName, std::move(name.Indentifier)}; +    } + +    TCandidate ToCandidate(TFolderName name, TLocalSyntaxContext& context) { +        TCandidate candidate = { +            .Kind = ECandidateKind::FolderName, +            .Content = std::move(name.Indentifier), +        }; + +        if (!context.IsQuoted.AtLhs) { +            candidate.Content.prepend('`'); +        } + +        candidate.Content.append('/'); + +        if (!context.IsQuoted.AtRhs) { +            candidate.Content.append('`'); +            candidate.CursorShift = 1; +        } + +        return candidate; +    } + +    TCandidate ToCandidate(TTableName name, TLocalSyntaxContext& context) { +        if (!context.IsQuoted.AtLhs) { +            name.Indentifier.prepend('`'); +        } +        if (!context.IsQuoted.AtRhs) { +            name.Indentifier.append('`'); +        } +        return {ECandidateKind::TableName, std::move(name.Indentifier)}; +    } + +    TCandidate ToCandidate(TClusterName name) { +        return {ECandidateKind::ClusterName, std::move(name.Indentifier)}; +    } + +    TCandidate ToCandidate(TColumnName name, TLocalSyntaxContext& context) { +        if (context.Column->Table.empty() && !name.TableAlias.empty()) { +            name.Indentifier.prepend('.'); +            name.Indentifier.prepend(name.TableAlias); +        } + +        return {ECandidateKind::ColumnName, std::move(name.Indentifier)}; +    } + +    TCandidate ToCandidate(TBindingName name, TLocalSyntaxContext& context) { +        if (!context.Binding) { +            name.Indentifier.prepend('$'); +        } +        return {ECandidateKind::BindingName, std::move(name.Indentifier)}; +    } + +    TCandidate ToCandidate(TUnknownName name) { +        return {ECandidateKind::UnknownName, std::move(name.Content)}; +    } + +    TCandidate ToCandidate(TGenericName generic, TLocalSyntaxContext& context) { +        return std::visit([&](auto&& name) -> TCandidate { +            using T = std::decay_t<decltype(name)>; +            constexpr bool IsContextSensitive = +                std::is_same_v<T, TKeyword> || +                std::is_same_v<T, TFolderName> || +                std::is_same_v<T, TTableName> || +                std::is_same_v<T, TColumnName> || +                std::is_same_v<T, TBindingName>; + +            if constexpr (IsContextSensitive) { +                return ToCandidate(std::move(name), context); +            } else { +                return ToCandidate(std::move(name)); +            } +        }, std::move(generic)); +    } + +    TVector<TCandidate> ToCandidate(TVector<TGenericName> names, TLocalSyntaxContext context) { +        TVector<TCandidate> candidates; +        candidates.reserve(names.size()); +        for (auto& name : names) { +            candidates.emplace_back(ToCandidate(std::move(name), context)); +        } +        return candidates; +    } + +} // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name_mapping.h b/yql/essentials/sql/v1/complete/name_mapping.h new file mode 100644 index 00000000000..0bde9ffd6dc --- /dev/null +++ b/yql/essentials/sql/v1/complete/name_mapping.h @@ -0,0 +1,14 @@ +#pragma once + +#include "sql_complete.h" + +#include <yql/essentials/sql/v1/complete/analysis/local/local.h> +#include <yql/essentials/sql/v1/complete/name/service/name_service.h> + +namespace NSQLComplete { + +    TCandidate ToCandidate(TGenericName name, TLocalSyntaxContext& context); + +    TVector<TCandidate> ToCandidate(TVector<TGenericName> names, TLocalSyntaxContext context); + +} // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/sql_complete.cpp b/yql/essentials/sql/v1/complete/sql_complete.cpp index 59cbeba1385..307bc432518 100644 --- a/yql/essentials/sql/v1/complete/sql_complete.cpp +++ b/yql/essentials/sql/v1/complete/sql_complete.cpp @@ -1,5 +1,7 @@  #include "sql_complete.h" +#include "name_mapping.h" +  #include <yql/essentials/sql/v1/complete/syntax/grammar.h>  #include <yql/essentials/sql/v1/complete/text/word.h>  #include <yql/essentials/sql/v1/complete/name/object/simple/static/schema.h> @@ -23,7 +25,7 @@ namespace NSQLComplete {          TSqlCompletionEngine(              TLexerSupplier lexer,              INameService::TPtr names, -            ISqlCompletionEngine::TConfiguration configuration) +            TConfiguration configuration)              : Configuration_(std::move(configuration))              , SyntaxAnalysis_(MakeLocalSyntaxAnalysis(                    lexer, @@ -41,10 +43,9 @@ namespace NSQLComplete {          }          NThreading::TFuture<TCompletion> CompleteAsync(TCompletionInput input, TEnvironment env) override { -            if ( -                input.CursorPosition < input.Text.length() && -                    IsUTF8ContinuationByte(input.Text.at(input.CursorPosition)) || -                input.Text.length() < input.CursorPosition) { +            if ((input.CursorPosition < input.Text.length() && +                 IsUTF8ContinuationByte(input.Text.at(input.CursorPosition))) || +                (input.Text.length() < input.CursorPosition)) {                  ythrow yexception()                      << "invalid cursor position " << input.CursorPosition                      << " for input size " << input.Text.size(); @@ -167,13 +168,10 @@ namespace NSQLComplete {              return request;          } -        TCompletion ToCompletion( -            TCompletionInput input, -            TLocalSyntaxContext context, -            TNameResponse response) const { +        TCompletion ToCompletion(TCompletionInput input, TLocalSyntaxContext context, TNameResponse response) const {              TCompletion completion = {                  .CompletedToken = GetCompletedToken(input, context.EditRange), -                .Candidates = Convert(std::move(response.RankedNames), std::move(context)), +                .Candidates = ToCandidate(std::move(response.RankedNames), std::move(context)),              };              if (response.NameHintLength) { @@ -188,200 +186,16 @@ namespace NSQLComplete {              return completion;          } -        static TVector<TCandidate> Convert(TVector<TGenericName> names, TLocalSyntaxContext context) { -            TVector<TCandidate> candidates; -            candidates.reserve(names.size()); -            for (auto& name : names) { -                candidates.emplace_back(Convert(std::move(name), context)); -            } -            return candidates; -        } - -        // TODO(YQL-19747): extract to a separate file -        static TCandidate Convert(TGenericName name, TLocalSyntaxContext& context) { -            return std::visit([&](auto&& name) -> TCandidate { -                using T = std::decay_t<decltype(name)>; - -                if constexpr (std::is_base_of_v<TKeyword, T>) { -                    TVector<TString>& seq = context.Keywords[name.Content]; -                    seq.insert(std::begin(seq), name.Content); - -                    TCandidate candidate = { -                        .Kind = ECandidateKind::Keyword, -                        .Content = FormatKeywords(seq), -                    }; - -                    if (candidate.Content.EndsWith('(')) { -                        candidate.Content += ')'; -                        candidate.CursorShift = 1; -                    } - -                    return candidate; -                } - -                if constexpr (std::is_base_of_v<TPragmaName, T>) { -                    return {ECandidateKind::PragmaName, std::move(name.Indentifier)}; -                } - -                if constexpr (std::is_base_of_v<TTypeName, T>) { -                    TCandidate candidate = { -                        .Kind = ECandidateKind::TypeName, -                        .Content = std::move(name.Indentifier), -                    }; - -                    switch (name.Kind) { -                        case TTypeName::EKind::Simple: { -                        } break; -                        case TTypeName::EKind::Container: { -                            candidate.Content += "<>"; -                            candidate.CursorShift = 1; -                        } break; -                        case TTypeName::EKind::Parameterized: { -                            candidate.Content += "()"; -                            candidate.CursorShift = 1; -                        } break; -                    } - -                    return candidate; -                } - -                if constexpr (std::is_base_of_v<TFunctionName, T>) { -                    TCandidate candidate = { -                        .Kind = ECandidateKind::FunctionName, -                        .Content = std::move(name.Indentifier), -                    }; - -                    candidate.Content += "()"; -                    candidate.CursorShift = 1; - -                    return candidate; -                } - -                if constexpr (std::is_base_of_v<THintName, T>) { -                    return {ECandidateKind::HintName, std::move(name.Indentifier)}; -                } - -                if constexpr (std::is_base_of_v<TFolderName, T>) { -                    TCandidate candidate = { -                        .Kind = ECandidateKind::FolderName, -                        .Content = std::move(name.Indentifier), -                    }; - -                    if (!context.IsQuoted.AtLhs) { -                        candidate.Content.prepend('`'); -                    } - -                    candidate.Content.append('/'); - -                    if (!context.IsQuoted.AtRhs) { -                        candidate.Content.append('`'); -                        candidate.CursorShift = 1; -                    } - -                    return candidate; -                } - -                if constexpr (std::is_base_of_v<TTableName, T>) { -                    if (!context.IsQuoted.AtLhs) { -                        name.Indentifier.prepend('`'); -                    } -                    if (!context.IsQuoted.AtRhs) { -                        name.Indentifier.append('`'); -                    } -                    return {ECandidateKind::TableName, std::move(name.Indentifier)}; -                } - -                if constexpr (std::is_base_of_v<TClusterName, T>) { -                    return {ECandidateKind::ClusterName, std::move(name.Indentifier)}; -                } - -                if constexpr (std::is_base_of_v<TColumnName, T>) { -                    if (context.Column->Table.empty() && !name.TableAlias.empty()) { -                        name.Indentifier.prepend('.'); -                        name.Indentifier.prepend(name.TableAlias); -                    } - -                    return {ECandidateKind::ColumnName, std::move(name.Indentifier)}; -                } - -                if constexpr (std::is_base_of_v<TBindingName, T>) { -                    if (!context.Binding) { -                        name.Indentifier.prepend('$'); -                    } -                    return {ECandidateKind::BindingName, std::move(name.Indentifier)}; -                } - -                if constexpr (std::is_base_of_v<TUnkownName, T>) { -                    return {ECandidateKind::UnknownName, std::move(name.Content)}; -                } -            }, std::move(name)); -        } -          TConfiguration Configuration_;          ILocalSyntaxAnalysis::TPtr SyntaxAnalysis_;          IGlobalAnalysis::TPtr GlobalAnalysis_;          INameService::TPtr Names_;      }; -    ISqlCompletionEngine::TConfiguration MakeConfiguration(THashSet<TString> allowedStmts) { -        allowedStmts.emplace("sql_stmt"); - -        ISqlCompletionEngine::TConfiguration config; -        for (const std::string& name : GetSqlGrammar().GetAllRules()) { -            if (name.ends_with("_stmt") && !allowedStmts.contains(name)) { -                config.IgnoredRules_.emplace(name); -            } -        } -        return config; -    } - -    ISqlCompletionEngine::TConfiguration MakeYDBConfiguration() { -        ISqlCompletionEngine::TConfiguration config; -        config.IgnoredRules_ = { -            "use_stmt", -            "import_stmt", -            "export_stmt", -        }; -        return config; -    } - -    ISqlCompletionEngine::TConfiguration MakeYQLConfiguration() { -        auto config = MakeConfiguration(/* allowedStmts = */ { -            "lambda_stmt", -            "pragma_stmt", -            "select_stmt", -            "named_nodes_stmt", -            "drop_table_stmt", -            "use_stmt", -            "into_table_stmt", -            "commit_stmt", -            "declare_stmt", -            "import_stmt", -            "export_stmt", -            "do_stmt", -            "define_action_or_subquery_stmt", -            "if_stmt", -            "for_stmt", -            "values_stmt", -        }); - -        config.DisabledPreviousByToken_ = {}; - -        config.ForcedPreviousByToken_ = { -            {"PARALLEL", {}}, -            {"TABLESTORE", {}}, -            {"FOR", {"EVALUATE"}}, -            {"IF", {"EVALUATE"}}, -            {"EXTERNAL", {"USING"}}, -        }; - -        return config; -    } -      ISqlCompletionEngine::TPtr MakeSqlCompletionEngine(          TLexerSupplier lexer,          INameService::TPtr names, -        ISqlCompletionEngine::TConfiguration configuration) { +        TConfiguration configuration) {          return MakeHolder<TSqlCompletionEngine>(              lexer, std::move(names), std::move(configuration));      } diff --git a/yql/essentials/sql/v1/complete/sql_complete.h b/yql/essentials/sql/v1/complete/sql_complete.h index ce8a7c5296f..3387019e25f 100644 --- a/yql/essentials/sql/v1/complete/sql_complete.h +++ b/yql/essentials/sql/v1/complete/sql_complete.h @@ -1,5 +1,7 @@  #pragma once +#include "configuration.h" +  #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> @@ -51,20 +53,8 @@ namespace NSQLComplete {      public:          using TPtr = THolder<ISqlCompletionEngine>; -        struct TConfiguration { -            friend class TSqlCompletionEngine; -            friend ISqlCompletionEngine::TConfiguration MakeYDBConfiguration(); -            friend ISqlCompletionEngine::TConfiguration MakeYQLConfiguration(); -            friend ISqlCompletionEngine::TConfiguration MakeConfiguration(THashSet<TString> allowedStmts); - -        public: -            size_t Limit = 256; - -        private: -            THashSet<TString> IgnoredRules_; -            THashMap<TString, THashSet<TString>> DisabledPreviousByToken_; -            THashMap<TString, THashSet<TString>> ForcedPreviousByToken_; -        }; +        // TODO(YQL-19747): Deprecated, Migrate YDB CLI to `TConfiguration` +        using TConfiguration = NSQLComplete::TConfiguration;          virtual ~ISqlCompletionEngine() = default; @@ -77,13 +67,9 @@ namespace NSQLComplete {      using TLexerSupplier = std::function<NSQLTranslation::ILexer::TPtr(bool ansi)>; -    ISqlCompletionEngine::TConfiguration MakeYDBConfiguration(); - -    ISqlCompletionEngine::TConfiguration MakeYQLConfiguration(); -      ISqlCompletionEngine::TPtr MakeSqlCompletionEngine(          TLexerSupplier lexer,          INameService::TPtr names, -        ISqlCompletionEngine::TConfiguration configuration = {}); +        TConfiguration configuration = {});  } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/ya.make b/yql/essentials/sql/v1/complete/ya.make index e85ba90b524..b0b5ee4be21 100644 --- a/yql/essentials/sql/v1/complete/ya.make +++ b/yql/essentials/sql/v1/complete/ya.make @@ -1,6 +1,8 @@  LIBRARY()  SRCS( +    configuration.cpp +    name_mapping.cpp      sql_complete.cpp  )  | 
