diff options
| author | vityaman <[email protected]> | 2025-04-29 20:36:31 +0300 |
|---|---|---|
| committer | robot-piglet <[email protected]> | 2025-04-29 20:50:11 +0300 |
| commit | 0c2a81c9d391c539cfb25930a38fe153aa502255 (patch) | |
| tree | f8cc5f861c8b8433c30faf905c1af36ec09a01b2 /yql/essentials/sql | |
| parent | 13042213866893f652428dddafaf35d4e5398060 (diff) | |
YQL-19747 Introduce SimpleSchemaGateway
Introduce the `SimpleSchemaGateway` to make it easier to implement `SchemaGateway`s. The idea is that actually existing schema providers really do not support filtration such as by name and type, so in practice they return us the whole list and we need to filter it by hand. The `SimpleSchemaGateway` to `SchemaGateway` adapter does this for us -- we only need to implement a path splitting and folder listing.
The other and important feature of the `SimpleSchemaGateway` is that it is simple to implement a caching decorator for it -- just store a mapping `Path -> [FolderEntry]`, while caching a `SchemaGateway` with filters is soooo not trivial.
I also added string constants for known folder entry types, because they should be documented somewhere.
---
- Related to `YQL-19747`
- Related to https://github.com/vityaman/ydb/issues/14
- Related to https://github.com/vityaman/ydb/issues/34
---
Pull Request resolved: https://github.com/ytsaurus/ytsaurus/pull/1245
commit_hash:dda6dcac544ca95d5e8e08f1e7de9de6b5770f25
Diffstat (limited to 'yql/essentials/sql')
9 files changed, 133 insertions, 36 deletions
diff --git a/yql/essentials/sql/v1/complete/name/object/schema_gateway.h b/yql/essentials/sql/v1/complete/name/object/schema_gateway.h index 37fff8571e0..f9307bf495d 100644 --- a/yql/essentials/sql/v1/complete/name/object/schema_gateway.h +++ b/yql/essentials/sql/v1/complete/name/object/schema_gateway.h @@ -10,6 +10,9 @@ namespace NSQLComplete { struct TFolderEntry { + static constexpr const char* Folder = "Folder"; + static constexpr const char* Table = "Table"; + TString Type; TString Name; diff --git a/yql/essentials/sql/v1/complete/name/object/simple/schema_gateway.cpp b/yql/essentials/sql/v1/complete/name/object/simple/schema_gateway.cpp new file mode 100644 index 00000000000..e8e7bf3ccd9 --- /dev/null +++ b/yql/essentials/sql/v1/complete/name/object/simple/schema_gateway.cpp @@ -0,0 +1,74 @@ +#include "schema_gateway.h" + +#include <util/charset/utf8.h> + +namespace NSQLComplete { + + namespace { + + class TSimpleSchemaGateway: public ISchemaGateway { + private: + static auto FilterByName(TString name) { + return [name = std::move(name)](auto f) { + TVector<TFolderEntry> entries = f.ExtractValue(); + EraseIf(entries, [prefix = ToLowerUTF8(name)](const TFolderEntry& entry) { + return !entry.Name.StartsWith(prefix); + }); + return entries; + }; + } + + static auto FilterByTypes(TMaybe<THashSet<TString>> types) { + return [types = std::move(types)](auto f) { + TVector<TFolderEntry> entries = f.ExtractValue(); + EraseIf(entries, [types = std::move(types)](const TFolderEntry& entry) { + return types && !types->contains(entry.Type); + }); + return entries; + }; + } + + static auto Crop(size_t limit) { + return [limit](auto f) { + TVector<TFolderEntry> entries = f.ExtractValue(); + entries.crop(limit); + return entries; + }; + } + + static auto ToResponse(TStringBuf name) { + const auto length = name.length(); + return [length](auto f) { + return TListResponse{ + .NameHintLength = length, + .Entries = f.ExtractValue(), + }; + }; + } + + public: + explicit TSimpleSchemaGateway(ISimpleSchemaGateway::TPtr simple) + : Simple_(std::move(simple)) + { + } + + NThreading::TFuture<TListResponse> List(const TListRequest& request) const override { + auto [path, name] = Simple_->Split(request.Path); + return Simple_->List(TString(path)) + .Apply(FilterByName(TString(name))) + .Apply(FilterByTypes(std::move(request.Filter.Types))) + .Apply(Crop(request.Limit)) + .Apply(ToResponse(name)); + } + + private: + ISimpleSchemaGateway::TPtr Simple_; + }; + + } // namespace + + ISchemaGateway::TPtr MakeSimpleSchemaGateway(ISimpleSchemaGateway::TPtr simple) { + return ISchemaGateway::TPtr(new TSimpleSchemaGateway(std::move(simple))); + } + +} // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/schema_gateway.h b/yql/essentials/sql/v1/complete/name/object/simple/schema_gateway.h new file mode 100644 index 00000000000..4b4671f1cca --- /dev/null +++ b/yql/essentials/sql/v1/complete/name/object/simple/schema_gateway.h @@ -0,0 +1,23 @@ +#pragma once + +#include <yql/essentials/sql/v1/complete/name/object/schema_gateway.h> + +namespace NSQLComplete { + + struct TSplittedPath { + TStringBuf Path; + TStringBuf NameHint; + }; + + class ISimpleSchemaGateway: public TThrRefBase { + public: + using TPtr = TIntrusivePtr<ISimpleSchemaGateway>; + + virtual ~ISimpleSchemaGateway() = default; + virtual TSplittedPath Split(TStringBuf path) const = 0; + virtual NThreading::TFuture<TVector<TFolderEntry>> List(TString folder) const = 0; + }; + + ISchemaGateway::TPtr MakeSimpleSchemaGateway(ISimpleSchemaGateway::TPtr simple); + +} // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/simple/ya.make b/yql/essentials/sql/v1/complete/name/object/simple/ya.make new file mode 100644 index 00000000000..d3668fdb1fc --- /dev/null +++ b/yql/essentials/sql/v1/complete/name/object/simple/ya.make @@ -0,0 +1,11 @@ +LIBRARY() + +SRCS( + schema_gateway.cpp +) + +PEERDIR( + yql/essentials/sql/v1/complete/name/object +) + +END() diff --git a/yql/essentials/sql/v1/complete/name/object/static/schema_gateway.cpp b/yql/essentials/sql/v1/complete/name/object/static/schema_gateway.cpp index e325b908f7a..f43af57c752 100644 --- a/yql/essentials/sql/v1/complete/name/object/static/schema_gateway.cpp +++ b/yql/essentials/sql/v1/complete/name/object/static/schema_gateway.cpp @@ -1,6 +1,6 @@ #include "schema_gateway.h" -#include <yql/essentials/sql/v1/complete/text/case.h> +#include <yql/essentials/sql/v1/complete/name/object/simple/schema_gateway.h> #include <util/charset/utf8.h> @@ -8,11 +8,9 @@ namespace NSQLComplete { namespace { - class TSchemaGateway: public ISchemaGateway { - static constexpr size_t MaxLimit = 4 * 1024; - + class TSimpleSchemaGateway: public ISimpleSchemaGateway { public: - explicit TSchemaGateway(THashMap<TString, TVector<TFolderEntry>> data) + explicit TSimpleSchemaGateway(THashMap<TString, TVector<TFolderEntry>> data) : Data_(std::move(data)) { for (const auto& [k, _] : Data_) { @@ -21,35 +19,7 @@ namespace NSQLComplete { } } - NThreading::TFuture<TListResponse> List(const TListRequest& request) const override { - auto [path, prefix] = ParsePath(request.Path); - - TVector<TFolderEntry> entries; - if (const auto* data = Data_.FindPtr(path)) { - entries = *data; - } - - EraseIf(entries, [prefix = ToLowerUTF8(prefix)](const TFolderEntry& entry) { - return !entry.Name.StartsWith(prefix); - }); - - EraseIf(entries, [types = std::move(request.Filter.Types)](const TFolderEntry& entry) { - return types && !types->contains(entry.Type); - }); - - Y_ENSURE(request.Limit <= MaxLimit); - entries.crop(request.Limit); - - TListResponse response = { - .NameHintLength = prefix.size(), - .Entries = std::move(entries), - }; - - return NThreading::MakeFuture(std::move(response)); - } - - private: - static std::tuple<TStringBuf, TStringBuf> ParsePath(TString path Y_LIFETIME_BOUND) { + TSplittedPath Split(TStringBuf path) const override { size_t pos = path.find_last_of('/'); if (pos == TString::npos) { return {"", path}; @@ -60,13 +30,24 @@ namespace NSQLComplete { return {head, tail}; } + NThreading::TFuture<TVector<TFolderEntry>> List(TString folder) const override { + TVector<TFolderEntry> entries; + if (const auto* data = Data_.FindPtr(folder)) { + entries = *data; + } + return NThreading::MakeFuture(std::move(entries)); + } + + private: THashMap<TString, TVector<TFolderEntry>> Data_; }; } // namespace ISchemaGateway::TPtr MakeStaticSchemaGateway(THashMap<TString, TVector<TFolderEntry>> fs) { - return MakeIntrusive<TSchemaGateway>(std::move(fs)); + return MakeSimpleSchemaGateway( + ISimpleSchemaGateway::TPtr( + new TSimpleSchemaGateway(std::move(fs)))); } } // namespace NSQLComplete diff --git a/yql/essentials/sql/v1/complete/name/object/static/ya.make b/yql/essentials/sql/v1/complete/name/object/static/ya.make index d3dd658468c..d37495f0700 100644 --- a/yql/essentials/sql/v1/complete/name/object/static/ya.make +++ b/yql/essentials/sql/v1/complete/name/object/static/ya.make @@ -6,6 +6,7 @@ SRCS( PEERDIR( yql/essentials/sql/v1/complete/name/object + yql/essentials/sql/v1/complete/name/object/simple ) END() diff --git a/yql/essentials/sql/v1/complete/name/object/ya.make b/yql/essentials/sql/v1/complete/name/object/ya.make index 1254e60dc6c..483f11c9a59 100644 --- a/yql/essentials/sql/v1/complete/name/object/ya.make +++ b/yql/essentials/sql/v1/complete/name/object/ya.make @@ -11,5 +11,6 @@ PEERDIR( END() RECURSE( + simple static ) diff --git a/yql/essentials/sql/v1/complete/ut/ya.make b/yql/essentials/sql/v1/complete/ut/ya.make index 4c50124cf7c..fbb84f56f25 100644 --- a/yql/essentials/sql/v1/complete/ut/ya.make +++ b/yql/essentials/sql/v1/complete/ut/ya.make @@ -7,6 +7,7 @@ SRCS( PEERDIR( yql/essentials/sql/v1/lexer/antlr4_pure yql/essentials/sql/v1/lexer/antlr4_pure_ansi + yql/essentials/sql/v1/complete/name/service/static ) END() diff --git a/yql/essentials/sql/v1/complete/ya.make b/yql/essentials/sql/v1/complete/ya.make index 4e2d02b7a97..010c8ac5243 100644 --- a/yql/essentials/sql/v1/complete/ya.make +++ b/yql/essentials/sql/v1/complete/ya.make @@ -8,9 +8,11 @@ PEERDIR( yql/essentials/sql/v1/lexer yql/essentials/sql/v1/complete/antlr4 yql/essentials/sql/v1/complete/name/service - yql/essentials/sql/v1/complete/name/service/static yql/essentials/sql/v1/complete/syntax yql/essentials/sql/v1/complete/text + + # TODO(YQL-19747): add it to YDB CLI PEERDIR + yql/essentials/sql/v1/complete/name/service/static ) END() |
