70 ExecutionStrategyType,
71 KeyspaceSchema<SettingsProviderType>,
72 FetchLedgerCacheType> {
75 ExecutionStrategyType,
77 FetchLedgerCacheType>;
79 using DefaultCassandraFamily::executor_;
80 using DefaultCassandraFamily::ledgerSequence_;
81 using DefaultCassandraFamily::log_;
82 using DefaultCassandraFamily::range_;
83 using DefaultCassandraFamily::schema_;
89 using DefaultCassandraFamily::DefaultCassandraFamily;
104 if (not range_.has_value()) {
105 executor_.writeSync(schema_->insertLedgerRange,
false, ledgerSequence_);
106 executor_.writeSync(schema_->insertLedgerRange,
true, ledgerSequence_);
109 if (not this->
executeSyncUpdate(schema_->updateLedgerRange.bind(ledgerSequence_,
true, ledgerSequence_ - 1))) {
110 log_.warn() <<
"Update failed for ledger " << ledgerSequence_;
114 log_.info() <<
"Committed ledger " << ledgerSequence_;
120 ripple::AccountID
const& issuer,
121 std::optional<std::uint32_t>
const& taxon,
122 std::uint32_t
const ledgerSequence,
123 std::uint32_t
const limit,
124 std::optional<ripple::uint256>
const& cursorIn,
125 boost::asio::yield_context yield
128 std::vector<ripple::uint256> nftIDs;
129 if (taxon.has_value()) {
131 nftIDs = fetchNFTIDsByTaxon(issuer, *taxon, limit, cursorIn, yield);
134 auto const startTaxon = cursorIn.has_value() ? ripple::nft::toUInt32(ripple::nft::getTaxon(*cursorIn)) : 0;
135 auto const startTokenID = cursorIn.value_or(ripple::uint256(0));
137 Statement
const firstQuery = schema_->selectNFTIDsByIssuerTaxon.bind(issuer);
138 firstQuery.
bindAt(1, startTaxon);
139 firstQuery.
bindAt(2, startTokenID);
142 auto const firstRes = executor_.read(yield, firstQuery);
143 if (firstRes.has_value()) {
145 nftIDs.push_back(nftID);
148 if (nftIDs.size() < limit) {
149 auto const remainingLimit = limit - nftIDs.size();
150 Statement
const secondQuery = schema_->selectNFTsAfterTaxonKeyspaces.bind(issuer);
151 secondQuery.
bindAt(1, startTaxon);
154 auto const secondRes = executor_.read(yield, secondQuery);
155 if (secondRes.has_value()) {
157 nftIDs.push_back(nftID);
161 return populateNFTsAndCreateCursor(nftIDs, ledgerSequence, limit, yield);
177 std::vector<ripple::uint256>
179 [[maybe_unused]] std::uint32_t number,
180 [[maybe_unused]] std::uint32_t pageSize,
181 [[maybe_unused]] std::uint32_t seq,
182 [[maybe_unused]] boost::asio::yield_context yield
185 ASSERT(
false,
"Fetching account roots is not supported by the Keyspaces backend.");
190 std::vector<ripple::uint256>
192 ripple::AccountID
const& issuer,
193 std::uint32_t
const taxon,
194 std::uint32_t
const limit,
195 std::optional<ripple::uint256>
const& cursorIn,
196 boost::asio::yield_context yield
199 std::vector<ripple::uint256> nftIDs;
200 Statement
const statement = schema_->selectNFTIDsByIssuerTaxon.bind(issuer);
201 statement.
bindAt(1, taxon);
202 statement.
bindAt(2, cursorIn.value_or(ripple::uint256(0)));
205 auto const res = executor_.read(yield, statement);
206 if (res.has_value() && res->hasRows()) {
208 nftIDs.push_back(nftID);
213 std::vector<ripple::uint256>
214 fetchNFTIDsWithoutTaxon(
215 ripple::AccountID
const& issuer,
216 std::uint32_t
const limit,
217 std::optional<ripple::uint256>
const& cursorIn,
218 boost::asio::yield_context yield
221 std::vector<ripple::uint256> nftIDs;
223 auto const startTaxon = cursorIn.has_value() ? ripple::nft::toUInt32(ripple::nft::getTaxon(*cursorIn)) : 0;
224 auto const startTokenID = cursorIn.value_or(ripple::uint256(0));
226 Statement firstQuery = schema_->selectNFTIDsByIssuerTaxon.
bind(issuer);
227 firstQuery.bindAt(1, startTaxon);
228 firstQuery.bindAt(2, startTokenID);
229 firstQuery.bindAt(3, Limit{limit});
231 auto const firstRes = executor_.read(yield, firstQuery);
232 if (firstRes.has_value()) {
234 nftIDs.push_back(nftID);
237 if (nftIDs.size() < limit) {
238 auto const remainingLimit = limit - nftIDs.size();
239 Statement secondQuery = schema_->selectNFTsAfterTaxonKeyspaces.
bind(issuer);
240 secondQuery.bindAt(1, startTaxon);
241 secondQuery.bindAt(2, Limit{remainingLimit});
243 auto const secondRes = executor_.read(yield, secondQuery);
244 if (secondRes.has_value()) {
246 nftIDs.push_back(nftID);
256 populateNFTsAndCreateCursor(
257 std::vector<ripple::uint256>
const& nftIDs,
258 std::uint32_t
const ledgerSequence,
259 std::uint32_t
const limit,
260 boost::asio::yield_context yield
263 if (nftIDs.empty()) {
264 LOG(log_.debug()) <<
"No rows returned";
269 if (nftIDs.size() == limit)
270 ret.cursor = nftIDs.back();
273 std::vector<Statement> selectNFTStatements;
274 selectNFTStatements.reserve(nftIDs.size());
276 std::cbegin(nftIDs), std::cend(nftIDs), std::back_inserter(selectNFTStatements), [&](
auto const& nftID) {
277 return schema_->selectNFT.bind(nftID, ledgerSequence);
281 std::vector<Statement> selectNFTURIStatements;
282 selectNFTURIStatements.reserve(nftIDs.size());
284 std::cbegin(nftIDs), std::cend(nftIDs), std::back_inserter(selectNFTURIStatements), [&](
auto const& nftID) {
285 return schema_->selectNFTURI.bind(nftID, ledgerSequence);
289 auto const nftInfos = executor_.readEach(yield, selectNFTStatements);
290 auto const nftUris = executor_.readEach(yield, selectNFTURIStatements);
293 for (
auto i = 0u; i < nftIDs.size(); ++i) {
294 if (
auto const maybeRow = nftInfos[i].
template get<uint32_t, ripple::AccountID, bool>();
295 maybeRow.has_value()) {
296 auto [seq, owner, isBurned] = *maybeRow;
297 NFT nft(nftIDs[i], seq, owner, isBurned);
298 if (
auto const maybeUri = nftUris[i].
template get<ripple::Blob>(); maybeUri.has_value())
300 ret.nfts.push_back(nft);
NFTsAndCursor fetchNFTsByIssuer(ripple::AccountID const &issuer, std::optional< std::uint32_t > const &taxon, std::uint32_t const ledgerSequence, std::uint32_t const limit, std::optional< ripple::uint256 > const &cursorIn, boost::asio::yield_context yield) const override
Fetches all NFTs issued by a given address.
Definition KeyspaceBackend.hpp:119