// Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "impeller/archivist/archive_database.h" #include "third_party/sqlite/sqlite3.h" #include #include #include "impeller/archivist/archive.h" #include "impeller/archivist/archive_class_registration.h" #include "impeller/archivist/archive_statement.h" #include "impeller/base/validation.h" namespace impeller { struct ArchiveDatabase::Handle { explicit Handle(const std::string& filename) { if (::sqlite3_initialize() != SQLITE_OK) { VALIDATION_LOG << "Could not initialize sqlite."; return; } sqlite3* db = nullptr; auto res = ::sqlite3_open(filename.c_str(), &db); if (res != SQLITE_OK || db == nullptr) { return; } handle_ = db; } ~Handle() { if (handle_ == nullptr) { return; } ::sqlite3_close(handle_); } ::sqlite3* Get() const { return handle_; } bool IsValid() const { return handle_ != nullptr; } private: ::sqlite3* handle_ = nullptr; FML_DISALLOW_COPY_AND_ASSIGN(Handle); }; ArchiveDatabase::ArchiveDatabase(const std::string& filename) : handle_(std::make_unique(filename)) { if (!handle_->IsValid()) { handle_.reset(); return; } begin_transaction_stmt_ = std::unique_ptr( new ArchiveStatement(handle_->Get(), "BEGIN TRANSACTION;")); if (!begin_transaction_stmt_->IsValid()) { return; } end_transaction_stmt_ = std::unique_ptr( new ArchiveStatement(handle_->Get(), "END TRANSACTION;")); if (!end_transaction_stmt_->IsValid()) { return; } rollback_transaction_stmt_ = std::unique_ptr( new ArchiveStatement(handle_->Get(), "ROLLBACK TRANSACTION;")); if (!rollback_transaction_stmt_->IsValid()) { return; } } ArchiveDatabase::~ArchiveDatabase() = default; bool ArchiveDatabase::IsValid() const { return handle_ != nullptr; } int64_t ArchiveDatabase::GetLastInsertRowID() { if (!IsValid()) { return 0u; } return ::sqlite3_last_insert_rowid(handle_->Get()); } static inline const ArchiveClassRegistration* RegistrationIfReady( const ArchiveClassRegistration* registration) { if (registration == nullptr) { return nullptr; } return registration->IsValid() ? registration : nullptr; } const ArchiveClassRegistration* ArchiveDatabase::GetRegistrationForDefinition( const ArchiveDef& definition) { auto found = registrations_.find(definition.table_name); if (found != registrations_.end()) { /* * This class has already been registered. */ return RegistrationIfReady(found->second.get()); } /* * Initialize a new class registration for the given class definition. */ auto registration = std::unique_ptr( new ArchiveClassRegistration(*this, definition)); auto res = registrations_.emplace(definition.table_name, std::move(registration)); /* * If the new class registration is ready, return it to the caller. */ return res.second ? RegistrationIfReady((*(res.first)).second.get()) : nullptr; } ArchiveStatement ArchiveDatabase::CreateStatement( const std::string& statementString) const { return ArchiveStatement{handle_ ? handle_->Get() : nullptr, statementString}; } ArchiveTransaction ArchiveDatabase::CreateTransaction( int64_t& transactionCount) { return ArchiveTransaction{transactionCount, // *begin_transaction_stmt_, // *end_transaction_stmt_, // *rollback_transaction_stmt_}; } } // namespace impeller