33 flags = SQLITE_OPEN_READWRITE;
36 flags = SQLITE_OPEN_READONLY;
39 flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
42 flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY;
49 flags |= SQLITE_OPEN_NOMUTEX;
52 flags |= SQLITE_OPEN_FULLMUTEX;
56 sqlite3* connection =
nullptr;
60 if (*(path.data() + path.size()) !=
'\0')
62 temp = std::string(path);
66 error =
Error(sqlite3_open_v2(path.data(), &connection, flags,
nullptr));
76 if (connection ==
nullptr)
77 return Error(SQLITE_MISUSE);
86 return Error(SQLITE_MISUSE);
88 auto path = connection.
GetPath();
92 return Error(SQLITE_MISUSE);
94 return Open(path, mode, threadMode);
100 auto result =
Wrap(connection);
105 return Reopen(*result, mode, threadMode);
109 : mConnection { connection }
116 *
this = std::move(rhs);
123 std::swap(mInDestructor, rhs.mInDestructor);
124 std::swap(mPendingTransactions, rhs.mPendingTransactions);
132 auto error =
Close(
true);
133 assert(!error.IsError());
144 "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?)");
149 auto result = stmt->Prepare(tableName).Run();
151 if (!result.HasRows())
154 for (
auto row : result)
155 return row.GetOr(0,
false);
162 if (mInDestructor || mConnection ==
nullptr)
163 return Error(SQLITE_MISUSE);
165 auto tx = BeginTransaction(
"Connection_Execute");
167 auto first = sql.data();
168 auto last = first + sql.size();
170 while (first != last)
172 const char* next =
nullptr;
173 sqlite3_stmt* statement =
nullptr;
175 int result = sqlite3_prepare_v2 (
176 mConnection, first, last - first, &statement, &next);
178 if (result != SQLITE_OK)
179 return Error(result);
183 if (statement ==
nullptr)
186 auto finalizer =
finally([statement] { sqlite3_finalize(statement); });
188 result = sqlite3_step(statement);
190 if (result != SQLITE_OK && result != SQLITE_DONE && result != SQLITE_ROW)
191 return Error(result);
193 while (result == SQLITE_ROW)
194 result = sqlite3_step(statement);
216 sql = std::string(
"SAVEPOINT ") +
name;
219 sql = std::string(
"RELEASE SAVEPOINT ") +
name;
222 sql = std::string(
"ROLLBACK TO SAVEPOINT ") +
name +
223 std::string(
"; RELEASE SAVEPOINT ") +
name;
227 auto error =
Error(sqlite3_exec(
228 connection.
mConnection, sql.c_str(),
nullptr,
nullptr,
nullptr));
238 [tx = &transaction](
auto lhs) { return lhs == tx; }),
256 return Error(SQLITE_MISUSE);
258 sqlite3_stmt* statement =
nullptr;
260 auto error =
Error(sqlite3_prepare_v2(
261 mConnection, sql.data(), sql.size(), &statement,
nullptr));
270 const std::string& tableName,
const std::string& columnName, int64_t rowId,
271 bool readOnly,
const std::string& databaseName)
const
274 return Error(SQLITE_MISUSE);
276 sqlite3_blob* blob =
nullptr;
278 auto error =
Error(sqlite3_blob_open(
279 mConnection, databaseName.c_str(), tableName.c_str(), columnName.c_str(),
280 rowId, readOnly ? 0 : 1, &blob));
285 return Blob { blob };
288Connection::operator sqlite3*()
const noexcept
293Connection::operator bool() const noexcept
302 std::vector<Transaction*> pendingTransactions;
304 for (
auto* transaction : pendingTransactions)
305 if (
auto err = transaction->Abort(); !force && err.IsError())
308 if (mConnection !=
nullptr && mIsOwned)
309 if(
auto err =
Error(sqlite3_close(mConnection)); err.
IsError())
312 mConnection =
nullptr;
319 auto path = sqlite3_db_filename(mConnection, dbName);
A class representing a BLOB in a SQLite database.
A class representing a connection to a SQLite database.
bool CheckTableExists(std::string_view tableName) const
Returns true if the table exists in the database.
Error Close(bool force) noexcept
Closes the connection.
static Result< Connection > Reopen(const Connection &connection, OpenMode mode=OpenMode::ReadWriteCreate, ThreadMode threadMode=ThreadMode::Serialized)
std::vector< Transaction * > mPendingTransactions
Result< Blob > OpenBlob(const std::string &tableName, const std::string &columnName, int64_t rowId, bool readOnly, const std::string &databaseName="main") const
Opens a BLOB for reading or writing.
static Result< Connection > Open(std::string_view path, OpenMode mode=OpenMode::ReadWriteCreate, ThreadMode threadMode=ThreadMode::Serialized)
Opens a connection to a database.
Error Execute(std::string_view sql) noexcept
Executes the given SQL statement and returns the result.
std::string_view GetPath(const char *dbName={}) const noexcept
Returns the path to the database.
Connection & operator=(const Connection &)=delete
Result< Statement > CreateStatement(std::string_view sql) const
Prepares the given SQL statement for execution.
Transaction BeginTransaction(std::string name)
Starts a new transaction.
bool IsOpen() const noexcept
Returns true if the connection is open.
static Error TransactionHandler(Connection &connection, Transaction::TransactionOperation operation, Transaction &name)
static Result< Connection > Wrap(sqlite3 *connection)
A class representing an error in SQLite.
bool IsError() const noexcept
Returns true if the object represents an error.
A class representing a result of an operation.
A class representing a compiled statement.
A class representing a transaction in SQLite.
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
OpenMode
The mode in which the database should be opened.
ThreadMode
The mode in which the database should be accessed.
Error Initialize() noexcept