userver: userver/ydb/table.hpp Source File
Loading...
Searching...
No Matches
table.hpp
1#pragma once
2
3#include <ydb-cpp-sdk/client/query/client.h>
4#include <ydb-cpp-sdk/client/query/query.h>
5#include <ydb-cpp-sdk/client/table/table.h>
6
7#include <userver/dynamic_config/source.hpp>
8#include <userver/utils/statistics/fwd.hpp>
9
10#include <userver/ydb/builder.hpp>
11#include <userver/ydb/query.hpp>
12#include <userver/ydb/response.hpp>
13#include <userver/ydb/settings.hpp>
14#include <userver/ydb/transaction.hpp>
15
16namespace NMonitoring {
17class TMetricRegistry;
18} // namespace NMonitoring
19
20USERVER_NAMESPACE_BEGIN
21
22namespace tracing {
23class Span;
24} // namespace tracing
25
26namespace utils {
27class RetryBudget;
28} // namespace utils
29
30namespace ydb {
31
32namespace impl {
33struct Stats;
34struct TableSettings;
35class Driver;
36struct RequestContext;
37enum class IsStreaming : bool {};
38} // namespace impl
39
40using DescribePathSettings = NYdb::NScheme::TDescribePathSettings;
41using ListDirectorySettings = NYdb::NScheme::TListDirectorySettings;
42using MakeDirectorySettings = NYdb::NScheme::TMakeDirectorySettings;
43using RemoveDirectorySettings = NYdb::NScheme::TRemoveDirectorySettings;
44
45using BulkUpsertSettings = NYdb::NTable::TBulkUpsertSettings;
46using CreateTableSettings = NYdb::NTable::TCreateTableSettings;
47using DescribeTableSettings = NYdb::NTable::TDescribeTableSettings;
48using DropTableSettings = NYdb::NTable::TDropTableSettings;
49using ScanQuerySettings = NYdb::NTable::TStreamExecScanQuerySettings;
50
51/// @brief A dynamic transaction name for @see TableClient::Begin.
52///
53/// @warning Make sure that transaction name has low cardinality.
54/// If transaction name is unique for every call, per-transaction metrics will overflow metrics quota,
55/// and metrics will become unusable.
56using DynamicTransactionName = utils::StrongTypedef<struct DynamicTransactionNameTag, std::string>;
57
58class TableClient final {
59public:
60 /// @cond
61 // For internal use only.
62 TableClient(
63 impl::TableSettings settings,
64 OperationSettings operation_settings,
65 dynamic_config::Source config_source,
66 std::shared_ptr<impl::Driver> driver
67 );
68
69 ~TableClient();
70 /// @endcond
71
72 /// Query for creating/deleting tables
73 void ExecuteSchemeQuery(const std::string& query);
74
75 void MakeDirectory(const std::string& path, MakeDirectorySettings query_settings = {});
76 void RemoveDirectory(const std::string& path, RemoveDirectorySettings query_settings = {});
77
78 NYdb::NScheme::TDescribePathResult DescribePath(std::string_view path, DescribePathSettings query_settings = {});
79 NYdb::NScheme::TListDirectoryResult ListDirectory(std::string_view path, ListDirectorySettings query_settings = {});
80
81 NYdb::NTable::TDescribeTableResult DescribeTable(std::string_view path, DescribeTableSettings query_settings = {});
82 void CreateTable(
83 std::string_view path,
84 NYdb::NTable::TTableDescription&& table_desc,
85 CreateTableSettings query_settings = {}
86 );
87 void DropTable(std::string_view path, DropTableSettings query_settings = {});
88
89 /// @name Data queries execution
90 /// Execute a single data query outside of transactions. Query parameters are
91 /// passed in `Args` as "string key - value" pairs:
92 ///
93 /// @code
94 /// client.ExecuteDataQuery(query, "name1", value1, "name2", value2, ...);
95 /// @endcode
96 ///
97 /// @warning ExecuteDataQuery returns no more than 1000 rows. Consider @ref ExecuteQuery() instead, but make sure
98 /// that it works for your case.
99 ///
100 /// Use ydb::PreparedArgsBuilder for storing a generic buffer of query params if needed.
101 ///
102 /// It is convenient to keep YQL queries in separate files, see @ref scripts/docs/en/userver/sql_files.md
103 /// for more info.
104 ///
105 /// @{
106 template <typename... Args>
107 ExecuteResponse ExecuteDataQuery(const Query& query, Args&&... args);
108
109 template <typename... Args>
110 ExecuteResponse ExecuteDataQuery(OperationSettings settings, const Query& query, Args&&... args);
111
112 ExecuteResponse ExecuteDataQuery(OperationSettings settings, const Query& query, PreparedArgsBuilder&& builder);
113
114 ExecuteResponse ExecuteDataQuery(
115 QuerySettings query_settings,
116 OperationSettings settings,
117 const Query& query,
118 PreparedArgsBuilder&& builder
119 );
120 /// @}
121
122 /// @name Transactions
123 /// @brief Begin a transaction with the specified name. The settings are used
124 /// for the `BEGIN` statement.
125 /// @see ydb::Transaction
126 ///
127 /// @{
128 Transaction Begin(utils::StringLiteral transaction_name, OperationSettings settings = {});
129
130 /// @warning Make sure that `transaction_name` has low cardinality.
131 /// If `transaction_name` is unique for every call, per-transaction metrics will overflow metrics quota,
132 /// and metrics will become unusable.
133 Transaction Begin(DynamicTransactionName transaction_name, OperationSettings settings = {});
134
135 Transaction Begin(utils::StringLiteral transaction_name, TransactionMode tx_mode);
136 /// @}
137
138 /// Builder for storing dynamic query params.
139 PreparedArgsBuilder GetBuilder() const;
140
141 /// Efficiently write large ranges of table data.
143 std::string_view table,
144 NYdb::TValue&& rows,
145 OperationSettings settings = {},
146 BulkUpsertSettings query_settings = {}
147 );
148
149 /// Efficiently write large ranges of table data.
150 /// The passed range of structs is serialized to TValue.
151 template <typename RangeOfStructs>
152 void BulkUpsert(std::string_view table, const RangeOfStructs& rows, OperationSettings settings = {});
153
154 /// Efficiently read large ranges of table data.
155 ReadTableResults ReadTable(
156 std::string_view table,
157 NYdb::NTable::TReadTableSettings&& read_settings = {},
158 OperationSettings settings = {}
159 );
160
161 /// @name Scan queries execution
162 /// A separate data access interface designed primarily for performing
163 /// analytical ad-hoc queries.
164 /// @{
165 template <typename... Args>
166 ScanQueryResults ExecuteScanQuery(const Query& query, Args&&... args);
167
168 template <typename... Args>
169 ScanQueryResults ExecuteScanQuery(
170 ScanQuerySettings&& scan_settings,
171 OperationSettings settings,
172 const Query& query,
173 Args&&... args
174 );
175
176 ScanQueryResults ExecuteScanQuery(
177 ScanQuerySettings&& scan_settings,
178 OperationSettings settings,
179 const Query& query,
180 PreparedArgsBuilder&& builder
181 );
182 /// @}
183
184 /// @name Queries execution (using YDB Query SDK)
185 /// Execute a single query outside of transactions. Query parameters are
186 /// passed in `Args` as "string key - value" pairs:
187 ///
188 /// @code
189 /// client.ExecuteQuery(query, "name1", value1, "name2", value2, ...);
190 /// @endcode
191 ///
192 /// Use ydb::PreparedArgsBuilder for storing a generic buffer of query params if needed.
193 ///
194 /// If both exec_settings and settings args are passed,
195 /// exec_settings.client_timeout_ms and exec_settings.trace_id are ignored
196 /// and are overwritten by settings.client_timeout_ms and settings.trace_id.
197 ///
198 /// It is convenient to keep YQL queries in separate files, see @ref scripts/docs/en/userver/sql_files.md
199 /// for more info.
200 /// @{
201 template <typename... Args>
202 ExecuteResponse ExecuteQuery(const Query& query, Args&&... args);
203
204 template <typename... Args>
205 ExecuteResponse ExecuteQuery(OperationSettings settings, const Query& query, Args&&... args);
206
207 ExecuteResponse ExecuteQuery(OperationSettings settings, const Query& query, PreparedArgsBuilder&& builder);
208
209 ExecuteResponse ExecuteQuery(
210 NYdb::NQuery::TExecuteQuerySettings&& exec_settings,
211 OperationSettings settings,
212 const Query& query,
213 PreparedArgsBuilder&& builder
214 );
215 /// @}
216
217 /// @cond
218 // For internal use only.
219 friend void DumpMetric(utils::statistics::Writer& writer, const TableClient& table_client);
220 /// @endcond
221
222 /// Get native table or query client
223 /// @warning Use with care! Facilities from
224 /// `<core/include/userver/drivers/subscribable_futures.hpp>` can help with
225 /// non-blocking wait operations.
226 /// @{
227 NYdb::NTable::TTableClient& GetNativeTableClient();
228
229 NYdb::NQuery::TQueryClient& GetNativeQueryClient();
230 /// @}
231
232 utils::RetryBudget& GetRetryBudget();
233
234private:
235 friend class Transaction;
236 friend struct impl::RequestContext;
237
238 std::string JoinDbPath(std::string_view path) const;
239
240 void Select1();
241
242 NYdb::NQuery::TExecuteQuerySettings ToExecuteQuerySettings(const QuerySettings& query_settings) const;
243 NYdb::NTable::TExecDataQuerySettings ToExecDataQuerySettings(const QuerySettings& query_settings) const;
244
245 template <typename... Args>
246 PreparedArgsBuilder MakeBuilder(Args&&... args);
247
248 // Func: (TSession, const std::string& full_path, const Settings&)
249 // -> NThreading::TFuture<T>
250 // OR
251 // (TTableClient&, const std::string& full_path, const Settings&)
252 // -> NThreading::TFuture<T>
253 // ExecuteSchemeQueryImpl -> T
254 template <typename QuerySettings, typename Func>
255 auto ExecuteWithPathImpl(
256 std::string_view path,
257 std::string_view operation_name,
258 OperationSettings settings,
259 QuerySettings&& query_settings,
260 Func&& func
261 );
262
263 dynamic_config::Source config_source_;
264 const OperationSettings default_settings_;
265 const bool keep_in_query_cache_;
266 const bool use_query_client_;
267 std::unique_ptr<impl::Stats> stats_;
268 std::shared_ptr<impl::Driver> driver_;
269 std::unique_ptr<NYdb::NScheme::TSchemeClient> scheme_client_;
270 std::unique_ptr<NYdb::NTable::TTableClient> table_client_;
271 std::unique_ptr<NYdb::NQuery::TQueryClient> query_client_;
272};
273
274template <typename... Args>
275PreparedArgsBuilder TableClient::MakeBuilder(Args&&... args) {
276 auto builder = GetBuilder();
277 builder.AddParams(std::forward<Args>(args)...);
278 return builder;
279}
280
281template <typename... Args>
282ExecuteResponse TableClient::ExecuteDataQuery(const Query& query, Args&&... args) {
283 return ExecuteDataQuery(OperationSettings{}, query, MakeBuilder(std::forward<Args>(args)...));
284}
285
286template <typename... Args>
287ExecuteResponse TableClient::ExecuteDataQuery(OperationSettings settings, const Query& query, Args&&... args) {
288 return ExecuteDataQuery(settings, query, MakeBuilder(std::forward<Args>(args)...));
289}
290
291template <typename RangeOfStructs>
292void TableClient::BulkUpsert(std::string_view table, const RangeOfStructs& rows, OperationSettings settings) {
293 NYdb::TValueBuilder builder;
294 ydb::Write(builder, rows);
295 BulkUpsert(table, builder.Build(), std::move(settings));
296}
297
298template <typename... Args>
299ScanQueryResults TableClient::ExecuteScanQuery(const Query& query, Args&&... args) {
300 return ExecuteScanQuery(ScanQuerySettings{}, OperationSettings{}, query, MakeBuilder(std::forward<Args>(args)...));
301}
302
303template <typename... Args>
304ScanQueryResults TableClient::ExecuteScanQuery(
305 ScanQuerySettings&& scan_settings,
306 OperationSettings settings,
307 const Query& query,
308 Args&&... args
309) {
310 return ExecuteScanQuery(
311 std::move(scan_settings),
312 std::move(settings),
313 query,
314 MakeBuilder(std::forward<Args>(args)...)
315 );
316}
317
318template <typename... Args>
319ExecuteResponse TableClient::ExecuteQuery(const Query& query, Args&&... args) {
320 return ExecuteQuery(OperationSettings{}, query, MakeBuilder(std::forward<Args>(args)...));
321}
322
323template <typename... Args>
324ExecuteResponse TableClient::ExecuteQuery(OperationSettings settings, const Query& query, Args&&... args) {
325 return ExecuteQuery(settings, query, MakeBuilder(std::forward<Args>(args)...));
326}
327
328} // namespace ydb
329
330USERVER_NAMESPACE_END