From 82a8e4215372495f97c63ebe4791e9fb1438a843 Mon Sep 17 00:00:00 2001 From: MonsieurNicolas Date: Mon, 12 Aug 2019 18:52:58 -0700 Subject: [PATCH 1/4] squash database version 7 --- src/database/Database.cpp | 19 ++++-------------- src/ledger/LedgerTxnAccountSQL.cpp | 30 +++++++++++----------------- src/ledger/LedgerTxnTrustLineSQL.cpp | 2 ++ 3 files changed, 18 insertions(+), 33 deletions(-) diff --git a/src/database/Database.cpp b/src/database/Database.cpp index d24fe7f26e..e866c0ef12 100644 --- a/src/database/Database.cpp +++ b/src/database/Database.cpp @@ -189,18 +189,6 @@ Database::applySchemaUpgrade(unsigned long vers) soci::transaction tx(mSession); switch (vers) { - case 7: - Upgrades::dropAll(*this); - mSession << "ALTER TABLE accounts ADD buyingliabilities BIGINT " - "CHECK (buyingliabilities >= 0)"; - mSession << "ALTER TABLE accounts ADD sellingliabilities BIGINT " - "CHECK (sellingliabilities >= 0)"; - mSession << "ALTER TABLE trustlines ADD buyingliabilities BIGINT " - "CHECK (buyingliabilities >= 0)"; - mSession << "ALTER TABLE trustlines ADD sellingliabilities BIGINT " - "CHECK (sellingliabilities >= 0)"; - break; - case 8: mSession << "ALTER TABLE peers RENAME flags TO type"; mSession << "UPDATE peers SET type = 2*type"; @@ -223,10 +211,10 @@ Database::applySchemaUpgrade(unsigned long vers) mApp.getHerderPersistence().createQuorumTrackingTable(mSession); break; default: - if (vers <= 6) + if (vers <= 7) { throw std::runtime_error( - "Database version is too old, must use at least 7"); + "Database version is too old, must use at least 8"); } else { @@ -390,6 +378,7 @@ Database::initialize() // only time this section should be modified is when // consolidating changes found in applySchemaUpgrade here + Upgrades::dropAll(*this); mApp.getLedgerTxnRoot().dropAccounts(); mApp.getLedgerTxnRoot().dropOffers(); mApp.getLedgerTxnRoot().dropTrustLines(); @@ -402,7 +391,7 @@ Database::initialize() HerderPersistence::dropAll(*this); mApp.getLedgerTxnRoot().dropData(); BanManager::dropAll(*this); - putSchemaVersion(6); + putSchemaVersion(7); LOG(INFO) << "* "; LOG(INFO) << "* The database has been initialized"; diff --git a/src/ledger/LedgerTxnAccountSQL.cpp b/src/ledger/LedgerTxnAccountSQL.cpp index 16f0deb4d2..12c5108b23 100644 --- a/src/ledger/LedgerTxnAccountSQL.cpp +++ b/src/ledger/LedgerTxnAccountSQL.cpp @@ -530,25 +530,19 @@ LedgerTxnRoot::Impl::dropAccounts() mDatabase.getSession() << "CREATE TABLE accounts" "(" - "accountid VARCHAR(56) PRIMARY KEY," - "balance BIGINT NOT NULL CHECK (balance >= 0)," - "seqnum BIGINT NOT NULL," - "numsubentries INT NOT NULL CHECK (numsubentries >= 0)," - "inflationdest VARCHAR(56)," - "homedomain VARCHAR(32) NOT NULL," - "thresholds TEXT NOT NULL," - "flags INT NOT NULL," - "lastmodified INT NOT NULL" + "accountid VARCHAR(56) PRIMARY KEY," + "balance BIGINT NOT NULL CHECK (balance >= 0)," + "buyingliabilities BIGINT CHECK (buyingliabilities >= 0)," + "sellingliabilities BIGINT CHECK (sellingliabilities >= 0)," + "seqnum BIGINT NOT NULL," + "numsubentries INT NOT NULL CHECK (numsubentries >= " + "0)," + "inflationdest VARCHAR(56)," + "homedomain VARCHAR(32) NOT NULL," + "thresholds TEXT NOT NULL," + "flags INT NOT NULL," + "lastmodified INT NOT NULL" ");"; - mDatabase.getSession() << "CREATE TABLE signers" - "(" - "accountid VARCHAR(56) NOT NULL," - "publickey VARCHAR(56) NOT NULL," - "weight INT NOT NULL," - "PRIMARY KEY (accountid, publickey)" - ");"; - mDatabase.getSession() - << "CREATE INDEX signersaccount ON signers (accountid)"; mDatabase.getSession() << "CREATE INDEX accountbalances ON accounts (balance) WHERE " "balance >= 1000000000"; diff --git a/src/ledger/LedgerTxnTrustLineSQL.cpp b/src/ledger/LedgerTxnTrustLineSQL.cpp index 6f784508b8..d90600cf15 100644 --- a/src/ledger/LedgerTxnTrustLineSQL.cpp +++ b/src/ledger/LedgerTxnTrustLineSQL.cpp @@ -410,6 +410,8 @@ LedgerTxnRoot::Impl::dropTrustLines() "assetcode VARCHAR(12) NOT NULL," "tlimit BIGINT NOT NULL CHECK (tlimit > 0)," "balance BIGINT NOT NULL CHECK (balance >= 0)," + "buyingliabilities BIGINT CHECK (buyingliabilities >= 0)," + "sellingliabilities BIGINT CHECK (sellingliabilities >= 0)," "flags INT NOT NULL," "lastmodified INT NOT NULL," "PRIMARY KEY (accountid, issuer, assetcode)" From f5482fb8146f43ad4b78f6afe59d8692f8fff4c1 Mon Sep 17 00:00:00 2001 From: MonsieurNicolas Date: Mon, 12 Aug 2019 18:54:59 -0700 Subject: [PATCH 2/4] squash database schema version 8 --- src/database/Database.cpp | 10 +++------- src/overlay/PeerManager.cpp | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/database/Database.cpp b/src/database/Database.cpp index e866c0ef12..6bec5bc121 100644 --- a/src/database/Database.cpp +++ b/src/database/Database.cpp @@ -189,10 +189,6 @@ Database::applySchemaUpgrade(unsigned long vers) soci::transaction tx(mSession); switch (vers) { - case 8: - mSession << "ALTER TABLE peers RENAME flags TO type"; - mSession << "UPDATE peers SET type = 2*type"; - break; case 9: // Update schema for signers mSession << "ALTER TABLE accounts ADD signers TEXT"; @@ -211,10 +207,10 @@ Database::applySchemaUpgrade(unsigned long vers) mApp.getHerderPersistence().createQuorumTrackingTable(mSession); break; default: - if (vers <= 7) + if (vers <= 8) { throw std::runtime_error( - "Database version is too old, must use at least 8"); + "Database version is too old, must use at least 9"); } else { @@ -391,7 +387,7 @@ Database::initialize() HerderPersistence::dropAll(*this); mApp.getLedgerTxnRoot().dropData(); BanManager::dropAll(*this); - putSchemaVersion(7); + putSchemaVersion(8); LOG(INFO) << "* "; LOG(INFO) << "* The database has been initialized"; diff --git a/src/overlay/PeerManager.cpp b/src/overlay/PeerManager.cpp index 64c78c5ca4..e9eec31400 100644 --- a/src/overlay/PeerManager.cpp +++ b/src/overlay/PeerManager.cpp @@ -517,7 +517,7 @@ const char* PeerManager::kSQLCreateStatement = "port INT DEFAULT 0 CHECK (port > 0 AND port <= 65535) NOT NULL," "nextattempt TIMESTAMP NOT NULL," "numfailures INT DEFAULT 0 CHECK (numfailures >= 0) NOT NULL," - "flags INT NOT NULL," + "type INT NOT NULL," "PRIMARY KEY (ip, port)" ");"; } From 17deb58679c95c7ae062d4aec64757ac5d7e2d53 Mon Sep 17 00:00:00 2001 From: MonsieurNicolas Date: Mon, 12 Aug 2019 19:02:51 -0700 Subject: [PATCH 3/4] squash database schema version 9 --- src/database/Database.cpp | 19 +--- src/ledger/LedgerTxn.cpp | 24 ----- src/ledger/LedgerTxn.h | 5 - src/ledger/LedgerTxnAccountSQL.cpp | 145 +--------------------------- src/ledger/LedgerTxnDataSQL.cpp | 65 ------------- src/ledger/LedgerTxnImpl.h | 24 ----- src/ledger/LedgerTxnOfferSQL.cpp | 148 ++--------------------------- 7 files changed, 10 insertions(+), 420 deletions(-) diff --git a/src/database/Database.cpp b/src/database/Database.cpp index 6bec5bc121..a4aa6b59dc 100644 --- a/src/database/Database.cpp +++ b/src/database/Database.cpp @@ -189,28 +189,15 @@ Database::applySchemaUpgrade(unsigned long vers) soci::transaction tx(mSession); switch (vers) { - case 9: - // Update schema for signers - mSession << "ALTER TABLE accounts ADD signers TEXT"; - mApp.getLedgerTxnRoot().writeSignersTableIntoAccountsTable(); - mSession << "DROP TABLE IF EXISTS signers"; - - // Update schema for base-64 encoding - mApp.getLedgerTxnRoot().encodeDataNamesBase64(); - mApp.getLedgerTxnRoot().encodeHomeDomainsBase64(); - - // Update schema for simplified offers table - mApp.getLedgerTxnRoot().writeOffersIntoSimplifiedOffersTable(); - break; case 10: // add tracking table information mApp.getHerderPersistence().createQuorumTrackingTable(mSession); break; default: - if (vers <= 8) + if (vers <= 9) { throw std::runtime_error( - "Database version is too old, must use at least 9"); + "Database version is too old, must use at least 10"); } else { @@ -387,7 +374,7 @@ Database::initialize() HerderPersistence::dropAll(*this); mApp.getLedgerTxnRoot().dropData(); BanManager::dropAll(*this); - putSchemaVersion(8); + putSchemaVersion(9); LOG(INFO) << "* "; LOG(INFO) << "* The database has been initialized"; diff --git a/src/ledger/LedgerTxn.cpp b/src/ledger/LedgerTxn.cpp index f1907efd16..722f6e153a 100644 --- a/src/ledger/LedgerTxn.cpp +++ b/src/ledger/LedgerTxn.cpp @@ -2008,28 +2008,4 @@ LedgerTxnRoot::Impl::getFromBestOffersCache( throw; } } - -void -LedgerTxnRoot::writeSignersTableIntoAccountsTable() -{ - mImpl->writeSignersTableIntoAccountsTable(); -} - -void -LedgerTxnRoot::encodeDataNamesBase64() -{ - mImpl->encodeDataNamesBase64(); -} - -void -LedgerTxnRoot::encodeHomeDomainsBase64() -{ - mImpl->encodeHomeDomainsBase64(); -} - -void -LedgerTxnRoot::writeOffersIntoSimplifiedOffersTable() -{ - mImpl->writeOffersIntoSimplifiedOffersTable(); -} } diff --git a/src/ledger/LedgerTxn.h b/src/ledger/LedgerTxn.h index c774422d32..93fe9621ba 100644 --- a/src/ledger/LedgerTxn.h +++ b/src/ledger/LedgerTxn.h @@ -597,11 +597,6 @@ class LedgerTxnRoot : public AbstractLedgerTxnParent void rollbackChild() override; - void writeSignersTableIntoAccountsTable(); - void encodeDataNamesBase64(); - void encodeHomeDomainsBase64(); - - void writeOffersIntoSimplifiedOffersTable(); uint32_t prefetch(std::unordered_set const& keys); double getPrefetchHitRate() const; }; diff --git a/src/ledger/LedgerTxnAccountSQL.cpp b/src/ledger/LedgerTxnAccountSQL.cpp index 12c5108b23..0acad9afcd 100644 --- a/src/ledger/LedgerTxnAccountSQL.cpp +++ b/src/ledger/LedgerTxnAccountSQL.cpp @@ -128,74 +128,6 @@ LedgerTxnRoot::Impl::loadInflationWinners(size_t maxWinners, return winners; } -void -LedgerTxnRoot::Impl::writeSignersTableIntoAccountsTable() -{ - throwIfChild(); - soci::transaction sqlTx(mDatabase.getSession()); - - CLOG(INFO, "Ledger") << "Loading all signers from signers table"; - std::map> signersByAccount; - - { - std::string accountIDStrKey, pubKey; - Signer signer; - - auto prep = mDatabase.getPreparedStatement( - "SELECT accountid, publickey, weight FROM signers"); - auto& st = prep.statement(); - st.exchange(soci::into(accountIDStrKey)); - st.exchange(soci::into(pubKey)); - st.exchange(soci::into(signer.weight)); - st.define_and_bind(); - { - auto timer = mDatabase.getSelectTimer("signer"); - st.execute(true); - } - while (st.got_data()) - { - signer.key = KeyUtils::fromStrKey(pubKey); - signersByAccount[accountIDStrKey].emplace_back(signer); - st.fetch(); - } - } - - size_t numAccountsUpdated = 0; - for (auto& kv : signersByAccount) - { - std::sort(kv.second.begin(), kv.second.end(), - [](Signer const& lhs, Signer const& rhs) { - return lhs.key < rhs.key; - }); - std::string signers(decoder::encode_b64(xdr::xdr_to_opaque(kv.second))); - - auto prep = mDatabase.getPreparedStatement( - "UPDATE accounts SET signers = :v1 WHERE accountID = :id"); - auto& st = prep.statement(); - st.exchange(soci::use(signers, "v1")); - st.exchange(soci::use(kv.first, "id")); - st.define_and_bind(); - st.execute(true); - if (static_cast(st.get_affected_rows()) != 1) - { - throw std::runtime_error("Could not update data in SQL"); - } - - if ((++numAccountsUpdated & 0xfff) == 0xfff || - (numAccountsUpdated == signersByAccount.size())) - { - CLOG(INFO, "Ledger") - << "Wrote signers for " << numAccountsUpdated << " accounts"; - } - } - - sqlTx.commit(); - - // Clearing the cache does not throw - mEntryCache.clear(); - mBestOffersCache.clear(); -} - class BulkUpsertAccountsOperation : public DatabaseTypeSpecificOperation { Database& mDB; @@ -541,6 +473,7 @@ LedgerTxnRoot::Impl::dropAccounts() "homedomain VARCHAR(32) NOT NULL," "thresholds TEXT NOT NULL," "flags INT NOT NULL," + "signers TEXT," "lastmodified INT NOT NULL" ");"; mDatabase.getSession() @@ -548,82 +481,6 @@ LedgerTxnRoot::Impl::dropAccounts() "balance >= 1000000000"; } -static std::vector> -loadHomeDomainsToEncode(Database& db) -{ - std::string accountID, homeDomain; - - std::string sql = "SELECT accountid, homedomain FROM accounts " - "WHERE length(homedomain) > 0"; - - auto prep = db.getPreparedStatement(sql); - auto& st = prep.statement(); - st.exchange(soci::into(accountID)); - st.exchange(soci::into(homeDomain)); - st.define_and_bind(); - st.execute(true); - - std::vector> res; - while (st.got_data()) - { - res.emplace_back(accountID, homeDomain); - st.fetch(); - } - return res; -} - -static void -writeEncodedHomeDomain(Database& db, std::string const& accountID, - std::string const& homeDomain) -{ - std::string encodedHomeDomain = decoder::encode_b64(homeDomain); - - std::string sql = - "UPDATE accounts SET homedomain = :v1 WHERE accountid = :v2"; - - auto prep = db.getPreparedStatement(sql); - auto& st = prep.statement(); - st.exchange(soci::use(encodedHomeDomain)); - st.exchange(soci::use(accountID)); - st.define_and_bind(); - st.execute(true); - if (static_cast(st.get_affected_rows()) != 1) - { - throw std::runtime_error("could not update SQL"); - } -} - -void -LedgerTxnRoot::Impl::encodeHomeDomainsBase64() -{ - throwIfChild(); - mEntryCache.clear(); - mBestOffersCache.clear(); - - CLOG(INFO, "Ledger") << "Loading all home domains from accounts table"; - auto homeDomainsToEncode = loadHomeDomainsToEncode(mDatabase); - - if (!mDatabase.isSqlite()) - { - auto& session = mDatabase.getSession(); - session << "ALTER TABLE accounts ALTER COLUMN homedomain " - "SET DATA TYPE VARCHAR(44)"; - } - - size_t numUpdated = 0; - for (auto const& kv : homeDomainsToEncode) - { - writeEncodedHomeDomain(mDatabase, kv.first, kv.second); - - if ((++numUpdated & 0xfff) == 0xfff || - (numUpdated == homeDomainsToEncode.size())) - { - CLOG(INFO, "Ledger") - << "Wrote home domains for " << numUpdated << " accounts"; - } - } -} - class BulkLoadAccountsOperation : public DatabaseTypeSpecificOperation> { diff --git a/src/ledger/LedgerTxnDataSQL.cpp b/src/ledger/LedgerTxnDataSQL.cpp index 3a5fd79553..27b3d749d8 100644 --- a/src/ledger/LedgerTxnDataSQL.cpp +++ b/src/ledger/LedgerTxnDataSQL.cpp @@ -289,71 +289,6 @@ LedgerTxnRoot::Impl::dropData() ");"; } -static std::vector -loadDataToEncode(Database& db) -{ - std::string accountID, dataName, dataValue; - uint32_t lastModified; - - std::string sql = "SELECT accountid, dataname, datavalue, lastmodified " - "FROM accountdata"; - - auto prep = db.getPreparedStatement(sql); - auto& st = prep.statement(); - st.exchange(soci::into(accountID)); - st.exchange(soci::into(dataName)); - st.exchange(soci::into(dataValue)); - st.exchange(soci::into(lastModified)); - st.define_and_bind(); - st.execute(true); - - std::vector res; - while (st.got_data()) - { - res.emplace_back(); - auto& le = res.back(); - le.data.type(DATA); - - auto& de = le.data.data(); - de.accountID = KeyUtils::fromStrKey(accountID); - de.dataName = dataName; - decoder::decode_b64(dataValue, de.dataValue); - le.lastModifiedLedgerSeq = lastModified; - - st.fetch(); - } - return res; -} - -void -LedgerTxnRoot::Impl::encodeDataNamesBase64() -{ - throwIfChild(); - mEntryCache.clear(); - mBestOffersCache.clear(); - - CLOG(INFO, "Ledger") - << "Loading all data entries from the accountdata table"; - auto dataToEncode = loadDataToEncode(mDatabase); - - // Note: The table must be recreated since dataname is part of the primary - // key, so there could be a collision when updating it - dropData(); - if (!mDatabase.isSqlite()) - { - auto& session = mDatabase.getSession(); - session << "ALTER TABLE accountdata ALTER COLUMN dataname " - "SET DATA TYPE VARCHAR(88)"; - } - if (!dataToEncode.empty()) - { - BulkUpsertDataOperation op(mDatabase, dataToEncode); - mDatabase.doDatabaseTypeSpecificOperation(op); - CLOG(INFO, "Ledger") - << "Wrote " << dataToEncode.size() << " data entries"; - } -} - class BulkLoadDataOperation : public DatabaseTypeSpecificOperation> { diff --git a/src/ledger/LedgerTxnImpl.h b/src/ledger/LedgerTxnImpl.h index 59b4f357da..fe4a834645 100644 --- a/src/ledger/LedgerTxnImpl.h +++ b/src/ledger/LedgerTxnImpl.h @@ -564,30 +564,6 @@ class LedgerTxnRoot::Impl // rollbackChild has the strong exception safety guarantee. void rollbackChild(); - // writeSignersTableIntoAccountsTable has the basic exception safety - // guarantee. If it throws an exception, then - // - the prepared statement cache may be, but is not guaranteed to be, - // modified - void writeSignersTableIntoAccountsTable(); - - // encodedDataNamesBase64 has the basic exception safety guarantee. If it - // throws an exception, then - // - the prepared statement cache may be, but is not guaranteed to be, - // modified - void encodeDataNamesBase64(); - - // encodedHomeDomainsBase64 has the basic exception safety guarantee. If it - // throws an exception, then - // - the prepared statement cache may be, but is not guaranteed to be, - // modified - void encodeHomeDomainsBase64(); - - // writeOffersIntoSimplifiedOffersTable has the basic exception safety - // guarantee. If it throws an exception, then - // - the prepared statement cache may be, but is not guaranteed to be, - // modified - void writeOffersIntoSimplifiedOffersTable(); - // Prefetch some or all of given keys in batches. Note that no prefetching // could occur if the cache is at its fill ratio. Returns number of keys // prefetched. diff --git a/src/ledger/LedgerTxnOfferSQL.cpp b/src/ledger/LedgerTxnOfferSQL.cpp index abf0f70a3f..c4900f0f55 100644 --- a/src/ledger/LedgerTxnOfferSQL.cpp +++ b/src/ledger/LedgerTxnOfferSQL.cpp @@ -552,14 +552,10 @@ LedgerTxnRoot::Impl::dropOffers() mDatabase.getSession() << "CREATE TABLE offers" "(" - "sellerid VARCHAR(56) NOT NULL," - "offerid BIGINT NOT NULL CHECK (offerid >= 0)," - "sellingassettype INT NOT NULL," - "sellingassetcode VARCHAR(12)," - "sellingissuer VARCHAR(56)," - "buyingassettype INT NOT NULL," - "buyingassetcode VARCHAR(12)," - "buyingissuer VARCHAR(56)," + "sellerid VARCHAR(56) NOT NULL," + "offerid BIGINT NOT NULL CHECK (offerid >= 0)," + "sellingasset TEXT NOT NULL," + "buyingasset TEXT NOT NULL," "amount BIGINT NOT NULL CHECK (amount >= 0)," "pricen INT NOT NULL," "priced INT NOT NULL," @@ -568,11 +564,8 @@ LedgerTxnRoot::Impl::dropOffers() "lastmodified INT NOT NULL," "PRIMARY KEY (offerid)" ");"; - mDatabase.getSession() - << "CREATE INDEX sellingissuerindex ON offers (sellingissuer);"; - mDatabase.getSession() - << "CREATE INDEX buyingissuerindex ON offers (buyingissuer);"; - mDatabase.getSession() << "CREATE INDEX priceindex ON offers (price);"; + mDatabase.getSession() << "CREATE INDEX bestofferindex ON offers " + "(sellingasset,buyingasset,price);"; } class BulkLoadOffersOperation @@ -713,133 +706,4 @@ LedgerTxnRoot::Impl::bulkLoadOffers( return {}; } } - -static void -processAssetForSchemaUpgrade(Asset& asset, AssetType assetType, - std::string const& issuerStr, - soci::indicator const& issuerIndicator, - std::string const& assetCode, - soci::indicator const& assetCodeIndicator) -{ - asset.type(assetType); - if (assetType != ASSET_TYPE_NATIVE) - { - if ((assetCodeIndicator != soci::i_ok) || - (issuerIndicator != soci::i_ok)) - { - throw std::runtime_error("bad database state"); - } - - if (assetType == ASSET_TYPE_CREDIT_ALPHANUM12) - { - asset.alphaNum12().issuer = - KeyUtils::fromStrKey(issuerStr); - strToAssetCode(asset.alphaNum12().assetCode, assetCode); - } - else if (assetType == ASSET_TYPE_CREDIT_ALPHANUM4) - { - asset.alphaNum4().issuer = - KeyUtils::fromStrKey(issuerStr); - strToAssetCode(asset.alphaNum4().assetCode, assetCode); - } - else - { - throw std::runtime_error("bad database state"); - } - } -} - -static std::vector -loadAllOffersForSchemaUpgrade(Database& db) -{ - std::vector offers; - - std::string sql = "SELECT sellerid, offerid, " - "sellingassettype, sellingassetcode, sellingissuer, " - "buyingassettype, buyingassetcode, buyingissuer, " - "amount, pricen, priced, flags, lastmodified " - "FROM offers"; - auto prep = db.getPreparedStatement(sql); - - std::string actIDStrKey; - unsigned int sellingAssetType, buyingAssetType; - std::string sellingAssetCode, buyingAssetCode, sellingIssuerStrKey, - buyingIssuerStrKey; - soci::indicator sellingAssetCodeIndicator, buyingAssetCodeIndicator, - sellingIssuerIndicator, buyingIssuerIndicator; - - LedgerEntry le; - le.data.type(OFFER); - OfferEntry& oe = le.data.offer(); - - auto& st = prep.statement(); - st.exchange(soci::into(actIDStrKey)); - st.exchange(soci::into(oe.offerID)); - st.exchange(soci::into(sellingAssetType)); - st.exchange(soci::into(sellingAssetCode, sellingAssetCodeIndicator)); - st.exchange(soci::into(sellingIssuerStrKey, sellingIssuerIndicator)); - st.exchange(soci::into(buyingAssetType)); - st.exchange(soci::into(buyingAssetCode, buyingAssetCodeIndicator)); - st.exchange(soci::into(buyingIssuerStrKey, buyingIssuerIndicator)); - st.exchange(soci::into(oe.amount)); - st.exchange(soci::into(oe.price.n)); - st.exchange(soci::into(oe.price.d)); - st.exchange(soci::into(oe.flags)); - st.exchange(soci::into(le.lastModifiedLedgerSeq)); - st.define_and_bind(); - st.execute(true); - while (st.got_data()) - { - oe.sellerID = KeyUtils::fromStrKey(actIDStrKey); - processAssetForSchemaUpgrade(oe.selling, (AssetType)sellingAssetType, - sellingIssuerStrKey, - sellingIssuerIndicator, sellingAssetCode, - sellingAssetCodeIndicator); - processAssetForSchemaUpgrade(oe.buying, (AssetType)buyingAssetType, - buyingIssuerStrKey, buyingIssuerIndicator, - buyingAssetCode, buyingAssetCodeIndicator); - - offers.emplace_back(le); - st.fetch(); - } - - return offers; -} - -void -LedgerTxnRoot::Impl::writeOffersIntoSimplifiedOffersTable() -{ - throwIfChild(); - mEntryCache.clear(); - mBestOffersCache.clear(); - - CLOG(INFO, "Ledger") << "Loading all offers"; - auto const offers = stellar::loadAllOffersForSchemaUpgrade(mDatabase); - - mDatabase.getSession() << "DROP TABLE IF EXISTS offers"; - mDatabase.getSession() - << "CREATE TABLE offers" - "(" - "sellerid VARCHAR(56) NOT NULL," - "offerid BIGINT NOT NULL CHECK (offerid >= 0)," - "sellingasset TEXT NOT NULL," - "buyingasset TEXT NOT NULL," - "amount BIGINT NOT NULL CHECK (amount >= 0)," - "pricen INT NOT NULL," - "priced INT NOT NULL," - "price DOUBLE PRECISION NOT NULL," - "flags INT NOT NULL," - "lastmodified INT NOT NULL," - "PRIMARY KEY (offerid)" - ");"; - mDatabase.getSession() << "CREATE INDEX bestofferindex ON offers " - "(sellingasset,buyingasset,price);"; - - if (!offers.empty()) - { - BulkUpsertOffersOperation op(mDatabase, offers); - mDatabase.doDatabaseTypeSpecificOperation(op); - CLOG(INFO, "Ledger") << "Wrote " << offers.size() << " offer entries"; - } -} } From b36409a5bf0e6d40d0a5b458adebef29c2b05613 Mon Sep 17 00:00:00 2001 From: MonsieurNicolas Date: Wed, 14 Aug 2019 17:13:25 -0700 Subject: [PATCH 4/4] make it easier to manage min/max schema versions --- src/database/Database.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/database/Database.cpp b/src/database/Database.cpp index a4aa6b59dc..99a78fb6e1 100644 --- a/src/database/Database.cpp +++ b/src/database/Database.cpp @@ -55,6 +55,8 @@ using namespace std; bool Database::gDriversRegistered = false; +// smallest schema version supported +static unsigned long const MIN_SCHEMA_VERSION = 9; static unsigned long const SCHEMA_VERSION = 10; // These should always match our compiled version precisely, since we are @@ -194,15 +196,7 @@ Database::applySchemaUpgrade(unsigned long vers) mApp.getHerderPersistence().createQuorumTrackingTable(mSession); break; default: - if (vers <= 9) - { - throw std::runtime_error( - "Database version is too old, must use at least 10"); - } - else - { - throw std::runtime_error("Unknown DB schema version"); - } + throw std::runtime_error("Unknown DB schema version"); } tx.commit(); } @@ -211,6 +205,14 @@ void Database::upgradeToCurrentSchema() { auto vers = getDBSchemaVersion(); + if (vers < MIN_SCHEMA_VERSION) + { + std::string s = ("DB schema version " + std::to_string(vers) + + " is older than minimum supported schema " + + std::to_string(MIN_SCHEMA_VERSION)); + throw std::runtime_error(s); + } + if (vers > SCHEMA_VERSION) { std::string s = ("DB schema version " + std::to_string(vers) + @@ -374,7 +376,7 @@ Database::initialize() HerderPersistence::dropAll(*this); mApp.getLedgerTxnRoot().dropData(); BanManager::dropAll(*this); - putSchemaVersion(9); + putSchemaVersion(MIN_SCHEMA_VERSION); LOG(INFO) << "* "; LOG(INFO) << "* The database has been initialized";