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