Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 14 additions & 17 deletions src/database/Database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,11 +338,10 @@ migrateLedgerHeadersToStoreState(Database& db)
auto prep = db.getPreparedStatement(
"SELECT state FROM storestate WHERE statename = 'lastclosedledger'",
session);
auto& stmt = prep.statement();
stmt.exchange(soci::into(lclHash));
stmt.define_and_bind();
stmt.execute(true);
gotData = stmt.got_data();
prep.exchange(soci::into(lclHash));
prep.define_and_bind();
prep.execute(true);
gotData = prep.got_data();
}

// When we're doing this migration for a new db, storestate will be empty.
Expand All @@ -365,10 +364,9 @@ migrateLedgerHeadersToStoreState(Database& db)
db.getPreparedStatement("INSERT INTO storestate (statename, state) "
"VALUES ('lastclosedledgerheader', :v)",
session);
auto& stmt = prep.statement();
stmt.exchange(soci::use(headerData));
stmt.define_and_bind();
stmt.execute(true);
prep.exchange(soci::use(headerData));
prep.define_and_bind();
prep.execute(true);
raw << "DELETE FROM storestate WHERE statename = 'lastclosedledger'";
}

Expand Down Expand Up @@ -571,9 +569,8 @@ Database::setCurrentTransactionReadOnly()
{
auto prep =
getPreparedStatement("SET TRANSACTION READ ONLY", getSession());
auto& st = prep.statement();
st.define_and_bind();
st.execute(false);
prep.define_and_bind();
prep.execute(false);
}
}

Expand Down Expand Up @@ -739,13 +736,13 @@ Database::getMiscPool()
Database::getMiscDBName(mApp.getConfig().DATABASE.value));
}

StatementContext
soci::statement
Database::getPreparedStatement(std::string const& query,
SessionWrapper& session)
{
auto p = std::make_shared<soci::statement>(session.session());
p->alloc();
p->prepare(query);
return StatementContext(p);
soci::statement p(session.session());
p.alloc();
p.prepare(query);
return p;
}
}
42 changes: 3 additions & 39 deletions src/database/Database.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,39 +35,6 @@ static constexpr unsigned long FIRST_MAIN_VERSION_WITH_MISC = 26;
static constexpr unsigned long MIN_MISC_SCHEMA_VERSION = 0;
static constexpr unsigned long MISC_SCHEMA_VERSION = 1;

/**
* Helper class for borrowing a SOCI prepared statement handle into a local
* scope and cleaning it up once done with it. Returned by
* Database::getPreparedStatement below.
*/
class StatementContext : NonCopyable
{
std::shared_ptr<soci::statement> mStmt;

public:
StatementContext(std::shared_ptr<soci::statement> stmt) : mStmt(stmt)
{
mStmt->clean_up(false);
}
StatementContext(StatementContext&& other)
{
mStmt = other.mStmt;
other.mStmt.reset();
}
~StatementContext()
{
if (mStmt)
{
mStmt->clean_up(false);
}
}
soci::statement&
statement()
{
return *mStmt;
}
};

class SessionWrapper : NonCopyable
{
soci::session mSession;
Expand Down Expand Up @@ -160,12 +127,9 @@ class Database : NonMovableOrCopyable
{
}

// Return a helper object that borrows, from the Database, a prepared
// statement handle for the provided query. The prepared statement handle
// is created and reset (unbound from data) when the statement context
// is destroyed.
StatementContext getPreparedStatement(std::string const& query,
SessionWrapper& session);
// Return a prepared statement handle for the provided query.
soci::statement getPreparedStatement(std::string const& query,
SessionWrapper& session);

// Return metric-gathering timers for various families of SQL operation.
// These timers automatically count the time they are alive for,
Expand Down
42 changes: 18 additions & 24 deletions src/database/test/DatabaseTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,8 @@ TEST_CASE("Database splitting migration works correctly", "[db]")
// Helper to execute SQL on a session
auto execSQL = [&](std::string const& sql, SessionWrapper& session) {
auto prep = db.getPreparedStatement(sql, session);
auto& st = prep.statement();
st.define_and_bind();
st.execute(true);
prep.define_and_bind();
prep.execute(true);
};

// Helper to count rows in a table
Expand All @@ -446,10 +445,9 @@ TEST_CASE("Database splitting migration works correctly", "[db]")
int count = 0;
auto prep = db.getPreparedStatement("SELECT COUNT(*) FROM " + table,
session);
auto& st = prep.statement();
st.exchange(soci::into(count));
st.define_and_bind();
st.execute(true);
prep.exchange(soci::into(count));
prep.define_and_bind();
prep.execute(true);
return count;
};

Expand All @@ -462,10 +460,9 @@ TEST_CASE("Database splitting migration works correctly", "[db]")
"name='" +
table + "'",
session);
auto& st = prep.statement();
st.exchange(soci::into(count));
st.define_and_bind();
st.execute(true);
prep.exchange(soci::into(count));
prep.define_and_bind();
prep.execute(true);
return count > 0;
};

Expand Down Expand Up @@ -527,10 +524,9 @@ TEST_CASE("Database splitting migration works correctly", "[db]")
"SELECT state FROM storestate WHERE statename = "
"'lastclosedledgerheader'",
db.getSession());
auto& st = prep.statement();
st.exchange(soci::into(result));
st.define_and_bind();
st.execute(true);
prep.exchange(soci::into(result));
prep.define_and_bind();
prep.execute(true);
REQUIRE(result == headerEncoded);
}

Expand Down Expand Up @@ -564,11 +560,10 @@ TEST_CASE("Database splitting migration works correctly", "[db]")
int port = 0;
auto prep = db.getPreparedStatement("SELECT ip, port FROM peers",
db.getMiscSession());
auto& st = prep.statement();
st.exchange(soci::into(ip));
st.exchange(soci::into(port));
st.define_and_bind();
st.execute(true);
prep.exchange(soci::into(ip));
prep.exchange(soci::into(port));
prep.define_and_bind();
prep.execute(true);
REQUIRE(ip == "127.0.0.1");
REQUIRE(port == 11625);
}
Expand All @@ -578,10 +573,9 @@ TEST_CASE("Database splitting migration works correctly", "[db]")
"SELECT state FROM slotstate WHERE statename = "
"'ledgerupgrades'",
db.getMiscSession());
auto& st = prep.statement();
st.exchange(soci::into(state));
st.define_and_bind();
st.execute(true);
prep.exchange(soci::into(state));
prep.define_and_bind();
prep.execute(true);
REQUIRE(state == "testvalue");
}
}
Expand Down
77 changes: 35 additions & 42 deletions src/herder/HerderPersistenceImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,11 @@ HerderPersistenceImpl::saveSCPHistory(uint32_t seq,
auto prepClean = db.getPreparedStatement(
"DELETE FROM scphistory WHERE ledgerseq =:l", sess);

auto& st = prepClean.statement();
st.exchange(soci::use(seq));
st.define_and_bind();
prepClean.exchange(soci::use(seq));
prepClean.define_and_bind();
{
ZoneNamedN(deleteSCPHistoryZone, "delete scphistory", true);
st.execute(true);
prepClean.execute(true);
}
}

Expand Down Expand Up @@ -96,16 +95,15 @@ HerderPersistenceImpl::saveSCPHistory(uint32_t seq,
"(nodeid, ledgerseq, envelope) VALUES "
"(:n, :l, :e)",
sess);
auto& st = prepEnv.statement();
st.exchange(soci::use(nodeIDs, "n"));
st.exchange(soci::use(seqs, "l"));
st.exchange(soci::use(envelopes, "e"));
st.define_and_bind();
prepEnv.exchange(soci::use(nodeIDs, "n"));
prepEnv.exchange(soci::use(seqs, "l"));
prepEnv.exchange(soci::use(envelopes, "e"));
prepEnv.define_and_bind();
{
ZoneNamedN(insertSCPHistoryZone, "insert scphistory", true);
st.execute(true);
prepEnv.execute(true);
}
if (st.get_affected_rows() != envs.size())
if (prepEnv.get_affected_rows() != envs.size())
{
throw std::runtime_error("Could not update data in SQL");
}
Expand All @@ -128,28 +126,26 @@ HerderPersistenceImpl::saveSCPHistory(uint32_t seq,

auto prep = db.getPreparedStatement(
"UPDATE quoruminfo SET qsethash = :h WHERE nodeid = :id", sess);
auto& st = prep.statement();
st.exchange(soci::use(qSetHHex));
st.exchange(soci::use(nodeIDStrKey));
st.define_and_bind();
prep.exchange(soci::use(qSetHHex));
prep.exchange(soci::use(nodeIDStrKey));
prep.define_and_bind();
{
ZoneNamedN(updateQsetZone, "update quoruminfo", true);
st.execute(true);
prep.execute(true);
}
if (st.get_affected_rows() != 1)
if (prep.get_affected_rows() != 1)
{
auto prepI = db.getPreparedStatement(
"INSERT INTO quoruminfo (nodeid, qsethash) VALUES (:id, :h)",
sess);
auto& stI = prepI.statement();
stI.exchange(soci::use(nodeIDStrKey));
stI.exchange(soci::use(qSetHHex));
stI.define_and_bind();
prepI.exchange(soci::use(nodeIDStrKey));
prepI.exchange(soci::use(qSetHHex));
prepI.define_and_bind();
{
ZoneNamedN(insertQsetZone, "insert quoruminfo", true);
stI.execute(true);
prepI.execute(true);
}
if (stI.get_affected_rows() != 1)
if (prepI.get_affected_rows() != 1)
{
throw std::runtime_error("Could not update data in SQL");
}
Expand All @@ -163,16 +159,15 @@ HerderPersistenceImpl::saveSCPHistory(uint32_t seq,
uint32_t lastSeenSeq;
auto prepSelQSet = db.getPreparedStatement(
"SELECT lastledgerseq FROM scpquorums WHERE qsethash = :h", sess);
auto& stSel = prepSelQSet.statement();
stSel.exchange(soci::into(lastSeenSeq));
stSel.exchange(soci::use(qSetH));
stSel.define_and_bind();
prepSelQSet.exchange(soci::into(lastSeenSeq));
prepSelQSet.exchange(soci::use(qSetH));
prepSelQSet.define_and_bind();
{
ZoneNamedN(selectSCPQuorumsZone, "select scpquorums", true);
stSel.execute(true);
prepSelQSet.execute(true);
}

if (stSel.got_data())
if (prepSelQSet.got_data())
{
if (lastSeenSeq >= seq)
{
Expand All @@ -184,15 +179,14 @@ HerderPersistenceImpl::saveSCPHistory(uint32_t seq,
"lastledgerseq = :l WHERE qsethash = :h",
sess);

auto& stUp = prepUpQSet.statement();
stUp.exchange(soci::use(seq));
stUp.exchange(soci::use(qSetH));
stUp.define_and_bind();
prepUpQSet.exchange(soci::use(seq));
prepUpQSet.exchange(soci::use(qSetH));
prepUpQSet.define_and_bind();
{
ZoneNamedN(updateSCPQuorumsZone, "update scpquorums", true);
stUp.execute(true);
prepUpQSet.execute(true);
}
if (stUp.get_affected_rows() != 1)
if (prepUpQSet.get_affected_rows() != 1)
{
throw std::runtime_error("Could not update data in SQL");
}
Expand All @@ -210,16 +204,15 @@ HerderPersistenceImpl::saveSCPHistory(uint32_t seq,
"(:h, :l, :v);",
sess);

auto& stIns = prepInsQSet.statement();
stIns.exchange(soci::use(qSetH));
stIns.exchange(soci::use(seq));
stIns.exchange(soci::use(qSetEncoded));
stIns.define_and_bind();
prepInsQSet.exchange(soci::use(qSetH));
prepInsQSet.exchange(soci::use(seq));
prepInsQSet.exchange(soci::use(qSetEncoded));
prepInsQSet.define_and_bind();
{
ZoneNamedN(insertSCPQuorumsZone, "insert scpquorums", true);
stIns.execute(true);
prepInsQSet.execute(true);
}
if (stIns.get_affected_rows() != 1)
if (prepInsQSet.get_affected_rows() != 1)
{
throw std::runtime_error("Could not update data in SQL");
}
Expand Down
11 changes: 5 additions & 6 deletions src/herder/test/HerderTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6408,16 +6408,15 @@ TEST_CASE("SCP message capture from previous ledger", "[herder]")
auto prep = db.getPreparedStatement(
"SELECT envelope FROM scphistory WHERE ledgerseq = :l",
db.getMiscSession());
auto& st = prep.statement();
st.exchange(soci::use(ledgerNum));
prep.exchange(soci::use(ledgerNum));
std::string envStr;
st.exchange(soci::into(envStr));
st.define_and_bind();
st.execute(false);
prep.exchange(soci::into(envStr));
prep.define_and_bind();
prep.execute(false);

// Count the number of entries of each type
UnorderedMap<SCPStatementType, size_t> actualTypes;
while (st.fetch())
while (prep.fetch())
{
Value v;
decoder::decode_b64(envStr, v);
Expand Down
Loading
Loading