Fix nfts_by_issuer's DB issue (#997)

Fix #988
This commit is contained in:
cyan317
2023-11-22 15:55:46 +00:00
committed by GitHub
parent b998473673
commit f0224581a5
4 changed files with 32 additions and 72 deletions

View File

@@ -494,41 +494,39 @@ public:
if (nftIDs.size() == limit)
ret.cursor = nftIDs.back();
auto const nftQueryStatement = schema_->selectNFTBulk.bind(nftIDs);
nftQueryStatement.bindAt(1, ledgerSequence);
std::vector<Statement> selectNFTStatements;
selectNFTStatements.reserve(nftIDs.size());
// Fetch all the NFT data, meanwhile filtering out the NFTs that are not within the ledger range
auto const nftRes = executor_.read(yield, nftQueryStatement);
auto const& nftQueryResults = nftRes.value();
std::transform(
std::cbegin(nftIDs),
std::cend(nftIDs),
std::back_inserter(selectNFTStatements),
[&](auto const& nftID) { return schema_->selectNFT.bind(nftID, ledgerSequence); }
);
if (not nftQueryResults.hasRows()) {
LOG(log_.debug()) << "No rows returned";
return {};
auto const nftInfos = executor_.readEach(yield, selectNFTStatements);
std::vector<Statement> selectNFTURIStatements;
selectNFTURIStatements.reserve(nftIDs.size());
std::transform(
std::cbegin(nftIDs),
std::cend(nftIDs),
std::back_inserter(selectNFTURIStatements),
[&](auto const& nftID) { return schema_->selectNFTURI.bind(nftID, ledgerSequence); }
);
auto const nftUris = executor_.readEach(yield, selectNFTURIStatements);
for (auto i = 0u; i < nftIDs.size(); i++) {
if (auto const maybeRow = nftInfos[i].template get<uint32_t, ripple::AccountID, bool>(); maybeRow) {
auto [seq, owner, isBurned] = *maybeRow;
NFT nft(nftIDs[i], seq, owner, isBurned);
if (auto const maybeUri = nftUris[i].template get<ripple::Blob>(); maybeUri)
nft.uri = *maybeUri;
ret.nfts.push_back(nft);
}
}
auto const nftURIQueryStatement = schema_->selectNFTURIBulk.bind(nftIDs);
nftURIQueryStatement.bindAt(1, ledgerSequence);
// Get the URI for each NFT, but it's possible that URI doesn't exist
auto const uriRes = executor_.read(yield, nftURIQueryStatement);
auto const& nftURIQueryResults = uriRes.value();
std::unordered_map<std::string, Blob> nftURIMap;
for (auto const [nftID, uri] : extract<ripple::uint256, Blob>(nftURIQueryResults))
nftURIMap.insert({ripple::strHex(nftID), uri});
for (auto const [nftID, seq, owner, isBurned] :
extract<ripple::uint256, std::uint32_t, ripple::AccountID, bool>(nftQueryResults)) {
NFT nft;
nft.tokenID = nftID;
nft.ledgerSequence = seq;
nft.owner = owner;
nft.isBurned = isBurned;
if (nftURIMap.contains(ripple::strHex(nft.tokenID)))
nft.uri = nftURIMap.at(ripple::strHex(nft.tokenID));
ret.nfts.push_back(nft);
}
return ret;
}

View File

@@ -592,20 +592,6 @@ public:
));
}();
PreparedStatement selectNFTBulk = [this]() {
return handle_.get().prepare(fmt::format(
R"(
SELECT token_id, sequence, owner, is_burned
FROM {}
WHERE token_id IN ?
AND sequence <= ?
ORDER BY sequence DESC
PER PARTITION LIMIT 1
)",
qualifiedTableName(settingsProvider_.get(), "nf_tokens")
));
}();
PreparedStatement selectNFTURI = [this]() {
return handle_.get().prepare(fmt::format(
R"(
@@ -620,20 +606,6 @@ public:
));
}();
PreparedStatement selectNFTURIBulk = [this]() {
return handle_.get().prepare(fmt::format(
R"(
SELECT token_id, uri
FROM {}
WHERE token_id IN ?
AND sequence <= ?
ORDER BY sequence DESC
PER PARTITION LIMIT 1
)",
qualifiedTableName(settingsProvider_.get(), "nf_token_uris")
));
}();
PreparedStatement selectNFTTx = [this]() {
return handle_.get().prepare(fmt::format(
R"(

View File

@@ -20,7 +20,7 @@
#pragma once
#include <data/BackendInterface.h>
#include <rpc/RPCHelpers.h>
#include <rpc/JS.h>
#include <rpc/common/Modifiers.h>
#include <rpc/common/Types.h>
#include <rpc/common/Validators.h>

View File

@@ -321,16 +321,6 @@ TEST_F(RPCNFTsByIssuerHandlerTest, NonExistLedgerViaLedgerIndex2)
// normal case when issuer does not exist or has no NFTs
TEST_F(RPCNFTsByIssuerHandlerTest, AccountNotFound)
{
auto const currentOutput = fmt::format(
R"({{
"issuer": "{}",
"limit":50,
"ledger_index": 30,
"nfts": [],
"validated": true
}})",
ACCOUNT
);
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
ASSERT_NE(rawBackendPtr, nullptr);
mockBackendPtr->updateRange(10); // min
@@ -667,4 +657,4 @@ TEST_F(RPCNFTsByIssuerHandlerTest, LimitMoreThanMAx)
ASSERT_TRUE(output);
EXPECT_EQ(json::parse(currentOutput), *output);
});
}
}