LCOV - code coverage report
Current view: top level - irohad/ametsuchi/impl - storage_impl.cpp (source / functions) Hit Total Coverage
Test: coverage_cleared.info Lines: 271 303 89.4 %
Date: 2018-12-05 17:11:35 Functions: 50 55 90.9 %

          Line data    Source code
       1             : /**
       2             :  * Copyright Soramitsu Co., Ltd. All Rights Reserved.
       3             :  * SPDX-License-Identifier: Apache-2.0
       4             :  */
       5             : 
       6             : #include "ametsuchi/impl/storage_impl.hpp"
       7             : 
       8             : #include <soci/postgresql/soci-postgresql.h>
       9             : #include <boost/format.hpp>
      10             : 
      11             : #include "ametsuchi/impl/flat_file/flat_file.hpp"
      12             : #include "ametsuchi/impl/mutable_storage_impl.hpp"
      13             : #include "ametsuchi/impl/peer_query_wsv.hpp"
      14             : #include "ametsuchi/impl/postgres_block_index.hpp"
      15             : #include "ametsuchi/impl/postgres_block_query.hpp"
      16             : #include "ametsuchi/impl/postgres_command_executor.hpp"
      17             : #include "ametsuchi/impl/postgres_query_executor.hpp"
      18             : #include "ametsuchi/impl/postgres_wsv_query.hpp"
      19             : #include "ametsuchi/impl/temporary_wsv_impl.hpp"
      20             : #include "backend/protobuf/permissions.hpp"
      21             : #include "common/bind.hpp"
      22             : #include "common/byteutils.hpp"
      23             : #include "converters/protobuf/json_proto_converter.hpp"
      24             : #include "postgres_ordering_service_persistent_state.hpp"
      25             : 
      26             : namespace {
      27             :   void prepareStatements(soci::connection_pool &connections, size_t pool_size) {
      28        4774 :     for (size_t i = 0; i != pool_size; i++) {
      29        4340 :       soci::session &session = connections.at(i);
      30        4340 :       iroha::ametsuchi::PostgresCommandExecutor::prepareStatements(session);
      31        4340 :     }
      32         434 :   }
      33             : 
      34             :   /**
      35             :    * Verify whether postgres supports prepared transactions
      36             :    */
      37             :   bool preparedTransactionsAvailable(soci::session &sql) {
      38         434 :     int prepared_txs_count = 0;
      39         434 :     sql << "SHOW max_prepared_transactions;", soci::into(prepared_txs_count);
      40         434 :     return prepared_txs_count != 0;
      41           0 :   }
      42             : 
      43             : }  // namespace
      44             : 
      45             : namespace iroha {
      46             :   namespace ametsuchi {
      47             :     const char *kCommandExecutorError = "Cannot create CommandExecutorFactory";
      48             :     const char *kPsqlBroken = "Connection to PostgreSQL broken: %s";
      49             :     const char *kTmpWsv = "TemporaryWsv";
      50             : 
      51             :     ConnectionContext::ConnectionContext(
      52             :         std::unique_ptr<KeyValueStorage> block_store)
      53         434 :         : block_store(std::move(block_store)) {}
      54             : 
      55             :     StorageImpl::StorageImpl(
      56             :         std::string block_store_dir,
      57             :         PostgresOptions postgres_options,
      58             :         std::unique_ptr<KeyValueStorage> block_store,
      59             :         std::shared_ptr<soci::connection_pool> connection,
      60             :         std::shared_ptr<shared_model::interface::CommonObjectsFactory> factory,
      61             :         std::shared_ptr<shared_model::interface::BlockJsonConverter> converter,
      62             :         std::shared_ptr<shared_model::interface::PermissionToString>
      63             :             perm_converter,
      64             :         size_t pool_size,
      65             :         bool enable_prepared_blocks)
      66         434 :         : block_store_dir_(std::move(block_store_dir)),
      67         434 :           postgres_options_(std::move(postgres_options)),
      68         434 :           block_store_(std::move(block_store)),
      69         434 :           connection_(std::move(connection)),
      70         434 :           factory_(std::move(factory)),
      71         434 :           converter_(std::move(converter)),
      72         434 :           perm_converter_(std::move(perm_converter)),
      73         434 :           log_(logger::log("StorageImpl")),
      74         434 :           pool_size_(pool_size),
      75         434 :           prepared_blocks_enabled_(enable_prepared_blocks),
      76         434 :           block_is_prepared(false) {
      77         434 :       prepared_block_name_ =
      78         434 :           "prepared_block" + postgres_options_.dbname().value_or("");
      79         434 :       soci::session sql(*connection_);
      80             :       // rollback current prepared transaction
      81             :       // if there exists any since last session
      82             :       if (prepared_blocks_enabled_) {
      83         434 :         rollbackPrepared(sql);
      84         434 :       }
      85         434 :       sql << init_;
      86         434 :       prepareStatements(*connection_, pool_size_);
      87         434 :     }
      88             : 
      89             :     expected::Result<std::unique_ptr<TemporaryWsv>, std::string>
      90             :     StorageImpl::createTemporaryWsv() {
      91         712 :       std::shared_lock<std::shared_timed_mutex> lock(drop_mutex);
      92             :       if (connection_ == nullptr) {
      93           0 :         return expected::makeError("Connection was closed");
      94             :       }
      95         712 :       auto sql = std::make_unique<soci::session>(*connection_);
      96             : 
      97         712 :       return expected::makeValue<std::unique_ptr<TemporaryWsv>>(
      98         712 :           std::make_unique<TemporaryWsvImpl>(
      99         712 :               std::move(sql), factory_, perm_converter_));
     100         712 :     }
     101             : 
     102             :     expected::Result<std::unique_ptr<MutableStorage>, std::string>
     103             :     StorageImpl::createMutableStorage() {
     104         543 :       boost::optional<shared_model::interface::types::HashType> top_hash;
     105             : 
     106         543 :       std::shared_lock<std::shared_timed_mutex> lock(drop_mutex);
     107         543 :       if (connection_ == nullptr) {
     108           4 :         return expected::makeError("Connection was closed");
     109             :       }
     110             : 
     111         539 :       auto sql = std::make_unique<soci::session>(*connection_);
     112             :       // if we create mutable storage, then we intend to mutate wsv
     113             :       // this means that any state prepared before that moment is not needed
     114             :       // and must be removed to preventy locking
     115         539 :       if (block_is_prepared) {
     116           2 :         rollbackPrepared(*sql);
     117           2 :       }
     118         539 :       auto block_result = getBlockQuery()->getTopBlock();
     119         539 :       return expected::makeValue<std::unique_ptr<MutableStorage>>(
     120         539 :           std::make_unique<MutableStorageImpl>(
     121         539 :               block_result.match(
     122             :                   [](expected::Value<
     123             :                       std::shared_ptr<shared_model::interface::Block>> &block) {
     124          22 :                     return block.value->hash();
     125             :                   },
     126             :                   [](expected::Error<std::string> &) {
     127         517 :                     return shared_model::interface::types::HashType("");
     128           0 :                   }),
     129         539 :               std::make_shared<PostgresCommandExecutor>(*sql, perm_converter_),
     130         539 :               std::move(sql),
     131         539 :               factory_));
     132         543 :     }
     133             : 
     134             :     boost::optional<std::shared_ptr<PeerQuery>> StorageImpl::createPeerQuery()
     135             :         const {
     136        1919 :       auto wsv = getWsvQuery();
     137        1919 :       if (not wsv) {
     138           0 :         return boost::none;
     139             :       }
     140        1919 :       return boost::make_optional<std::shared_ptr<PeerQuery>>(
     141        1919 :           std::make_shared<PeerQueryWsv>(wsv));
     142        1919 :     }
     143             : 
     144             :     boost::optional<std::shared_ptr<BlockQuery>> StorageImpl::createBlockQuery()
     145             :         const {
     146        1662 :       auto block_query = getBlockQuery();
     147        1662 :       if (not block_query) {
     148           1 :         return boost::none;
     149             :       }
     150        1661 :       return boost::make_optional(block_query);
     151        1662 :     }
     152             : 
     153             :     boost::optional<std::shared_ptr<OrderingServicePersistentState>>
     154             :     StorageImpl::createOsPersistentState() const {
     155        1205 :       log_->info("create ordering service persistent state");
     156        1205 :       std::shared_lock<std::shared_timed_mutex> lock(drop_mutex);
     157        1205 :       if (not connection_) {
     158           1 :         log_->info("connection to database is not initialised");
     159           1 :         return boost::none;
     160             :       }
     161        1204 :       return boost::make_optional<
     162             :           std::shared_ptr<OrderingServicePersistentState>>(
     163        1204 :           std::make_shared<PostgresOrderingServicePersistentState>(
     164        1204 :               std::make_unique<soci::session>(*connection_)));
     165        1205 :     }
     166             : 
     167             :     boost::optional<std::shared_ptr<QueryExecutor>>
     168             :     StorageImpl::createQueryExecutor(
     169             :         std::shared_ptr<PendingTransactionStorage> pending_txs_storage,
     170             :         std::shared_ptr<shared_model::interface::QueryResponseFactory>
     171             :             response_factory) const {
     172         171 :       std::shared_lock<std::shared_timed_mutex> lock(drop_mutex);
     173         171 :       if (not connection_) {
     174           0 :         log_->info("connection to database is not initialised");
     175           0 :         return boost::none;
     176             :       }
     177         171 :       return boost::make_optional<std::shared_ptr<QueryExecutor>>(
     178         171 :           std::make_shared<PostgresQueryExecutor>(
     179         170 :               std::make_unique<soci::session>(*connection_),
     180         171 :               *block_store_,
     181         170 :               std::move(pending_txs_storage),
     182         170 :               converter_,
     183         170 :               std::move(response_factory),
     184         170 :               perm_converter_));
     185         171 :     }
     186             : 
     187             :     bool StorageImpl::insertBlock(const shared_model::interface::Block &block) {
     188         245 :       log_->info("create mutable storage");
     189         245 :       auto storageResult = createMutableStorage();
     190         245 :       bool inserted = false;
     191         245 :       storageResult.match(
     192             :           [&](expected::Value<std::unique_ptr<ametsuchi::MutableStorage>>
     193             :                   &storage) {
     194         245 :             inserted = storage.value->apply(block);
     195         245 :             log_->info("block inserted: {}", inserted);
     196         245 :             commit(std::move(storage.value));
     197         245 :           },
     198             :           [&](expected::Error<std::string> &error) {
     199           0 :             log_->error(error.error);
     200           0 :           });
     201             : 
     202         245 :       return inserted;
     203         245 :     }
     204             : 
     205             :     bool StorageImpl::insertBlocks(
     206             :         const std::vector<std::shared_ptr<shared_model::interface::Block>>
     207             :             &blocks) {
     208         246 :       log_->info("create mutable storage");
     209         246 :       bool inserted = true;
     210         246 :       auto storageResult = createMutableStorage();
     211         246 :       storageResult.match(
     212             :           [&](iroha::expected::Value<std::unique_ptr<MutableStorage>>
     213             :                   &mutableStorage) {
     214             :             std::for_each(blocks.begin(), blocks.end(), [&](auto block) {
     215         247 :               inserted &= mutableStorage.value->apply(*block);
     216         247 :             });
     217         246 :             commit(std::move(mutableStorage.value));
     218         246 :           },
     219             :           [&](iroha::expected::Error<std::string> &error) {
     220           0 :             log_->error(error.error);
     221           0 :             inserted = false;
     222           0 :           });
     223             : 
     224         246 :       log_->info("insert blocks finished");
     225         246 :       return inserted;
     226         246 :     }
     227             : 
     228             :     void StorageImpl::reset() {
     229         490 :       log_->info("drop wsv records from db tables");
     230         490 :       soci::session sql(*connection_);
     231         490 :       sql << reset_;
     232             : 
     233         490 :       log_->info("drop blocks from disk");
     234         490 :       block_store_->dropAll();
     235         490 :     }
     236             : 
     237             :     void StorageImpl::dropStorage() {
     238         441 :       log_->info("drop storage");
     239         441 :       if (connection_ == nullptr) {
     240           9 :         log_->warn("Tried to drop storage without active connection");
     241           9 :         return;
     242             :       }
     243             : 
     244         432 :       if (auto dbname = postgres_options_.dbname()) {
     245         432 :         auto &db = dbname.value();
     246         432 :         std::unique_lock<std::shared_timed_mutex> lock(drop_mutex);
     247         432 :         log_->info("Drop database {}", db);
     248         432 :         freeConnections();
     249         432 :         soci::session sql(soci::postgresql,
     250         432 :                           postgres_options_.optionsStringWithoutDbName());
     251             :         // perform dropping
     252         432 :         sql << "DROP DATABASE " + db;
     253         432 :       } else {
     254           0 :         soci::session(*connection_) << drop_;
     255             :       }
     256             : 
     257             :       // erase blocks
     258         432 :       log_->info("drop block store");
     259         432 :       block_store_->dropAll();
     260         441 :     }
     261             : 
     262             :     void StorageImpl::freeConnections() {
     263        1111 :       if (connection_ == nullptr) {
     264         677 :         log_->warn("Tried to free connections without active connection");
     265         677 :         return;
     266             :       }
     267             :       // rollback possible prepared transaction
     268         434 :       if (block_is_prepared) {
     269           5 :         soci::session sql(*connection_);
     270           5 :         rollbackPrepared(sql);
     271           5 :       }
     272         434 :       std::vector<std::shared_ptr<soci::session>> connections;
     273        4774 :       for (size_t i = 0; i < pool_size_; i++) {
     274        4340 :         connections.push_back(std::make_shared<soci::session>(*connection_));
     275        4340 :         connections[i]->close();
     276        4340 :         log_->debug("Closed connection {}", i);
     277        4340 :       }
     278         434 :       connections.clear();
     279         434 :       connection_.reset();
     280        1111 :     }
     281             : 
     282             :     expected::Result<bool, std::string> StorageImpl::createDatabaseIfNotExist(
     283             :         const std::string &dbname,
     284             :         const std::string &options_str_without_dbname) {
     285             :       try {
     286         435 :         soci::session sql(soci::postgresql, options_str_without_dbname);
     287             : 
     288             :         int size;
     289         434 :         std::string name = dbname;
     290             : 
     291         434 :         sql << "SELECT count(datname) FROM pg_catalog.pg_database WHERE "
     292         434 :                "datname = :dbname",
     293         434 :             soci::into(size), soci::use(name);
     294             : 
     295         434 :         if (size == 0) {
     296         432 :           std::string query = "CREATE DATABASE ";
     297         432 :           query += dbname;
     298         432 :           sql << query;
     299         432 :           return expected::makeValue(true);
     300         432 :         }
     301           2 :         return expected::makeValue(false);
     302         434 :       } catch (std::exception &e) {
     303           1 :         return expected::makeError<std::string>(
     304           1 :             std::string("Connection to PostgreSQL broken: ") + e.what());
     305           1 :       }
     306         435 :     }
     307             : 
     308             :     expected::Result<ConnectionContext, std::string>
     309             :     StorageImpl::initConnections(std::string block_store_dir) {
     310         434 :       auto log_ = logger::log("StorageImpl:initConnection");
     311         434 :       log_->info("Start storage creation");
     312             : 
     313         434 :       auto block_store = FlatFile::create(block_store_dir);
     314         434 :       if (not block_store) {
     315           0 :         return expected::makeError(
     316           0 :             (boost::format("Cannot create block store in %s") % block_store_dir)
     317           0 :                 .str());
     318             :       }
     319         434 :       log_->info("block store created");
     320             : 
     321         434 :       return expected::makeValue(ConnectionContext(std::move(*block_store)));
     322         434 :     }
     323             : 
     324             :     expected::Result<std::shared_ptr<soci::connection_pool>, std::string>
     325             :     StorageImpl::initPostgresConnection(std::string &options_str,
     326             :                                         size_t pool_size) {
     327         434 :       auto pool = std::make_shared<soci::connection_pool>(pool_size);
     328             : 
     329        4774 :       for (size_t i = 0; i != pool_size; i++) {
     330        4340 :         soci::session &session = pool->at(i);
     331        4340 :         session.open(soci::postgresql, options_str);
     332        4340 :       }
     333         434 :       return expected::makeValue(pool);
     334         434 :     };
     335             : 
     336             :     expected::Result<std::shared_ptr<StorageImpl>, std::string>
     337             :     StorageImpl::create(
     338             :         std::string block_store_dir,
     339             :         std::string postgres_options,
     340             :         std::shared_ptr<shared_model::interface::CommonObjectsFactory> factory,
     341             :         std::shared_ptr<shared_model::interface::BlockJsonConverter> converter,
     342             :         std::shared_ptr<shared_model::interface::PermissionToString>
     343             :             perm_converter,
     344             :         size_t pool_size) {
     345         435 :       boost::optional<std::string> string_res = boost::none;
     346             : 
     347         435 :       PostgresOptions options(postgres_options);
     348             : 
     349             :       // create database if
     350             :       options.dbname() | [&options, &string_res](const std::string &dbname) {
     351         435 :         createDatabaseIfNotExist(dbname, options.optionsStringWithoutDbName())
     352             :             .match([](expected::Value<bool> &val) {},
     353             :                    [&string_res](expected::Error<std::string> &error) {
     354           1 :                      string_res = error.error;
     355           1 :                    });
     356         435 :       };
     357             : 
     358         435 :       if (string_res) {
     359           1 :         return expected::makeError(string_res.value());
     360             :       }
     361             : 
     362         434 :       auto ctx_result = initConnections(block_store_dir);
     363         434 :       auto db_result = initPostgresConnection(postgres_options, pool_size);
     364         434 :       expected::Result<std::shared_ptr<StorageImpl>, std::string> storage;
     365         434 :       ctx_result.match(
     366             :           [&](expected::Value<ConnectionContext> &ctx) {
     367         434 :             db_result.match(
     368             :                 [&](expected::Value<std::shared_ptr<soci::connection_pool>>
     369             :                         &connection) {
     370         434 :                   soci::session sql(*connection.value);
     371         434 :                   bool enable_prepared_transactions =
     372         434 :                       preparedTransactionsAvailable(sql);
     373         434 :                   storage = expected::makeValue(std::shared_ptr<StorageImpl>(
     374         434 :                       new StorageImpl(block_store_dir,
     375         434 :                                       options,
     376         434 :                                       std::move(ctx.value.block_store),
     377         434 :                                       connection.value,
     378         434 :                                       factory,
     379         434 :                                       converter,
     380         434 :                                       perm_converter,
     381         434 :                                       pool_size,
     382         434 :                                       enable_prepared_transactions)));
     383         434 :                 },
     384             :                 [&](expected::Error<std::string> &error) { storage = error; });
     385         434 :           },
     386             :           [&](expected::Error<std::string> &error) { storage = error; });
     387         434 :       return storage;
     388         435 :     }
     389             : 
     390             :     void StorageImpl::commit(std::unique_ptr<MutableStorage> mutableStorage) {
     391         535 :       auto storage_ptr = std::move(mutableStorage);  // get ownership of storage
     392         535 :       auto storage = static_cast<MutableStorageImpl *>(storage_ptr.get());
     393        1071 :       for (const auto &block : storage->block_store_) {
     394         536 :         storeBlock(*block.second);
     395             :       }
     396         535 :       *(storage->sql_) << "COMMIT";
     397         535 :       storage->committed = true;
     398         535 :     }
     399             : 
     400             :     bool StorageImpl::commitPrepared(
     401             :         const shared_model::interface::Block &block) {
     402         710 :       if (not prepared_blocks_enabled_) {
     403           0 :         log_->warn("prepared blocks are not enabled");
     404           0 :         return false;
     405             :       }
     406             : 
     407         710 :       if (not block_is_prepared) {
     408           2 :         log_->info("there are no prepared blocks");
     409           2 :         return false;
     410             :       }
     411         708 :       log_->info("applying prepared block");
     412             : 
     413             :       try {
     414         708 :         std::shared_lock<std::shared_timed_mutex> lock(drop_mutex);
     415         708 :         if (not connection_) {
     416           3 :           log_->info("connection to database is not initialised");
     417           3 :           return false;
     418             :         }
     419         705 :         soci::session sql(*connection_);
     420         705 :         sql << "COMMIT PREPARED '" + prepared_block_name_ + "';";
     421         705 :         PostgresBlockIndex block_index(sql);
     422         705 :         block_index.index(block);
     423         705 :         block_is_prepared = false;
     424        1415 :       } catch (const std::exception &e) {
     425           0 :         log_->warn("failed to apply prepared block {}: {}",
     426           0 :                    block.hash().hex(),
     427           0 :                    e.what());
     428           0 :         return false;
     429           0 :       }
     430             : 
     431         705 :       return storeBlock(block);
     432         710 :     }
     433             : 
     434             :     std::shared_ptr<WsvQuery> StorageImpl::getWsvQuery() const {
     435        2065 :       std::shared_lock<std::shared_timed_mutex> lock(drop_mutex);
     436        2065 :       if (not connection_) {
     437           0 :         log_->info("connection to database is not initialised");
     438           0 :         return nullptr;
     439             :       }
     440        2065 :       return std::make_shared<PostgresWsvQuery>(
     441        2065 :           std::make_unique<soci::session>(*connection_), factory_);
     442        2065 :     }
     443             : 
     444             :     std::shared_ptr<BlockQuery> StorageImpl::getBlockQuery() const {
     445        2452 :       std::shared_lock<std::shared_timed_mutex> lock(drop_mutex);
     446        2452 :       if (not connection_) {
     447           2 :         log_->info("connection to database is not initialised");
     448           2 :         return nullptr;
     449             :       }
     450        2450 :       return std::make_shared<PostgresBlockQuery>(
     451        2450 :           std::make_unique<soci::session>(*connection_),
     452        2450 :           *block_store_,
     453        2450 :           converter_);
     454        2452 :     }
     455             : 
     456             :     rxcpp::observable<std::shared_ptr<shared_model::interface::Block>>
     457             :     StorageImpl::on_commit() {
     458         247 :       return notifier_.get_observable();
     459           0 :     }
     460             : 
     461             :     void StorageImpl::prepareBlock(std::unique_ptr<TemporaryWsv> wsv) {
     462         712 :       auto &wsv_impl = static_cast<TemporaryWsvImpl &>(*wsv);
     463         712 :       if (not prepared_blocks_enabled_) {
     464           0 :         log_->warn("prepared block are not enabled");
     465           0 :         return;
     466             :       }
     467         712 :       if (not block_is_prepared) {
     468         712 :         soci::session &sql = *wsv_impl.sql_;
     469             :         try {
     470         712 :           sql << "PREPARE TRANSACTION '" + prepared_block_name_ + "';";
     471         712 :           block_is_prepared = true;
     472         712 :         } catch (const std::exception &e) {
     473           0 :           log_->warn("failed to prepare state: {}", e.what());
     474           0 :         }
     475             : 
     476         712 :         log_->info("state prepared successfully");
     477         712 :       }
     478         712 :     }
     479             : 
     480             :     StorageImpl::~StorageImpl() {
     481         434 :       freeConnections();
     482         434 :     }
     483             : 
     484             :     void StorageImpl::rollbackPrepared(soci::session &sql) {
     485             :       try {
     486         441 :         sql << "ROLLBACK PREPARED '" + prepared_block_name_ + "';";
     487           7 :         block_is_prepared = false;
     488         434 :       } catch (const std::exception &e) {
     489         434 :         log_->info(e.what());
     490         434 :       }
     491         441 :     }
     492             : 
     493             :     bool StorageImpl::storeBlock(const shared_model::interface::Block &block) {
     494        1241 :       auto json_result = converter_->serialize(block);
     495        1241 :       return json_result.match(
     496             :           [this, &block](const expected::Value<std::string> &v) {
     497        1241 :             block_store_->add(block.height(), stringToBytes(v.value));
     498        1241 :             notifier_.get_subscriber().on_next(clone(block));
     499        1241 :             return true;
     500           0 :           },
     501             :           [this](const expected::Error<std::string> &e) {
     502           0 :             log_->error(e.error);
     503           0 :             return false;
     504             :           });
     505        1241 :     }
     506             : 
     507             :     const std::string &StorageImpl::drop_ = R"(
     508             : DROP TABLE IF EXISTS account_has_signatory;
     509             : DROP TABLE IF EXISTS account_has_asset;
     510             : DROP TABLE IF EXISTS role_has_permissions CASCADE;
     511             : DROP TABLE IF EXISTS account_has_roles;
     512             : DROP TABLE IF EXISTS account_has_grantable_permissions CASCADE;
     513             : DROP TABLE IF EXISTS account;
     514             : DROP TABLE IF EXISTS asset;
     515             : DROP TABLE IF EXISTS domain;
     516             : DROP TABLE IF EXISTS signatory;
     517             : DROP TABLE IF EXISTS peer;
     518             : DROP TABLE IF EXISTS role;
     519             : DROP TABLE IF EXISTS height_by_hash;
     520             : DROP TABLE IF EXISTS tx_status_by_hash;
     521             : DROP TABLE IF EXISTS height_by_account_set;
     522             : DROP TABLE IF EXISTS index_by_creator_height;
     523             : DROP TABLE IF EXISTS index_by_id_height_asset;
     524             : )";
     525             : 
     526             :     const std::string &StorageImpl::reset_ = R"(
     527             : DELETE FROM account_has_signatory;
     528             : DELETE FROM account_has_asset;
     529             : DELETE FROM role_has_permissions CASCADE;
     530             : DELETE FROM account_has_roles;
     531             : DELETE FROM account_has_grantable_permissions CASCADE;
     532             : DELETE FROM account;
     533             : DELETE FROM asset;
     534             : DELETE FROM domain;
     535             : DELETE FROM signatory;
     536             : DELETE FROM peer;
     537             : DELETE FROM role;
     538             : DELETE FROM height_by_hash;
     539             : DELETE FROM tx_status_by_hash;
     540             : DELETE FROM height_by_account_set;
     541             : DELETE FROM index_by_creator_height;
     542             : DELETE FROM index_by_id_height_asset;
     543             : )";
     544             : 
     545             :     const std::string &StorageImpl::init_ =
     546          43 :         R"(
     547             : CREATE TABLE IF NOT EXISTS role (
     548             :     role_id character varying(32),
     549             :     PRIMARY KEY (role_id)
     550             : );
     551             : CREATE TABLE IF NOT EXISTS domain (
     552             :     domain_id character varying(255),
     553             :     default_role character varying(32) NOT NULL REFERENCES role(role_id),
     554             :     PRIMARY KEY (domain_id)
     555             : );
     556             : CREATE TABLE IF NOT EXISTS signatory (
     557             :     public_key varchar NOT NULL,
     558             :     PRIMARY KEY (public_key)
     559             : );
     560             : CREATE TABLE IF NOT EXISTS account (
     561             :     account_id character varying(288),
     562             :     domain_id character varying(255) NOT NULL REFERENCES domain,
     563             :     quorum int NOT NULL,
     564             :     data JSONB,
     565             :     PRIMARY KEY (account_id)
     566             : );
     567             : CREATE TABLE IF NOT EXISTS account_has_signatory (
     568             :     account_id character varying(288) NOT NULL REFERENCES account,
     569             :     public_key varchar NOT NULL REFERENCES signatory,
     570             :     PRIMARY KEY (account_id, public_key)
     571             : );
     572             : CREATE TABLE IF NOT EXISTS peer (
     573             :     public_key varchar NOT NULL,
     574             :     address character varying(261) NOT NULL UNIQUE,
     575             :     PRIMARY KEY (public_key)
     576             : );
     577             : CREATE TABLE IF NOT EXISTS asset (
     578             :     asset_id character varying(288),
     579             :     domain_id character varying(255) NOT NULL REFERENCES domain,
     580             :     precision int NOT NULL,
     581             :     data json,
     582             :     PRIMARY KEY (asset_id)
     583             : );
     584             : CREATE TABLE IF NOT EXISTS account_has_asset (
     585             :     account_id character varying(288) NOT NULL REFERENCES account,
     586             :     asset_id character varying(288) NOT NULL REFERENCES asset,
     587             :     amount decimal NOT NULL,
     588             :     PRIMARY KEY (account_id, asset_id)
     589             : );
     590             : CREATE TABLE IF NOT EXISTS role_has_permissions (
     591             :     role_id character varying(32) NOT NULL REFERENCES role,
     592             :     permission bit()"
     593          43 :         + std::to_string(shared_model::interface::RolePermissionSet::size())
     594          43 :         + R"() NOT NULL,
     595             :     PRIMARY KEY (role_id)
     596             : );
     597             : CREATE TABLE IF NOT EXISTS account_has_roles (
     598             :     account_id character varying(288) NOT NULL REFERENCES account,
     599             :     role_id character varying(32) NOT NULL REFERENCES role,
     600             :     PRIMARY KEY (account_id, role_id)
     601             : );
     602             : CREATE TABLE IF NOT EXISTS account_has_grantable_permissions (
     603             :     permittee_account_id character varying(288) NOT NULL REFERENCES account,
     604             :     account_id character varying(288) NOT NULL REFERENCES account,
     605             :     permission bit()"
     606          43 :         + std::to_string(
     607          43 :               shared_model::interface::GrantablePermissionSet::size())
     608          43 :         + R"() NOT NULL,
     609             :     PRIMARY KEY (permittee_account_id, account_id)
     610             : );
     611             : CREATE TABLE IF NOT EXISTS height_by_hash (
     612             :     hash varchar,
     613             :     height text
     614             : );
     615             : 
     616             : CREATE TABLE IF NOT EXISTS tx_status_by_hash (
     617             :     hash varchar,
     618             :     status boolean
     619             : );
     620             : 
     621             : CREATE TABLE IF NOT EXISTS height_by_account_set (
     622             :     account_id text,
     623             :     height text
     624             : );
     625             : CREATE TABLE IF NOT EXISTS index_by_creator_height (
     626             :     id serial,
     627             :     creator_id text,
     628             :     height text,
     629             :     index text
     630             : );
     631             : CREATE TABLE IF NOT EXISTS index_by_id_height_asset (
     632             :     id text,
     633             :     height text,
     634             :     asset_id text,
     635             :     index text
     636             : );
     637             : )";
     638             :   }  // namespace ametsuchi
     639             : }  // namespace iroha

Generated by: LCOV version 1.13