1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2016 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of Qt Creator. 7 ** 8 ** Commercial License Usage 9 ** Licensees holding valid commercial Qt licenses may use this file in 10 ** accordance with the commercial license agreement provided with the 11 ** Software or, alternatively, in accordance with the terms contained in 12 ** a written agreement between you and The Qt Company. For licensing terms 13 ** and conditions see https://www.qt.io/terms-conditions. For further 14 ** information use the contact form at https://www.qt.io/contact-us. 15 ** 16 ** GNU General Public License Usage 17 ** Alternatively, this file may be used under the terms of the GNU 18 ** General Public License version 3 as published by the Free Software 19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT 20 ** included in the packaging of this file. Please review the following 21 ** information to ensure the GNU General Public License requirements will 22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html. 23 ** 24 ****************************************************************************/ 25 26 #pragma once 27 28 #include "sqlitedatabasebackend.h" 29 #include "sqlitedatabaseinterface.h" 30 #include "sqliteglobal.h" 31 #include "sqlitereadstatement.h" 32 #include "sqlitereadwritestatement.h" 33 #include "sqlitesessionchangeset.h" 34 #include "sqlitetable.h" 35 #include "sqlitetransaction.h" 36 #include "sqlitewritestatement.h" 37 38 #include <utils/smallstring.h> 39 40 #include <chrono> 41 #include <mutex> 42 #include <vector> 43 44 namespace Sqlite { 45 46 using namespace std::chrono_literals; 47 48 template<int ResultCount> 49 class ReadStatement; 50 class WriteStatement; 51 template<int ResultCount> 52 class ReadWriteStatement; 53 54 class SQLITE_EXPORT Database final : public TransactionInterface, public DatabaseInterface 55 { 56 template <typename Database> 57 friend class Statement; 58 friend class Backend; 59 60 public: 61 using MutexType = std::mutex; 62 template<int ResultCount> 63 using ReadStatement = Sqlite::ReadStatement<ResultCount>; 64 using WriteStatement = Sqlite::WriteStatement; 65 template<int ResultCount = 0> 66 using ReadWriteStatement = Sqlite::ReadWriteStatement<ResultCount>; 67 using BusyHandler = DatabaseBackend::BusyHandler; 68 69 Database(); 70 Database(Utils::PathString databaseFilePath, 71 JournalMode journalMode = JournalMode::Wal, 72 LockingMode lockingMode = LockingMode::Default); 73 Database(Utils::PathString databaseFilePath, 74 std::chrono::milliseconds busyTimeout, 75 JournalMode journalMode = JournalMode::Wal, 76 LockingMode lockingMode = LockingMode::Default); 77 ~Database(); 78 79 Database(const Database &) = delete; 80 Database &operator=(const Database &) = delete; 81 82 static void activateLogging(); 83 84 void open(LockingMode lockingMode = LockingMode::Default); 85 void open(Utils::PathString &&databaseFilePath, LockingMode lockingMode = LockingMode::Default); 86 void close(); 87 88 bool isInitialized() const; 89 void setIsInitialized(bool isInitialized); 90 91 bool isOpen() const; 92 93 void setDatabaseFilePath(Utils::PathString databaseFilePath); 94 const Utils::PathString &databaseFilePath() const; 95 96 void setJournalMode(JournalMode journalMode); 97 JournalMode journalMode() const; 98 99 LockingMode lockingMode() const; 100 101 void setOpenMode(OpenMode openMode); 102 OpenMode openMode() const; 103 104 void execute(Utils::SmallStringView sqlStatement) override; 105 106 DatabaseBackend &backend(); 107 lastInsertedRowId()108 int64_t lastInsertedRowId() const 109 { 110 return m_databaseBackend.lastInsertedRowId(); 111 } 112 setLastInsertedRowId(int64_t rowId)113 void setLastInsertedRowId(int64_t rowId) 114 { 115 m_databaseBackend.setLastInsertedRowId(rowId); 116 } 117 changesCount()118 int changesCount() 119 { 120 return m_databaseBackend.changesCount(); 121 } 122 totalChangesCount()123 int totalChangesCount() { return m_databaseBackend.totalChangesCount(); } 124 walCheckpointFull()125 void walCheckpointFull() override 126 { 127 std::lock_guard<std::mutex> lock{m_databaseMutex}; 128 m_databaseBackend.walCheckpointFull(); 129 } 130 setUpdateHook(void * object,void (* callback)(void * object,int,char const * database,char const *,long long rowId))131 void setUpdateHook(void *object, 132 void (*callback)(void *object, 133 int, 134 char const *database, 135 char const *, 136 long long rowId)) override 137 { 138 m_databaseBackend.setUpdateHook(object, callback); 139 } 140 resetUpdateHook()141 void resetUpdateHook() override { m_databaseBackend.resetUpdateHook(); } 142 143 void setAttachedTables(const Utils::SmallStringVector &tables) override; 144 void applyAndUpdateSessions() override; 145 setBusyHandler(BusyHandler busyHandler)146 void setBusyHandler(BusyHandler busyHandler) 147 { 148 m_databaseBackend.setBusyHandler(std::move(busyHandler)); 149 } 150 151 SessionChangeSets changeSets() const; 152 isLocked()153 bool isLocked() const 154 { 155 #ifdef UNIT_TESTS 156 return m_isLocked; 157 #else 158 return true; 159 #endif 160 } 161 void lock() override; 162 void unlock() override; 163 164 private: 165 void deferredBegin() override; 166 void immediateBegin() override; 167 void exclusiveBegin() override; 168 void commit() override; 169 void rollback() override; 170 void immediateSessionBegin() override; 171 void sessionCommit() override; 172 void sessionRollback() override; 173 174 void initializeTables(); 175 void registerTransactionStatements(); 176 void deleteTransactionStatements(); databaseMutex()177 std::mutex &databaseMutex() { return m_databaseMutex; } 178 179 class Statements; 180 181 private: 182 Utils::PathString m_databaseFilePath; 183 DatabaseBackend m_databaseBackend; 184 std::mutex m_databaseMutex; 185 std::unique_ptr<Statements> m_statements; 186 std::chrono::milliseconds m_busyTimeout; 187 JournalMode m_journalMode = JournalMode::Wal; 188 OpenMode m_openMode = OpenMode::ReadWrite; 189 bool m_isOpen = false; 190 bool m_isInitialized = false; 191 bool m_isLocked = false; 192 }; 193 194 } // namespace Sqlite 195