summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2025-04-22 19:01:12 +0300
committerrobot-piglet <[email protected]>2025-04-22 19:45:00 +0300
commit60665d3830d1f5e3252c2b7f5bb4db32cadadfc1 (patch)
tree0f03b5608e43c58113eccfaf7bd2299448609224
parent9b729cf67c26251cd90ddaf5d921a6b0feb562e5 (diff)
Intermediate changes
commit_hash:a1ac242ea5619c1e83dd638a82653e1d5c385821
-rw-r--r--yql/essentials/sql/v1/complete/name/object/schema_gateway.cpp6
-rw-r--r--yql/essentials/sql/v1/complete/name/object/schema_gateway.h49
-rw-r--r--yql/essentials/sql/v1/complete/name/object/static/schema_gateway.cpp68
-rw-r--r--yql/essentials/sql/v1/complete/name/object/static/schema_gateway.h9
-rw-r--r--yql/essentials/sql/v1/complete/name/object/static/schema_gateway_ut.cpp123
-rw-r--r--yql/essentials/sql/v1/complete/name/object/static/ut/ya.make7
-rw-r--r--yql/essentials/sql/v1/complete/name/object/static/ya.make15
-rw-r--r--yql/essentials/sql/v1/complete/name/object/ya.make15
-rw-r--r--yql/essentials/sql/v1/complete/name/ya.make1
9 files changed, 293 insertions, 0 deletions
diff --git a/yql/essentials/sql/v1/complete/name/object/schema_gateway.cpp b/yql/essentials/sql/v1/complete/name/object/schema_gateway.cpp
new file mode 100644
index 00000000000..c802ddcb7a1
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/name/object/schema_gateway.cpp
@@ -0,0 +1,6 @@
+#include "schema_gateway.h"
+
+template <>
+void Out<NSQLComplete::TFolderEntry>(IOutputStream& out, const NSQLComplete::TFolderEntry& entry) {
+ out << "{" << entry.Type << ", " << entry.Name << "}";
+}
diff --git a/yql/essentials/sql/v1/complete/name/object/schema_gateway.h b/yql/essentials/sql/v1/complete/name/object/schema_gateway.h
new file mode 100644
index 00000000000..c09883d8bb7
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/name/object/schema_gateway.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <library/cpp/threading/future/core/future.h>
+
+#include <util/generic/string.h>
+#include <util/generic/vector.h>
+#include <util/generic/hash_set.h>
+#include <util/generic/maybe.h>
+
+namespace NSQLComplete {
+
+ struct TFolderEntry {
+ TString Type;
+ TString Name;
+
+ friend bool operator==(const TFolderEntry& lhs, const TFolderEntry& rhs) = default;
+ };
+
+ struct TListFilter {
+ TMaybe<THashSet<TString>> Types;
+ };
+
+ struct TListRequest {
+ TString Cluster;
+
+ // `Path` structure is defined by a `System`.
+ // Can end with a folder entry name hint.
+ // For example, `/local/exa` lists a folder `/local`,
+ // but can rank and filter entries by a hint `exa`.
+ TString Path;
+
+ TListFilter Filter;
+ size_t Limit = 128;
+ };
+
+ struct TListResponse {
+ size_t NameHintLength = 0;
+ TVector<TFolderEntry> Entries;
+ };
+
+ class ISchemaGateway {
+ public:
+ using TPtr = THolder<ISchemaGateway>;
+
+ virtual ~ISchemaGateway() = default;
+ virtual NThreading::TFuture<TListResponse> List(const TListRequest& request) = 0;
+ };
+
+} // namespace NSQLComplete
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
new file mode 100644
index 00000000000..974c1ee5922
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/name/object/static/schema_gateway.cpp
@@ -0,0 +1,68 @@
+#include "schema_gateway.h"
+
+#include <yql/essentials/sql/v1/complete/text/case.h>
+
+#include <util/charset/utf8.h>
+
+namespace NSQLComplete {
+
+ namespace {
+
+ class TSchemaGateway: public ISchemaGateway {
+ static constexpr size_t MaxLimit = 4 * 1024;
+
+ public:
+ explicit TSchemaGateway(THashMap<TString, TVector<TFolderEntry>> data)
+ : Data_(std::move(data))
+ {
+ for (const auto& [k, _] : Data_) {
+ Y_ENSURE(k.StartsWith("/"), k << " must start with the '/'");
+ Y_ENSURE(k.EndsWith("/"), k << " must end with the '/'");
+ }
+ }
+
+ NThreading::TFuture<TListResponse> List(const TListRequest& request) override {
+ auto [path, prefix] = ParsePath(request.Path);
+
+ TVector<TFolderEntry> entries = Data_[path];
+ 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) {
+ size_t pos = path.find_last_of('/');
+ if (pos == TString::npos) {
+ return {"", path};
+ }
+
+ TStringBuf head, tail;
+ TStringBuf(path).SplitAt(pos + 1, head, tail);
+ return {head, tail};
+ }
+
+ THashMap<TString, TVector<TFolderEntry>> Data_;
+ };
+
+ } // namespace
+
+ ISchemaGateway::TPtr MakeStaticSchemaGateway(THashMap<TString, TVector<TFolderEntry>> fs) {
+ return MakeHolder<TSchemaGateway>(std::move(fs));
+ }
+
+} // namespace NSQLComplete
diff --git a/yql/essentials/sql/v1/complete/name/object/static/schema_gateway.h b/yql/essentials/sql/v1/complete/name/object/static/schema_gateway.h
new file mode 100644
index 00000000000..fd23a956d25
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/name/object/static/schema_gateway.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <yql/essentials/sql/v1/complete/name/object/schema_gateway.h>
+
+namespace NSQLComplete {
+
+ ISchemaGateway::TPtr MakeStaticSchemaGateway(THashMap<TString, TVector<TFolderEntry>> fs);
+
+} // namespace NSQLComplete
diff --git a/yql/essentials/sql/v1/complete/name/object/static/schema_gateway_ut.cpp b/yql/essentials/sql/v1/complete/name/object/static/schema_gateway_ut.cpp
new file mode 100644
index 00000000000..86c8118f197
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/name/object/static/schema_gateway_ut.cpp
@@ -0,0 +1,123 @@
+#include "schema_gateway.h"
+
+#include <library/cpp/testing/unittest/registar.h>
+
+using namespace NSQLComplete;
+
+Y_UNIT_TEST_SUITE(StaticSchemaGatewayTests) {
+
+ ISchemaGateway::TPtr MakeStaticSchemaGatewayUT() {
+ THashMap<TString, TVector<TFolderEntry>> fs = {
+ {"/", {{"Folder", "local"},
+ {"Folder", "test"},
+ {"Folder", "prod"}}},
+ {"/local/", {{"Table", "example"},
+ {"Table", "account"},
+ {"Table", "abacaba"}}},
+ {"/test/", {{"Folder", "service"},
+ {"Table", "meta"}}},
+ {"/test/service/", {{"Table", "example"}}},
+ };
+ return MakeStaticSchemaGateway(std::move(fs));
+ }
+
+ Y_UNIT_TEST(ListFolderBasic) {
+ auto gateway = MakeStaticSchemaGatewayUT();
+ {
+ TVector<TFolderEntry> expected = {
+ {"Folder", "local"},
+ {"Folder", "test"},
+ {"Folder", "prod"},
+ };
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/"}).GetValueSync().Entries, expected);
+ }
+ {
+ TVector<TFolderEntry> expected = {
+ {"Table", "example"},
+ {"Table", "account"},
+ {"Table", "abacaba"},
+ };
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/local/"}).GetValueSync().Entries, expected);
+ }
+ {
+ TVector<TFolderEntry> expected = {
+ {"Folder", "service"},
+ {"Table", "meta"},
+ };
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/test/"}).GetValueSync().Entries, expected);
+ }
+ {
+ TVector<TFolderEntry> expected = {
+ {"Table", "example"}};
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/test/service/"}).GetValueSync().Entries, expected);
+ }
+ }
+
+ Y_UNIT_TEST(ListFolderHint) {
+ auto gateway = MakeStaticSchemaGatewayUT();
+ {
+ TVector<TFolderEntry> expected = {
+ {"Folder", "local"},
+ };
+ auto actual = gateway->List({.Path = "/l"}).GetValueSync();
+ UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected);
+ UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 1);
+ }
+ {
+ TVector<TFolderEntry> expected = {
+ {"Table", "account"},
+ {"Table", "abacaba"},
+ };
+ auto actual = gateway->List({.Path = "/local/a"}).GetValueSync();
+ UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected);
+ UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 1);
+ }
+ {
+ TVector<TFolderEntry> expected = {
+ {"Folder", "service"},
+ };
+ auto actual = gateway->List({.Path = "/test/service"}).GetValueSync();
+ UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected);
+ UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 7);
+ }
+ }
+
+ Y_UNIT_TEST(ListFolderFilterByType) {
+ auto gateway = MakeStaticSchemaGatewayUT();
+ {
+ TVector<TFolderEntry> expected = {
+ {"Folder", "service"},
+ };
+ TListRequest request = {
+ .Path = "/test/",
+ .Filter = {
+ .Types = THashSet<TString>{"Folder"},
+ },
+ };
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List(request).GetValueSync().Entries, expected);
+ }
+ {
+ TVector<TFolderEntry> expected = {
+ {"Table", "meta"},
+ };
+ TListRequest request = {
+ .Path = "/test/",
+ .Filter = {
+ .Types = THashSet<TString>{"Table"},
+ },
+ };
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List(request).GetValueSync().Entries, expected);
+ }
+ }
+
+ Y_UNIT_TEST(ListFolderLimit) {
+ auto gateway = MakeStaticSchemaGatewayUT();
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 0}).GetValueSync().Entries.size(), 0);
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 1}).GetValueSync().Entries.size(), 1);
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 2}).GetValueSync().Entries.size(), 2);
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 3}).GetValueSync().Entries.size(), 3);
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 4}).GetValueSync().Entries.size(), 3);
+ UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 5}).GetValueSync().Entries.size(), 3);
+ }
+
+} // Y_UNIT_TEST_SUITE(StaticSchemaGatewayTests)
diff --git a/yql/essentials/sql/v1/complete/name/object/static/ut/ya.make b/yql/essentials/sql/v1/complete/name/object/static/ut/ya.make
new file mode 100644
index 00000000000..877f015d806
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/name/object/static/ut/ya.make
@@ -0,0 +1,7 @@
+UNITTEST_FOR(yql/essentials/sql/v1/complete/name/object/static)
+
+SRCS(
+ schema_gateway_ut.cpp
+)
+
+END()
diff --git a/yql/essentials/sql/v1/complete/name/object/static/ya.make b/yql/essentials/sql/v1/complete/name/object/static/ya.make
new file mode 100644
index 00000000000..d3dd658468c
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/name/object/static/ya.make
@@ -0,0 +1,15 @@
+LIBRARY()
+
+SRCS(
+ schema_gateway.cpp
+)
+
+PEERDIR(
+ yql/essentials/sql/v1/complete/name/object
+)
+
+END()
+
+RECURSE_FOR_TESTS(
+ ut
+)
diff --git a/yql/essentials/sql/v1/complete/name/object/ya.make b/yql/essentials/sql/v1/complete/name/object/ya.make
new file mode 100644
index 00000000000..1254e60dc6c
--- /dev/null
+++ b/yql/essentials/sql/v1/complete/name/object/ya.make
@@ -0,0 +1,15 @@
+LIBRARY()
+
+SRCS(
+ schema_gateway.cpp
+)
+
+PEERDIR(
+ library/cpp/threading/future
+)
+
+END()
+
+RECURSE(
+ static
+)
diff --git a/yql/essentials/sql/v1/complete/name/ya.make b/yql/essentials/sql/v1/complete/name/ya.make
index 43f7dc2c1b3..9b64891e4d6 100644
--- a/yql/essentials/sql/v1/complete/name/ya.make
+++ b/yql/essentials/sql/v1/complete/name/ya.make
@@ -8,5 +8,6 @@ END()
RECURSE(
fallback
+ object
static
)