20 #include <ripple/app/ledger/LedgerMaster.h>
21 #include <ripple/app/main/Application.h>
22 #include <ripple/app/misc/HashRouter.h>
23 #include <ripple/app/misc/Transaction.h>
24 #include <ripple/app/tx/apply.h>
25 #include <ripple/basics/Log.h>
26 #include <ripple/basics/safe_cast.h>
27 #include <ripple/core/DatabaseCon.h>
28 #include <ripple/core/Pg.h>
29 #include <ripple/json/json_reader.h>
30 #include <ripple/protocol/ErrorCodes.h>
31 #include <ripple/protocol/Feature.h>
32 #include <ripple/protocol/jss.h>
33 #include <boost/optional.hpp>
41 : mTransaction(stx), mApp(app), j_(app.journal(
"Ledger"))
45 mTransactionID = mTransaction->getTransactionID();
70 char const c = (status) ? (*status)[0] : safe_cast<char>(
txnSqlUnknown);
92 boost::optional<std::uint64_t>
const& ledgerSeq,
93 boost::optional<std::string>
const& status,
98 rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0));
101 auto txn = std::make_shared<STTx const>(it);
103 auto tr = std::make_shared<Transaction>(txn, reason, app);
106 tr->setLedger(inLedger);
115 return load(
id, app, boost::none, ec);
127 using op = boost::optional<ClosedInterval<uint32_t>>;
135 #ifdef RIPPLED_REPORTING
136 auto baseCmd = boost::format(R
"(SELECT tx('%s');)");
141 auto res = PgQuery(app.getPgPool())(sql.
data());
147 <<
" : Postgres response is null - tx ID = " <<
strHex(
id);
151 else if (res.status() != PGRES_TUPLES_OK)
155 <<
" : Postgres response should have been "
156 "PGRES_TUPLES_OK but instead was "
157 << res.status() <<
" - msg = " << res.msg()
158 <<
" - tx ID = " <<
strHex(
id);
164 << __func__ <<
" Postgres result msg : " << res.msg();
165 if (res.isNull() || res.ntuples() == 0)
169 <<
" : No data returned from Postgres : tx ID = " <<
strHex(
id);
175 char const* resultStr = res.c_str();
177 <<
"postgres result = " << resultStr;
181 bool success = reader.
parse(resultStr, resultStr + strlen(resultStr), v);
190 uint32_t ledgerSeq = v[
"ledger_seq"].
asUInt();
197 v[
"min_seq"].asUInt(), v[
"max_seq"].asUInt())};
204 Throw<std::runtime_error>(
205 "Transaction::Locate - Invalid Postgres response");
218 "SELECT LedgerSeq,Status,RawTxn,TxnMeta "
219 "FROM Transactions WHERE TransID='";
224 boost::optional<std::uint64_t> ledgerSeq;
225 boost::optional<std::string> status;
226 Blob rawTxn, rawMeta;
229 soci::blob sociRawTxnBlob(*db), sociRawMetaBlob(*db);
230 soci::indicator txn, meta;
232 *db << sql, soci::into(ledgerSeq), soci::into(status),
233 soci::into(sociRawTxnBlob, txn), soci::into(sociRawMetaBlob, meta);
235 auto const got_data = db->got_data();
237 if ((!got_data || txn != soci::i_ok || meta != soci::i_ok) && !
range)
245 *db <<
"SELECT COUNT(DISTINCT LedgerSeq) FROM Transactions WHERE "
247 <<
range->first() <<
" AND " <<
range->last() <<
";",
248 soci::into(count, rti);
250 if (!db->got_data() || rti != soci::i_ok)
253 return count == (
range->last() -
range->first() + 1)
258 convert(sociRawTxnBlob, rawTxn);
259 convert(sociRawMetaBlob, rawMeta);
268 return std::pair{std::move(txn),
nullptr};
271 rangeCheckedCast<std::uint32_t>(ledgerSeq.value());
273 auto txMeta = std::make_shared<TxMeta>(
id, inLedger, rawMeta);
275 return std::pair{std::move(txn), std::move(txMeta)};
280 <<
"Unable to deserialize transaction from raw SQL value. Error: "
304 ret[jss::date] = ct->time_since_epoch().count();