Skip to content

Commit 60665d3

Browse files
committed
Intermediate changes
commit_hash:a1ac242ea5619c1e83dd638a82653e1d5c385821
1 parent 9b729cf commit 60665d3

File tree

9 files changed

+293
-0
lines changed

9 files changed

+293
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "schema_gateway.h"
2+
3+
template <>
4+
void Out<NSQLComplete::TFolderEntry>(IOutputStream& out, const NSQLComplete::TFolderEntry& entry) {
5+
out << "{" << entry.Type << ", " << entry.Name << "}";
6+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#pragma once
2+
3+
#include <library/cpp/threading/future/core/future.h>
4+
5+
#include <util/generic/string.h>
6+
#include <util/generic/vector.h>
7+
#include <util/generic/hash_set.h>
8+
#include <util/generic/maybe.h>
9+
10+
namespace NSQLComplete {
11+
12+
struct TFolderEntry {
13+
TString Type;
14+
TString Name;
15+
16+
friend bool operator==(const TFolderEntry& lhs, const TFolderEntry& rhs) = default;
17+
};
18+
19+
struct TListFilter {
20+
TMaybe<THashSet<TString>> Types;
21+
};
22+
23+
struct TListRequest {
24+
TString Cluster;
25+
26+
// `Path` structure is defined by a `System`.
27+
// Can end with a folder entry name hint.
28+
// For example, `/local/exa` lists a folder `/local`,
29+
// but can rank and filter entries by a hint `exa`.
30+
TString Path;
31+
32+
TListFilter Filter;
33+
size_t Limit = 128;
34+
};
35+
36+
struct TListResponse {
37+
size_t NameHintLength = 0;
38+
TVector<TFolderEntry> Entries;
39+
};
40+
41+
class ISchemaGateway {
42+
public:
43+
using TPtr = THolder<ISchemaGateway>;
44+
45+
virtual ~ISchemaGateway() = default;
46+
virtual NThreading::TFuture<TListResponse> List(const TListRequest& request) = 0;
47+
};
48+
49+
} // namespace NSQLComplete
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include "schema_gateway.h"
2+
3+
#include <yql/essentials/sql/v1/complete/text/case.h>
4+
5+
#include <util/charset/utf8.h>
6+
7+
namespace NSQLComplete {
8+
9+
namespace {
10+
11+
class TSchemaGateway: public ISchemaGateway {
12+
static constexpr size_t MaxLimit = 4 * 1024;
13+
14+
public:
15+
explicit TSchemaGateway(THashMap<TString, TVector<TFolderEntry>> data)
16+
: Data_(std::move(data))
17+
{
18+
for (const auto& [k, _] : Data_) {
19+
Y_ENSURE(k.StartsWith("/"), k << " must start with the '/'");
20+
Y_ENSURE(k.EndsWith("/"), k << " must end with the '/'");
21+
}
22+
}
23+
24+
NThreading::TFuture<TListResponse> List(const TListRequest& request) override {
25+
auto [path, prefix] = ParsePath(request.Path);
26+
27+
TVector<TFolderEntry> entries = Data_[path];
28+
EraseIf(entries, [prefix = ToLowerUTF8(prefix)](const TFolderEntry& entry) {
29+
return !entry.Name.StartsWith(prefix);
30+
});
31+
32+
EraseIf(entries, [types = std::move(request.Filter.Types)](const TFolderEntry& entry) {
33+
return types && !types->contains(entry.Type);
34+
});
35+
36+
Y_ENSURE(request.Limit <= MaxLimit);
37+
entries.crop(request.Limit);
38+
39+
TListResponse response = {
40+
.NameHintLength = prefix.size(),
41+
.Entries = std::move(entries),
42+
};
43+
44+
return NThreading::MakeFuture(std::move(response));
45+
}
46+
47+
private:
48+
static std::tuple<TStringBuf, TStringBuf> ParsePath(TString path Y_LIFETIME_BOUND) {
49+
size_t pos = path.find_last_of('/');
50+
if (pos == TString::npos) {
51+
return {"", path};
52+
}
53+
54+
TStringBuf head, tail;
55+
TStringBuf(path).SplitAt(pos + 1, head, tail);
56+
return {head, tail};
57+
}
58+
59+
THashMap<TString, TVector<TFolderEntry>> Data_;
60+
};
61+
62+
} // namespace
63+
64+
ISchemaGateway::TPtr MakeStaticSchemaGateway(THashMap<TString, TVector<TFolderEntry>> fs) {
65+
return MakeHolder<TSchemaGateway>(std::move(fs));
66+
}
67+
68+
} // namespace NSQLComplete
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
#include <yql/essentials/sql/v1/complete/name/object/schema_gateway.h>
4+
5+
namespace NSQLComplete {
6+
7+
ISchemaGateway::TPtr MakeStaticSchemaGateway(THashMap<TString, TVector<TFolderEntry>> fs);
8+
9+
} // namespace NSQLComplete
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#include "schema_gateway.h"
2+
3+
#include <library/cpp/testing/unittest/registar.h>
4+
5+
using namespace NSQLComplete;
6+
7+
Y_UNIT_TEST_SUITE(StaticSchemaGatewayTests) {
8+
9+
ISchemaGateway::TPtr MakeStaticSchemaGatewayUT() {
10+
THashMap<TString, TVector<TFolderEntry>> fs = {
11+
{"/", {{"Folder", "local"},
12+
{"Folder", "test"},
13+
{"Folder", "prod"}}},
14+
{"/local/", {{"Table", "example"},
15+
{"Table", "account"},
16+
{"Table", "abacaba"}}},
17+
{"/test/", {{"Folder", "service"},
18+
{"Table", "meta"}}},
19+
{"/test/service/", {{"Table", "example"}}},
20+
};
21+
return MakeStaticSchemaGateway(std::move(fs));
22+
}
23+
24+
Y_UNIT_TEST(ListFolderBasic) {
25+
auto gateway = MakeStaticSchemaGatewayUT();
26+
{
27+
TVector<TFolderEntry> expected = {
28+
{"Folder", "local"},
29+
{"Folder", "test"},
30+
{"Folder", "prod"},
31+
};
32+
UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/"}).GetValueSync().Entries, expected);
33+
}
34+
{
35+
TVector<TFolderEntry> expected = {
36+
{"Table", "example"},
37+
{"Table", "account"},
38+
{"Table", "abacaba"},
39+
};
40+
UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/local/"}).GetValueSync().Entries, expected);
41+
}
42+
{
43+
TVector<TFolderEntry> expected = {
44+
{"Folder", "service"},
45+
{"Table", "meta"},
46+
};
47+
UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/test/"}).GetValueSync().Entries, expected);
48+
}
49+
{
50+
TVector<TFolderEntry> expected = {
51+
{"Table", "example"}};
52+
UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/test/service/"}).GetValueSync().Entries, expected);
53+
}
54+
}
55+
56+
Y_UNIT_TEST(ListFolderHint) {
57+
auto gateway = MakeStaticSchemaGatewayUT();
58+
{
59+
TVector<TFolderEntry> expected = {
60+
{"Folder", "local"},
61+
};
62+
auto actual = gateway->List({.Path = "/l"}).GetValueSync();
63+
UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected);
64+
UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 1);
65+
}
66+
{
67+
TVector<TFolderEntry> expected = {
68+
{"Table", "account"},
69+
{"Table", "abacaba"},
70+
};
71+
auto actual = gateway->List({.Path = "/local/a"}).GetValueSync();
72+
UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected);
73+
UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 1);
74+
}
75+
{
76+
TVector<TFolderEntry> expected = {
77+
{"Folder", "service"},
78+
};
79+
auto actual = gateway->List({.Path = "/test/service"}).GetValueSync();
80+
UNIT_ASSERT_VALUES_EQUAL(actual.Entries, expected);
81+
UNIT_ASSERT_VALUES_EQUAL(actual.NameHintLength, 7);
82+
}
83+
}
84+
85+
Y_UNIT_TEST(ListFolderFilterByType) {
86+
auto gateway = MakeStaticSchemaGatewayUT();
87+
{
88+
TVector<TFolderEntry> expected = {
89+
{"Folder", "service"},
90+
};
91+
TListRequest request = {
92+
.Path = "/test/",
93+
.Filter = {
94+
.Types = THashSet<TString>{"Folder"},
95+
},
96+
};
97+
UNIT_ASSERT_VALUES_EQUAL(gateway->List(request).GetValueSync().Entries, expected);
98+
}
99+
{
100+
TVector<TFolderEntry> expected = {
101+
{"Table", "meta"},
102+
};
103+
TListRequest request = {
104+
.Path = "/test/",
105+
.Filter = {
106+
.Types = THashSet<TString>{"Table"},
107+
},
108+
};
109+
UNIT_ASSERT_VALUES_EQUAL(gateway->List(request).GetValueSync().Entries, expected);
110+
}
111+
}
112+
113+
Y_UNIT_TEST(ListFolderLimit) {
114+
auto gateway = MakeStaticSchemaGatewayUT();
115+
UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 0}).GetValueSync().Entries.size(), 0);
116+
UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 1}).GetValueSync().Entries.size(), 1);
117+
UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 2}).GetValueSync().Entries.size(), 2);
118+
UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 3}).GetValueSync().Entries.size(), 3);
119+
UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 4}).GetValueSync().Entries.size(), 3);
120+
UNIT_ASSERT_VALUES_EQUAL(gateway->List({.Path = "/", .Limit = 5}).GetValueSync().Entries.size(), 3);
121+
}
122+
123+
} // Y_UNIT_TEST_SUITE(StaticSchemaGatewayTests)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
UNITTEST_FOR(yql/essentials/sql/v1/complete/name/object/static)
2+
3+
SRCS(
4+
schema_gateway_ut.cpp
5+
)
6+
7+
END()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
LIBRARY()
2+
3+
SRCS(
4+
schema_gateway.cpp
5+
)
6+
7+
PEERDIR(
8+
yql/essentials/sql/v1/complete/name/object
9+
)
10+
11+
END()
12+
13+
RECURSE_FOR_TESTS(
14+
ut
15+
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
LIBRARY()
2+
3+
SRCS(
4+
schema_gateway.cpp
5+
)
6+
7+
PEERDIR(
8+
library/cpp/threading/future
9+
)
10+
11+
END()
12+
13+
RECURSE(
14+
static
15+
)

yql/essentials/sql/v1/complete/name/ya.make

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ END()
88

99
RECURSE(
1010
fallback
11+
object
1112
static
1213
)

0 commit comments

Comments
 (0)