mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 22:45:52 +00:00
Sort order, limit, and offsets work. Still to do: detecting when we've requested too many ledgers.
This commit is contained in:
@@ -1060,28 +1060,52 @@ void NetworkOPs::setMode(OperatingMode om)
|
||||
|
||||
|
||||
std::string
|
||||
NetworkOPs::transactionsSQL(const RippleAddress& account, uint32 minLedger, uint32 maxLedger, bool descending, uint32 offset, uint32 limit, bool binary, bool bAdmin)
|
||||
NetworkOPs::transactionsSQL(std::string selection, const RippleAddress& account, int32 minLedger, int32 maxLedger, bool descending, uint32 offset, uint32 limit, bool binary, bool bAdmin)
|
||||
{
|
||||
uint32 NONBINARY_PAGE_LENGTH = 200;
|
||||
uint32 BINARY_PAGE_LENGTH = 500;
|
||||
uint32 numberOfResults = limit;
|
||||
if (limit == 0) {numberOfResults = std::numeric_limits<uint32>::max();}
|
||||
if (!bAdmin) {
|
||||
if (numberOfResults < (binary ? BINARY_PAGE_LENGTH : NONBINARY_PAGE_LENGTH)) {
|
||||
numberOfResults = (binary ? BINARY_PAGE_LENGTH : NONBINARY_PAGE_LENGTH);
|
||||
}
|
||||
}
|
||||
// How to get only validated ledgers?
|
||||
|
||||
std::string maxClause = "";
|
||||
std::string minClause = "";
|
||||
if (maxLedger != -1) {
|
||||
maxClause = boost::str(boost::format("AND AccountTransactions.LedgerSeq <= '%u'") % maxLedger);
|
||||
}
|
||||
if (minLedger != -1) {
|
||||
minClause = boost::str(boost::format("AND AccountTransactions.LedgerSeq >= '%u'") % minLedger);
|
||||
}
|
||||
|
||||
std::string sql =
|
||||
boost::str(boost::format("SELECT AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta FROM "
|
||||
boost::str(boost::format("SELECT %s FROM "
|
||||
"AccountTransactions INNER JOIN Transactions ON Transactions.TransID = AccountTransactions.TransID "
|
||||
"WHERE Account = '%s' AND AccountTransactions.LedgerSeq <= '%u' AND AccountTransactions.LedgerSeq >= '%u' "
|
||||
"ORDER BY AccountTransactions.LedgerSeq,AccountTransactions.TransID %sSC%s;")
|
||||
% account.humanAccountID() % maxLedger % minLedger % (descending ? "DE" : "A") % (bAdmin ? "" : (" LIMIT "+boost::lexical_cast<std::string>(offset)+(binary?"500":"200") ) ) );
|
||||
"WHERE Account = '%s' %s %s "
|
||||
"ORDER BY AccountTransactions.LedgerSeq %sSC, AccountTransactions.TransID %sSC LIMIT %u, %u;")
|
||||
% selection
|
||||
% account.humanAccountID()
|
||||
% maxClause
|
||||
% minClause
|
||||
% (descending ? "DE" : "A")
|
||||
% (descending ? "DE" : "A")
|
||||
% boost::lexical_cast<std::string>(offset)
|
||||
% boost::lexical_cast<std::string>(numberOfResults)
|
||||
);
|
||||
std::cout << "SQL QUERY! " << sql;
|
||||
return sql;
|
||||
}
|
||||
|
||||
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
|
||||
NetworkOPs::getAccountTxs(const RippleAddress& account, uint32 minLedger, uint32 maxLedger, bool bAdmin)
|
||||
NetworkOPs::getAccountTxs(const RippleAddress& account, int32 minLedger, int32 maxLedger, bool descending, uint32 offset, uint32 limit, bool bAdmin)
|
||||
{ // can be called with no locks
|
||||
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > ret;
|
||||
|
||||
std::string sql =
|
||||
boost::str(boost::format("SELECT AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta FROM "
|
||||
"AccountTransactions INNER JOIN Transactions ON Transactions.TransID = AccountTransactions.TransID "
|
||||
"WHERE Account = '%s' AND AccountTransactions.LedgerSeq <= '%u' AND AccountTransactions.LedgerSeq >= '%u' "
|
||||
"ORDER BY AccountTransactions.LedgerSeq,AccountTransactions.TransID DESC%s;")
|
||||
% account.humanAccountID() % maxLedger % minLedger % (bAdmin ? "" : " LIMIT 200"));
|
||||
std::string sql = NetworkOPs::transactionsSQL("AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta", account, minLedger, maxLedger, descending, offset, limit, false, bAdmin);
|
||||
|
||||
{
|
||||
Database* db = theApp->getTxnDB()->getDB();
|
||||
@@ -1110,15 +1134,13 @@ std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
|
||||
}
|
||||
|
||||
std::vector<NetworkOPs::txnMetaLedgerType> NetworkOPs::getAccountTxsB(
|
||||
const RippleAddress& account, uint32 minLedger, uint32 maxLedger, bool bAdmin)
|
||||
const RippleAddress& account, int32 minLedger, int32 maxLedger, bool descending, uint32 offset, uint32 limit, bool bAdmin)
|
||||
{ // can be called with no locks
|
||||
std::vector< txnMetaLedgerType> ret;
|
||||
|
||||
std::string sql = str(boost::format("SELECT AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta FROM "
|
||||
"AccountTransactions INNER JOIN Transactions ON Transactions.TransID = AccountTransactions.TransID "
|
||||
"WHERE Account = '%s' AND AccountTransactions.LedgerSeq <= '%u' AND AccountTransactions.LedgerSeq >= '%u' "
|
||||
"ORDER BY AccountTransactions.LedgerSeq,AccountTransactions.TransID DESC%s;")
|
||||
% account.humanAccountID() % maxLedger % minLedger % (bAdmin ? "" : " LIMIT 500"));
|
||||
|
||||
std::string sql = NetworkOPs::transactionsSQL("AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta", account, minLedger, maxLedger, descending, offset, limit, true/*binary*/, bAdmin);
|
||||
|
||||
|
||||
{
|
||||
Database* db = theApp->getTxnDB()->getDB();
|
||||
@@ -1156,6 +1178,26 @@ std::vector<NetworkOPs::txnMetaLedgerType> NetworkOPs::getAccountTxsB(
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uint32
|
||||
NetworkOPs::countAccountTxs(const RippleAddress& account, int32 minLedger, int32 maxLedger, uint32 offset)
|
||||
{ // can be called with no locks
|
||||
uint32 ret = 0;
|
||||
std::string sql = NetworkOPs::transactionsSQL("COUNT(1) AS 'TransactionCount'", account, minLedger, maxLedger, false, offset, 0, true, true);
|
||||
|
||||
|
||||
Database* db = theApp->getTxnDB()->getDB();
|
||||
ScopedLock sl(theApp->getTxnDB()->getDBLock());
|
||||
SQL_FOREACH(db, sql)
|
||||
{
|
||||
ret = db->getInt("TransactionCount");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::vector<RippleAddress>
|
||||
NetworkOPs::getLedgerAffectedAccounts(uint32 ledgerSeq)
|
||||
{
|
||||
|
||||
@@ -293,20 +293,20 @@ public:
|
||||
bool isWantedHash(const uint256& h, bool remove);
|
||||
|
||||
//Helper function to generate SQL query to get transactions
|
||||
std::string transactionsSQL(const RippleAddress& account, uint32 minLedger, uint32 maxLedger, bool descending, uint32 offset, uint32 limit, bool binary, bool bAdmin);
|
||||
std::string transactionsSQL(std::string selection, const RippleAddress& account, int32 minLedger, int32 maxLedger, bool descending, uint32 offset, uint32 limit, bool binary, bool bAdmin);
|
||||
|
||||
|
||||
// client information retrieval functions
|
||||
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
|
||||
getAccountTxs(const RippleAddress& account, uint32 minLedger, uint32 maxLedger, bool bAdmin);
|
||||
getAccountTxs(const RippleAddress& account, int32 minLedger, int32 maxLedger, bool descending, uint32 offset, uint32 limit, bool bAdmin);
|
||||
|
||||
typedef boost::tuple<std::string, std::string, uint32> txnMetaLedgerType;
|
||||
std::vector<txnMetaLedgerType>
|
||||
getAccountTxsB(const RippleAddress& account, uint32 minL, uint32 maxL, bool bAdmin);
|
||||
getAccountTxsB(const RippleAddress& account, int32 minLedger, int32 maxLedger, bool descending, uint32 offset, uint32 limit, bool bAdmin);
|
||||
|
||||
std::vector<RippleAddress> getLedgerAffectedAccounts(uint32 ledgerSeq);
|
||||
std::vector<SerializedTransaction> getLedgerTransactions(uint32 ledgerSeq);
|
||||
|
||||
uint32 NetworkOPs::countAccountTxs(const RippleAddress& account, int32 minLedger, int32 maxLedger, uint32 offset);
|
||||
//
|
||||
// Monitoring: publisher side
|
||||
//
|
||||
|
||||
@@ -1664,8 +1664,14 @@ Json::Value RPCHandler::doLedger(Json::Value jvRequest, int& cost)
|
||||
Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest, int& cost)
|
||||
{
|
||||
RippleAddress raAccount;
|
||||
uint32 minLedger;
|
||||
uint32 maxLedger;
|
||||
int32 minLedger;
|
||||
int32 maxLedger;
|
||||
bool descending = false;
|
||||
uint32 offset = 0;
|
||||
uint32 limit = 0;
|
||||
bool count = false;
|
||||
|
||||
bool allValidated = true;
|
||||
|
||||
if (!jvRequest.isMember("account"))
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
@@ -1675,8 +1681,8 @@ Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest, int& cost)
|
||||
|
||||
if (jvRequest.isMember("ledger_min") && jvRequest.isMember("ledger_max"))
|
||||
{
|
||||
minLedger = jvRequest["ledger_min"].asUInt();
|
||||
maxLedger = jvRequest["ledger_max"].asUInt();
|
||||
minLedger = jvRequest["ledger_min"].asInt();
|
||||
maxLedger = jvRequest["ledger_max"].asInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1692,6 +1698,23 @@ Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest, int& cost)
|
||||
return rpcError(rpcLGR_IDXS_INVALID);
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("descending"))
|
||||
{
|
||||
descending = jvRequest["descending"].asBool();
|
||||
}
|
||||
if (jvRequest.isMember("offset"))
|
||||
{
|
||||
offset = jvRequest["offset"].asUInt();
|
||||
}
|
||||
if (jvRequest.isMember("limit"))
|
||||
{
|
||||
limit = jvRequest["limit"].asUInt();
|
||||
}
|
||||
if (jvRequest.isMember("count"))
|
||||
{
|
||||
count = jvRequest["count"].asBool();
|
||||
}
|
||||
|
||||
#ifndef DEBUG
|
||||
try
|
||||
{
|
||||
@@ -1705,7 +1728,7 @@ Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest, int& cost)
|
||||
if (jvRequest.isMember("binary") && jvRequest["binary"].asBool())
|
||||
{
|
||||
std::vector<NetworkOPs::txnMetaLedgerType> txns =
|
||||
mNetOps->getAccountTxsB(raAccount, minLedger, maxLedger, mRole == ADMIN);
|
||||
mNetOps->getAccountTxsB(raAccount, minLedger, maxLedger, descending, offset, limit, mRole == ADMIN);
|
||||
|
||||
for (std::vector<NetworkOPs::txnMetaLedgerType>::const_iterator it = txns.begin(), end = txns.end();
|
||||
it != end; ++it)
|
||||
@@ -1714,16 +1737,21 @@ Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest, int& cost)
|
||||
obj["transaction"] = it->get<0>();
|
||||
obj["meta"] = it->get<1>();
|
||||
obj["inLedger"] = it->get<2>();
|
||||
if (it->get<2>() > vl)
|
||||
if (it->get<2>() > vl) {
|
||||
obj["validated"] = false;
|
||||
allValidated = false;
|
||||
}
|
||||
else if (mNetOps->haveLedger(it->get<2>()))
|
||||
obj["validated"] = true;
|
||||
else {
|
||||
//return rpcError(rpcLGR_NOT_FOUND);
|
||||
}
|
||||
ret["transactions"].append(obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > txns = mNetOps->getAccountTxs(raAccount, minLedger, maxLedger, mRole == ADMIN);
|
||||
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > txns = mNetOps->getAccountTxs(raAccount, minLedger, maxLedger, descending, offset, limit, mRole == ADMIN);
|
||||
for (std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >::iterator it = txns.begin(), end = txns.end(); it != end; ++it)
|
||||
{
|
||||
Json::Value obj(Json::objectValue);
|
||||
@@ -1735,15 +1763,31 @@ Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest, int& cost)
|
||||
obj["meta"] = it->second->getJson(0);
|
||||
|
||||
uint32 s = it->second->getLgrSeq();
|
||||
if (s > vl)
|
||||
if (s > vl) {
|
||||
obj["validated"] = false;
|
||||
allValidated = false;
|
||||
}
|
||||
else if (mNetOps->haveLedger(s))
|
||||
obj["validated"] = true;
|
||||
else {
|
||||
//return rpcError(rpcLGR_NOT_FOUND); //Can this also happen when s > vl?
|
||||
}
|
||||
}
|
||||
|
||||
ret["transactions"].append(obj);
|
||||
}
|
||||
}
|
||||
|
||||
//Add information about the original query
|
||||
ret["validated"] = allValidated;
|
||||
if(count) {
|
||||
ret["count"] = mNetOps->countAccountTxs(raAccount, minLedger, maxLedger, offset);
|
||||
}
|
||||
ret["limit"] = limit;
|
||||
ret["ledger_min"] = minLedger;
|
||||
ret["ledger_max"] = maxLedger;
|
||||
ret["offset"] = offset;
|
||||
|
||||
return ret;
|
||||
#ifndef DEBUG
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user