From f0224581a56714f7df770f473a3675a30db7538b Mon Sep 17 00:00:00 2001 From: cyan317 <120398799+cindyyan317@users.noreply.github.com> Date: Wed, 22 Nov 2023 15:55:46 +0000 Subject: [PATCH] Fix nfts_by_issuer's DB issue (#997) Fix #988 --- src/data/CassandraBackend.h | 62 ++++++++++----------- src/data/cassandra/Schema.h | 28 ---------- src/rpc/handlers/NFTsByIssuer.h | 2 +- unittests/rpc/handlers/NFTsByIssuerTest.cpp | 12 +--- 4 files changed, 32 insertions(+), 72 deletions(-) diff --git a/src/data/CassandraBackend.h b/src/data/CassandraBackend.h index 26daa65e..7107b473 100644 --- a/src/data/CassandraBackend.h +++ b/src/data/CassandraBackend.h @@ -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 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 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(); maybeRow) { + auto [seq, owner, isBurned] = *maybeRow; + NFT nft(nftIDs[i], seq, owner, isBurned); + if (auto const maybeUri = nftUris[i].template get(); 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 nftURIMap; - for (auto const [nftID, uri] : extract(nftURIQueryResults)) - nftURIMap.insert({ripple::strHex(nftID), uri}); - - for (auto const [nftID, seq, owner, isBurned] : - extract(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; } diff --git a/src/data/cassandra/Schema.h b/src/data/cassandra/Schema.h index 8bfb60dc..3e5e56bf 100644 --- a/src/data/cassandra/Schema.h +++ b/src/data/cassandra/Schema.h @@ -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"( diff --git a/src/rpc/handlers/NFTsByIssuer.h b/src/rpc/handlers/NFTsByIssuer.h index 8b80f3d6..1fbcc3d5 100644 --- a/src/rpc/handlers/NFTsByIssuer.h +++ b/src/rpc/handlers/NFTsByIssuer.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include #include #include diff --git a/unittests/rpc/handlers/NFTsByIssuerTest.cpp b/unittests/rpc/handlers/NFTsByIssuerTest.cpp index a006c025..72382efa 100644 --- a/unittests/rpc/handlers/NFTsByIssuerTest.cpp +++ b/unittests/rpc/handlers/NFTsByIssuerTest.cpp @@ -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(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); }); -} \ No newline at end of file +}