22
22
23
23
#include < silkworm/db/access_layer.hpp>
24
24
#include < silkworm/db/chain/local_chain_storage.hpp>
25
+ #include < silkworm/db/datastore/common/ranges/vector_from_range.hpp>
25
26
#include < silkworm/db/datastore/domain_get_as_of_query.hpp>
26
27
#include < silkworm/db/datastore/domain_get_latest_query.hpp>
27
28
#include < silkworm/db/datastore/domain_range_as_of_query.hpp>
@@ -39,7 +40,7 @@ namespace silkworm::db::kv::api {
39
40
40
41
using namespace silkworm ::datastore;
41
42
42
- static const std::map<std::string_view, datastore:: EntityName> kTable2EntityNames {
43
+ static const std::map<std::string_view, EntityName> kTable2EntityNames {
43
44
{table::kAccountDomain , state::kDomainNameAccounts },
44
45
{table::kStorageDomain , state::kDomainNameStorage },
45
46
{table::kCodeDomain , state::kDomainNameCode },
@@ -86,7 +87,7 @@ using ReceiptsHistoryGetQuery = RawHistoryGetQuery<state::kHistorySegmentAndIdxN
86
87
using RawInvertedIndexRangeByKeyQuery = InvertedIndexRangeByKeyQuery<
87
88
kvdb::RawEncoder<Bytes>, snapshots::RawEncoder<Bytes>>; // TODO(canepat) try ByteView
88
89
89
- using RawHistoryRangeInPeriodQuery = datastore:: HistoryRangeInPeriodQuery<
90
+ using RawHistoryRangeInPeriodQuery = HistoryRangeInPeriodQuery<
90
91
kvdb::RawDecoder<Bytes>, snapshots::RawDecoder<Bytes>, kvdb::RawDecoder<Bytes>, snapshots::RawDecoder<Bytes>>;
91
92
92
93
template <typename PageResult>
@@ -156,7 +157,7 @@ Task<GetLatestResult> LocalTransaction::get_latest(GetLatestQuery query) {
156
157
co_return GetAsOfResult{};
157
158
}
158
159
159
- const auto domain_name = kTable2EntityNames .at (query.table );
160
+ const EntityName domain_name = kTable2EntityNames .at (query.table );
160
161
RawDomainGetLatestQuery store_query (
161
162
domain_name,
162
163
data_store_.chaindata .domain (domain_name),
@@ -176,7 +177,7 @@ Task<GetAsOfResult> LocalTransaction::get_as_of(GetAsOfQuery query) {
176
177
co_return GetAsOfResult{};
177
178
}
178
179
179
- const auto domain_name = kTable2EntityNames .at (query.table );
180
+ const EntityName domain_name = kTable2EntityNames .at (query.table );
180
181
std::optional<Bytes> value;
181
182
if (domain_name == state::kDomainNameAccounts ) {
182
183
value = query_domain_as_of<AccountsDomainGetAsOfQuery>(domain_name, query.key , query.timestamp );
@@ -200,8 +201,8 @@ Task<HistoryPointResult> LocalTransaction::history_seek(HistoryPointQuery query)
200
201
co_return HistoryPointResult{};
201
202
}
202
203
203
- const auto domain_name = kTable2EntityNames .at (query.table );
204
- const auto domain = data_store_.chaindata .domain (domain_name);
204
+ const EntityName domain_name = kTable2EntityNames .at (query.table );
205
+ const kvdb::Domain domain = data_store_.chaindata .domain (domain_name);
205
206
if (!domain.history ) {
206
207
co_return HistoryPointResult{};
207
208
}
@@ -232,26 +233,31 @@ Task<PaginatedTimestamps> LocalTransaction::index_range(IndexRangeQuery query) {
232
233
}
233
234
234
235
auto paginator = [this , query = std::move (query)](api::PaginatedTimestamps::PageToken) mutable -> Task<api::PaginatedTimestamps::PageResult> {
235
- datastore::TimestampRange ts_range = as_datastore_ts_range ({query.from_timestamp , query.to_timestamp }, !query.ascending_order );
236
- const auto inverted_index_name = kTable2EntityNames .at (query.table );
236
+ const EntityName inverted_index_name = kTable2EntityNames .at (query.table );
237
237
RawInvertedIndexRangeByKeyQuery store_query{
238
238
inverted_index_name,
239
239
data_store_.chaindata ,
240
240
tx_,
241
241
data_store_.state_repository_historical ,
242
242
};
243
+
244
+ datastore::TimestampRange ts_range = as_datastore_ts_range ({query.from_timestamp , query.to_timestamp }, !query.ascending_order );
243
245
const size_t limit = (query.limit == kUnlimited ) ? std::numeric_limits<size_t >::max () : static_cast <size_t >(query.limit );
246
+
244
247
api::PaginatedTimestamps::PageResult result;
245
248
// TODO: support pagination: apply page_size using std::views::chunk, save the range for future requests using page_token and return the first chunk
246
249
if (query.ascending_order ) {
247
- auto timestamp_view = store_query.exec <true >(query.key , std::move (ts_range)) | std::views::take (limit);
248
- // TODO: avoid range copy using std::views::as_rvalue (C++23)
249
- std::ranges::copy (timestamp_view /* | std::views::as_rvalue*/ , std::back_inserter (result.values ));
250
+ auto timestamps = store_query.exec <true >(query.key , std::move (ts_range)) |
251
+ std::views::transform ([](datastore::Timestamp ts) { return static_cast <Timestamp>(ts); }) |
252
+ std::views::take (limit);
253
+ result.values = vector_from_range (std::move (timestamps));
250
254
} else {
251
- auto timestamp_view = store_query.exec <false >(query.key , std::move (ts_range)) | std::views::take (limit);
252
- // TODO: avoid range copy using std::views::as_rvalue (C++23)
253
- std::ranges::copy (timestamp_view /* | std::views::as_rvalue*/ , std::back_inserter (result.values ));
255
+ auto timestamps = store_query.exec <false >(query.key , std::move (ts_range)) |
256
+ std::views::transform ([](datastore::Timestamp ts) { return static_cast <Timestamp>(ts); }) |
257
+ std::views::take (limit);
258
+ result.values = vector_from_range (std::move (timestamps));
254
259
}
260
+
255
261
co_return result;
256
262
};
257
263
co_return api::PaginatedTimestamps{std::move (paginator)};
@@ -263,63 +269,63 @@ Task<PaginatedKeysValues> LocalTransaction::history_range(HistoryRangeQuery quer
263
269
}
264
270
265
271
auto paginator = [this , query = std::move (query)](api::PaginatedKeysValues::PageToken) mutable -> Task<api::PaginatedKeysValues::PageResult> {
266
- datastore::TimestampRange ts_range = as_datastore_ts_range ({query.from_timestamp , query.to_timestamp }, !query.ascending_order );
267
- const auto entity_name = kTable2EntityNames .at (query.table );
272
+ const EntityName entity_name = kTable2EntityNames .at (query.table );
268
273
RawHistoryRangeInPeriodQuery store_query{
269
274
entity_name,
270
275
data_store_.chaindata ,
271
276
tx_,
272
277
data_store_.state_repository_historical ,
273
278
};
279
+
280
+ datastore::TimestampRange ts_range = as_datastore_ts_range ({query.from_timestamp , query.to_timestamp }, !query.ascending_order );
274
281
const size_t limit = (query.limit == kUnlimited ) ? std::numeric_limits<size_t >::max () : static_cast <size_t >(query.limit );
275
- std::vector<RawHistoryRangeInPeriodQuery::ResultItem> kv_pair_sequence;
282
+
276
283
// TODO: support pagination: apply page_size using std::views::chunk, save the range for future requests using page_token and return the first chunk
277
- auto kv_view = store_query.exec (ts_range, query.ascending_order ) | std::views::take (limit);
278
- // TODO: avoid range copy using std::views::as_rvalue (C++23)
279
- std::ranges::copy (kv_view /* | std::views::as_rvalue*/ , std::back_inserter (kv_pair_sequence));
280
284
api::PaginatedKeysValues::PageResult result;
281
- if (!kv_pair_sequence.empty ()) {
282
- result.keys .reserve (kv_pair_sequence.size ());
283
- result.values .reserve (kv_pair_sequence.size ());
284
- for (auto && kv_pair : kv_pair_sequence) {
285
- result.keys .emplace_back (std::move (kv_pair.first ));
286
- result.values .emplace_back (std::move (kv_pair.second ));
287
- }
285
+ for (auto && kv_pair : store_query.exec (ts_range, query.ascending_order ) | std::views::take (limit)) {
286
+ result.keys .emplace_back (std::move (kv_pair.first ));
287
+ result.values .emplace_back (std::move (kv_pair.second ));
288
288
}
289
+
289
290
co_return result;
290
291
};
291
292
co_return api::PaginatedKeysValues{std::move (paginator)};
292
293
}
293
294
294
295
Task<PaginatedKeysValues> LocalTransaction::range_as_of (DomainRangeQuery query) {
295
- // convert table to entity name
296
296
if (!kTable2EntityNames .contains (query.table )) {
297
- // TODO: return an empty result
297
+ co_return api::PaginatedKeysValues{make_empty_paginator<api::PaginatedKeysValues::PageResult>()};
298
298
}
299
- datastore::EntityName entity_name = kTable2EntityNames .at (query.table );
300
-
301
- using DomainRangeAsOfQuery = datastore::DomainRangeAsOfQuery<
302
- kvdb::RawEncoder<Bytes>, snapshots::RawEncoder<Bytes>,
303
- kvdb::RawDecoder<Bytes>, snapshots::RawDecoder<Bytes>,
304
- kvdb::RawDecoder<Bytes>, snapshots::RawDecoder<Bytes>>;
305
- DomainRangeAsOfQuery store_query{
306
- entity_name,
307
- data_store_.chaindata ,
308
- tx_,
309
- data_store_.state_repository_latest ,
310
- data_store_.state_repository_historical ,
311
- };
312
299
313
- size_t limit = (query.limit == kUnlimited ) ? std::numeric_limits<size_t >::max () : static_cast <size_t >(query.limit );
300
+ auto paginator = [this , query = std::move (query)](api::PaginatedKeysValues::PageToken) mutable -> Task<api::PaginatedKeysValues::PageResult> {
301
+ const EntityName entity_name = kTable2EntityNames .at (query.table );
302
+
303
+ using DomainRangeAsOfQuery = DomainRangeAsOfQuery<
304
+ kvdb::RawEncoder<Bytes>, snapshots::RawEncoder<Bytes>,
305
+ kvdb::RawDecoder<Bytes>, snapshots::RawDecoder<Bytes>,
306
+ kvdb::RawDecoder<Bytes>, snapshots::RawDecoder<Bytes>>;
307
+ DomainRangeAsOfQuery store_query{
308
+ entity_name,
309
+ data_store_.chaindata ,
310
+ tx_,
311
+ data_store_.state_repository_latest ,
312
+ data_store_.state_repository_historical ,
313
+ };
314
314
315
- // TODO: this is just a test example, instead of direct iteration, apply page_size using std::views::chunk,
316
- // TODO: save the range for future requests using page_token and return the first chunk
317
- for ([[maybe_unused]] decltype (store_query)::ResultItem& kv_pair : store_query.exec (query.from_key , query.to_key , query.timestamp , query.ascending_order ) | std::views::take (limit)) {
318
- }
315
+ std::optional<datastore::Timestamp> timestamp;
316
+ if (query.timestamp && (*query.timestamp >= 0 )) {
317
+ timestamp = static_cast <datastore::Timestamp>(*query.timestamp );
318
+ }
319
+ const size_t limit = (query.limit == kUnlimited ) ? std::numeric_limits<size_t >::max () : static_cast <size_t >(query.limit );
319
320
320
- // TODO(canepat) implement using E3-like aggregator abstraction [tx_id_ must be changed]
321
- auto paginator = [](api::PaginatedKeysValues::PageToken) mutable -> Task<api::PaginatedKeysValues::PageResult> {
322
- co_return api::PaginatedKeysValues::PageResult{};
321
+ // TODO: support pagination: apply page_size using std::views::chunk, save the range for future requests using page_token and return the first chunk
322
+ api::PaginatedKeysValues::PageResult result;
323
+ for (auto && kv_pair : store_query.exec (query.from_key , query.to_key , timestamp, query.ascending_order ) | std::views::take (limit)) {
324
+ result.keys .emplace_back (std::move (kv_pair.first ));
325
+ result.values .emplace_back (std::move (kv_pair.second ));
326
+ }
327
+
328
+ co_return result;
323
329
};
324
330
co_return api::PaginatedKeysValues{std::move (paginator)};
325
331
}
0 commit comments