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