File indexing completed on 2024-12-08 12:44:36

0001 // SPDX-FileCopyrightText: 2022 Jonah BrĂ¼chert <jbb@kaidan.im
0002 //
0003 // SPDX-License-Identifier: BSD-2-Clause
0004 
0005 /*
0006  * This example demonstrates how to use transactions with FutureSQL
0007  * For explanations of the general concepts, see the hello-world example,
0008  * which is very similar (except it doesn't use transactions, of course),
0009  * but it contains more comments.
0010  */
0011 
0012 // Qt
0013 #include <QCoreApplication>
0014 #include <QTimer>
0015 
0016 // QCoro
0017 #include <QCoro/QCoroTask>
0018 #include <QCoro/QCoroFuture>
0019 
0020 // FutureSQL
0021 #include <ThreadedDatabase>
0022 
0023 // STL
0024 #include <tuple>
0025 
0026 // Why is this function not part of the library, I hear you ask.
0027 // Currently, FutureSQL should not hard-depend on QCoro,
0028 // even though with Qt5, QCoro is the only way to use it without
0029 // hand-crafting helper functions to deal with QFutures.
0030 template <typename Func>
0031 QCoro::Task<> transaction(std::unique_ptr<ThreadedDatabase> &database, Func queryFunc) {
0032     co_await database->execute(QStringLiteral("BEGIN TRANSACTION"));
0033     co_await queryFunc();
0034     co_await database->execute(QStringLiteral("COMMIT"));
0035 }
0036 
0037 struct HelloWorld {
0038     using ColumnTypes = std::tuple<int, QString>;
0039 
0040     // attributes
0041     int id;
0042     QString data;
0043 };
0044 
0045 QCoro::Task<> databaseExample() {
0046     // This object contains the database configuration,
0047     // in this case just the path to the SQLite file, and the database type (SQLite).
0048     DatabaseConfiguration config;
0049     config.setDatabaseName(QStringLiteral("database.sqlite"));
0050     config.setType(DatabaseType::SQLite);
0051 
0052     // Here we open the database file, and get a handle to the database.
0053     auto database = ThreadedDatabase::establishConnection(config);
0054 
0055     // Run the following steps in a transaction
0056     co_await transaction(database, [&database]() -> QCoro::Task<> {
0057         // Create the table
0058         co_await database->execute(QStringLiteral("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT)"));
0059 
0060         // Insert some initial data
0061         co_await database->execute(QStringLiteral("INSERT INTO test (data) VALUES (?)"), QStringLiteral("Hello World"));
0062     });
0063 
0064     // Retrieve some data from the database.
0065     // The data is directly returned as our HelloWorld struct.
0066     auto results = co_await database->getResults<HelloWorld>(QStringLiteral("SELECT * FROM test"));
0067 
0068     // Print out the data in the result list
0069     for (const auto &result : results) {
0070         qDebug() << result.id << result.data;
0071     }
0072 
0073     // Quit the event loop as we are done
0074     QCoreApplication::instance()->quit();
0075 }
0076 
0077 // Just a minimal main function for QCoro, to start the Qt event loop.
0078 int main(int argc, char *argv[]) {
0079     QCoreApplication app(argc, argv);
0080     QTimer::singleShot(0, databaseExample);
0081     return app.exec();
0082 }