From 059d6d38792bd99a24d57dbd6f9f84b2d2c145ed Mon Sep 17 00:00:00 2001 From: amass Date: Tue, 26 Nov 2024 22:58:54 +0800 Subject: [PATCH] use wt dbo. --- Database/CMakeLists.txt | 15 +- Database/Database.cpp | 178 +++-------------------- Database/Database.h | 20 +-- Database/HomeBox.cpp | 1 - Database/HomeBox.h | 23 +-- {WebApplication => Database}/Session.cpp | 29 ++-- {WebApplication => Database}/Session.h | 3 +- Database/Task.cpp | 34 ----- Database/Task.h | 20 +-- {WebApplication => Database}/User.h | 0 Server/Application.cpp | 64 ++++---- Server/main.cpp | 3 +- UnitTest/DatabaseTest.cpp | 67 +++++++-- WebApplication/CMakeLists.txt | 6 +- WebApplication/Hello.cpp | 16 +- WebApplication/Hello.h | 2 +- WebApplication/Restful.cpp | 8 +- WebApplication/Restful.h | 5 +- WebApplication/User.cpp | 5 - WebApplication/WebApplication.cpp | 14 +- WebApplication/WebApplication.h | 6 - 21 files changed, 195 insertions(+), 324 deletions(-) delete mode 100644 Database/HomeBox.cpp rename {WebApplication => Database}/Session.cpp (51%) rename {WebApplication => Database}/Session.h (91%) delete mode 100644 Database/Task.cpp rename {WebApplication => Database}/User.h (100%) delete mode 100644 WebApplication/User.cpp diff --git a/Database/CMakeLists.txt b/Database/CMakeLists.txt index 2e67e0a..a716369 100644 --- a/Database/CMakeLists.txt +++ b/Database/CMakeLists.txt @@ -1,14 +1,23 @@ +find_package(Wt REQUIRED Dbo) + add_library(Database Database.h Database.cpp - Task.h Task.cpp - HomeBox.h HomeBox.cpp + Session.h Session.cpp + Task.h + User.h + HomeBox.h ) +get_filename_component(PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) + target_include_directories(Database - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + INTERFACE ${PARENT_DIR} ) target_link_libraries(Database PUBLIC sqlite3 PUBLIC Universal + PUBLIC Wt::Wt + PUBLIC Wt::Dbo + PRIVATE Wt::DboSqlite3 ) \ No newline at end of file diff --git a/Database/Database.cpp b/Database/Database.cpp index 9f676b8..18e1452 100644 --- a/Database/Database.cpp +++ b/Database/Database.cpp @@ -1,9 +1,29 @@ #include "Database.h" #include "BoostLog.h" +#include "Session.h" +#include +#include +#include #include #include +std::unique_ptr Database::session() { + if (!m_sqlConnectionPool) return {}; + return std::make_unique(*m_sqlConnectionPool); +} + bool Database::open(const std::string &path) { + try { + auto connection = std::make_unique(path); + connection->setProperty("show-queries", "true"); + connection->setDateTimeStorage(Wt::Dbo::SqlDateTimeType::DateTime, + Wt::Dbo::backend::DateTimeStorage::PseudoISO8601AsText); + m_sqlConnectionPool = std::make_unique(std::move(connection), 10); + session()->createTables(); + } catch (const Wt::Dbo::Exception &e) { + LOG(error) << e.code() << ": " << e.what(); + } + bool ret = true; int result = sqlite3_open(path.c_str(), &m_sqlite3); if (result != SQLITE_OK) { @@ -14,97 +34,6 @@ bool Database::open(const std::string &path) { return ret; } -static int selectTaskCallback(void *data, int argc, char **argv, char **columnName) { - auto tasks = reinterpret_cast(data); - Task task; - for (int i = 0; i < argc; i++) { - if (argv[i] == nullptr) continue; - if (strcmp(columnName[i], "id") == 0) { - task.id = std::atol(argv[i]); - } else if (strcmp(columnName[i], "create_time") == 0) { - task.createTime = std::atol(argv[i]); - } else if (strcmp(columnName[i], "content") == 0) { - task.content = argv[i]; - } else if (strcmp(columnName[i], "comment") == 0) { - task.comment = argv[i]; - } else if (strcmp(columnName[i], "finished") == 0) { - task.finished = std::atol(argv[i]); - } else if (strcmp(columnName[i], "parent_id") == 0) { - task.parentId = std::atol(argv[i]); - } - } - tasks->push_back(task); - return 0; -} - -Tasks Database::tasks() { - Tasks ret; - char *error = nullptr; - if (sqlite3_exec(m_sqlite3, "select * from tasks", selectTaskCallback, &ret, &error) != SQLITE_OK) { - LOG(error) << "sqlite3_exec() failed: " << error << std::endl; - sqlite3_free(error); - } - std::unordered_map tasks; - for (auto iterator = ret.begin(); iterator != ret.end();) { - if (iterator->parentId >= 0) { - if (tasks.count(iterator->parentId) > 0) { - auto parentTask = tasks.at(iterator->parentId); - parentTask->children.push_back(*iterator); - tasks.insert({iterator->id, &parentTask->children.back()}); - } else { - LOG(warning) << "task`s parent id " << iterator->parentId << " not existed."; - } - iterator = ret.erase(iterator); - } else { - tasks.insert({iterator->id, &(*iterator)}); - ++iterator; - } - } - return ret; -} - -bool Database::addTask(uint64_t createTime, const std::string &content, const std::string &comment, int parentId, - bool finished) { - bool ret = true; - std::ostringstream oss; - oss << "INSERT INTO tasks (create_time,content,comment,parent_id,finished) VALUES (" << createTime << ",\"" - << content << "\",\"" << comment << "\"," << parentId << "," << finished << ");"; - auto sql = oss.str(); - char *error = nullptr; - int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error); - if (result != SQLITE_OK) { - LOG(error) << "add task failed: " << error << ", sql: " << sql; - sqlite3_free(error); - ret = false; - } - return ret; -} - -bool Database::removeTask(int id) { - bool ret = true; - std::ostringstream oss; - oss << "DELETE FROM tasks WHERE id = " << id << ";"; - auto sql = oss.str(); - char *error = nullptr; - int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error); - if (result != SQLITE_OK) { - LOG(error) << "add task failed: " << error << ", sql: " << sql; - sqlite3_free(error); - ret = false; - } - return ret; -} - -void Database::setTaskFinished(int id, bool finished, uint64_t finishedTime) { - std::ostringstream oss; - oss << "UPDATE tasks SET finished = " << finished << ", finished_time = " << finishedTime << " WHERE id = " << id; - auto sql = oss.str(); - int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, NULL); - if (result != SQLITE_OK) { - LOG(error) << "add task failed: " << sqlite3_errmsg(m_sqlite3) << ", sql: " << sql; - return; - } -} void Database::updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent, int64_t time) { @@ -278,72 +207,9 @@ VisitAnalysis Database::visitAnalysisData(const std::string &url) { return ret; } -bool Database::addHomeBoxItem(const std::string &name, const std::string &location, int cost) { - bool ret = true; - std::ostringstream oss; - oss << "INSERT INTO homebox (name,location,cost) VALUES (\"" << name << "\",\"" << location << "\"," << cost - << ");"; - auto sql = oss.str(); - char *error = nullptr; - int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error); - if (result != SQLITE_OK) { - LOG(error) << "add task failed: " << error << ", sql: " << sql; - sqlite3_free(error); - ret = false; - } - return ret; -} - -static int selectHomeBoxItemCallback(void *data, int argc, char **argv, char **columnName) { - auto items = reinterpret_cast(data); - HomeBox::Item item; - for (int i = 0; i < argc; i++) { - if (argv[i] == nullptr) continue; - if (strcmp(columnName[i], "id") == 0) { - item.id = std::atol(argv[i]); - } else if (strcmp(columnName[i], "name") == 0) { - item.name = argv[i]; - } else if (strcmp(columnName[i], "location") == 0) { - item.location = argv[i]; - } else if (strcmp(columnName[i], "cost") == 0) { - item.cost = std::atol(argv[i]); - } - } - items->push_back(item); - return 0; -} - -HomeBox::Items Database::homeBoxItems() { - HomeBox::Items ret; - char *error = nullptr; - if (sqlite3_exec(m_sqlite3, "select * from homebox", selectHomeBoxItemCallback, &ret, &error) != SQLITE_OK) { - LOG(error) << "sqlite3_exec() failed: " << error << std::endl; - sqlite3_free(error); - } - return ret; -} - void Database::initialize() { - const char *sql = - "CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY AUTOINCREMENT, create_time INTEGER NOT NULL, " - "parent_id INTEGER, content VARCHAR(512) NOT NULL, comment VARCHAR(512) NOT NULL, finished BOLL, finished_time " - "INTEGER);"; - int result = sqlite3_exec(m_sqlite3, sql, NULL, NULL, NULL); - if (result != SQLITE_OK) { - LOG(error) << "Failed to create table: " << sqlite3_errmsg(m_sqlite3); - return; - } - - const char *homeBoxSql = "CREATE TABLE IF NOT EXISTS homebox (id INTEGER PRIMARY KEY AUTOINCREMENT, " - "name VARCHAR(512) NOT NULL, location VARCHAR(512) NOT NULL, cost INTEGER);"; - result = sqlite3_exec(m_sqlite3, homeBoxSql, NULL, NULL, NULL); - if (result != SQLITE_OK) { - LOG(error) << "Failed to create table: " << sqlite3_errmsg(m_sqlite3); - return; - } - char *message = nullptr; - sql = R"( + auto sql = R"( CREATE TABLE IF NOT EXISTS visit_analysis ( id INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT NOT NULL, @@ -353,7 +219,7 @@ void Database::initialize() { page_view_count INTEGER NOT NULL ); )"; - result = sqlite3_exec(m_sqlite3, sql, 0, 0, &message); + int result = sqlite3_exec(m_sqlite3, sql, 0, 0, &message); if (result != SQLITE_OK) { LOG(error) << "Failed to create table: " << message << std::endl; sqlite3_free(message); diff --git a/Database/Database.h b/Database/Database.h index 363207c..0c19515 100644 --- a/Database/Database.h +++ b/Database/Database.h @@ -6,6 +6,12 @@ #include "Task.h" #include +namespace Wt { +namespace Dbo { +class SqlConnectionPool; +} +} // namespace Wt + class VisitAnalysis { public: std::string url; @@ -15,34 +21,28 @@ public: }; struct sqlite3; +class Session; class Database { friend class Amass::Singleton; public: ~Database(); + std::unique_ptr session(); bool open(const std::string &path); - Tasks tasks(); - bool addTask(uint64_t createTime, const std::string &content, const std::string &comment = "", int parentId = -1, - bool finished = false); - bool removeTask(int id); - void setTaskFinished(int id, bool finished, uint64_t finishedTime); - void updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent, - int64_t time); + void updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent, int64_t time); void clearVisitRecord(); VisitAnalysis visitAnalysisData(const std::string &url); VisitAnalysis siteVisitAnalysisData(); std::list mostViewedUrls(int size); std::list latestViewedUrls(int size); - HomeBox::Items homeBoxItems(); - bool addHomeBoxItem(const std::string &name, const std::string &location, int cost); - protected: void initialize(); private: + std::unique_ptr m_sqlConnectionPool; sqlite3 *m_sqlite3 = nullptr; }; diff --git a/Database/HomeBox.cpp b/Database/HomeBox.cpp deleted file mode 100644 index 6e66874..0000000 --- a/Database/HomeBox.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "HomeBox.h" \ No newline at end of file diff --git a/Database/HomeBox.h b/Database/HomeBox.h index c394a28..a24652a 100644 --- a/Database/HomeBox.h +++ b/Database/HomeBox.h @@ -1,20 +1,23 @@ #ifndef __HOMEBOX_H__ #define __HOMEBOX_H__ -#include +#include #include -class HomeBox { +namespace HomeBox { +class Item { public: - class Item { - public: - int id = -1; - std::string name; - std::string location; - int cost; - }; + std::string name; + std::string location; + int cost; - using Items = std::list; + template + void persist(Action &a) { + Wt::Dbo::field(a, name, "name"); + Wt::Dbo::field(a, location, "location"); + Wt::Dbo::field(a, cost, "cost"); + } }; +} // namespace HomeBox #endif // __HOMEBOX_H__ \ No newline at end of file diff --git a/WebApplication/Session.cpp b/Database/Session.cpp similarity index 51% rename from WebApplication/Session.cpp rename to Database/Session.cpp index a614d9e..c4dee9a 100644 --- a/WebApplication/Session.cpp +++ b/Database/Session.cpp @@ -1,30 +1,17 @@ #include "Session.h" -#include "BoostLog.h" -#include #include -#include -#include -#include -#include -#include -#include -#include -Session::Session(Wt::Dbo::SqlConnectionPool &connectionPool) : m_connectionPool(connectionPool) { - setConnectionPool(m_connectionPool); +Session::Session(Wt::Dbo::SqlConnectionPool &connectionPool) { + setConnectionPool(connectionPool); + + mapClass("task"); + mapClass("homebox_item"); mapClass("user"); mapClass("auth_info"); mapClass("auth_identity"); mapClass("auth_token"); - try { - createTables(); - LOG(info) << "Created database."; - } catch (Wt::Dbo::Exception &e) { - LOG(error) << e.what() << ", using existing database"; - } - m_users = std::make_unique(*this); } @@ -45,4 +32,8 @@ Wt::Auth::AbstractUserDatabase &Session::users() { Wt::Auth::Login &Session::login() { return m_login; -} \ No newline at end of file +} + +DBO_INSTANTIATE_TEMPLATES(User) +DBO_INSTANTIATE_TEMPLATES(Task) +DBO_INSTANTIATE_TEMPLATES(HomeBox::Item) \ No newline at end of file diff --git a/WebApplication/Session.h b/Database/Session.h similarity index 91% rename from WebApplication/Session.h rename to Database/Session.h index f758351..d76204b 100644 --- a/WebApplication/Session.h +++ b/Database/Session.h @@ -1,6 +1,8 @@ #ifndef __SESSION_H__ #define __SESSION_H__ +#include "HomeBox.h" +#include "Task.h" #include "User.h" #include #include @@ -16,7 +18,6 @@ public: Wt::Auth::Login &login(); private: - Wt::Dbo::SqlConnectionPool &m_connectionPool; std::unique_ptr m_users; Wt::Auth::Login m_login; }; diff --git a/Database/Task.cpp b/Database/Task.cpp deleted file mode 100644 index 3798c70..0000000 --- a/Database/Task.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "Task.h" -#include -#include -#include - -namespace boost { -namespace json { - -static boost::json::object serialize(const Task &task) { - boost::json::object ret; - ret["id"] = task.id; - ret["parentId"] = task.parentId; - ret["finished"] = task.finished; - ret["createTime"] = task.createTime; - ret["content"] = task.content; - ret["comment"] = task.comment; - - boost::json::array children; - for (auto &child : task.children) { - children.push_back(serialize(child)); - } - ret["children"] = std::move(children); - return ret; -} - -std::string serialize(const Tasks &tasks) { - boost::json::array ret; - for (auto &task : tasks) { - ret.push_back(serialize(task)); - } - return boost::json::serialize(ret); -} -} // namespace json -} // namespace boost \ No newline at end of file diff --git a/Database/Task.h b/Database/Task.h index 88d553c..b744376 100644 --- a/Database/Task.h +++ b/Database/Task.h @@ -1,31 +1,33 @@ #ifndef __TASK_H__ #define __TASK_H__ -#include +#include #include class Task; -using Tasks = std::list; +using Tasks = Wt::Dbo::collection>; class Task { public: - int id = -1; - int parentId = -1; bool finished = false; int32_t createTime = 0; std::string content; std::string comment; + + Wt::Dbo::ptr parent; Tasks children; template void persist(Action &a) { + Wt::Dbo::field(a, content, "content"); + Wt::Dbo::field(a, comment, "comment"); + Wt::Dbo::field(a, finished, "finished"); + Wt::Dbo::field(a, createTime, "create_time"); + + Wt::Dbo::belongsTo(a, parent, "parent"); + Wt::Dbo::hasMany(a, children, Wt::Dbo::ManyToOne, "parent"); } }; -namespace boost { -namespace json { -std::string serialize(const Tasks &tasks); -} -} // namespace boost #endif // __TASK_H__ \ No newline at end of file diff --git a/WebApplication/User.h b/Database/User.h similarity index 100% rename from WebApplication/User.h rename to Database/User.h diff --git a/Server/Application.cpp b/Server/Application.cpp index f8ab7f6..c5a0cbc 100644 --- a/Server/Application.cpp +++ b/Server/Application.cpp @@ -1,5 +1,6 @@ #include "Application.h" -#include "Database.h" +#include "Database/Database.h" +#include "Database/Session.h" #include "DateTime.h" #include "HttpSession.h" #include "IoContext.h" @@ -8,6 +9,7 @@ #include "ServiceManager.h" #include "SystemUsage.h" #include "WeChatContext/CorporationContext.h" +#include #include #include #include @@ -60,22 +62,23 @@ Application::Application(const std::string &path) m_router->insert("/api/v1/tasklist", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) { using namespace boost::beast; - auto database = Amass::Singleton::instance(); - auto tasks = database->tasks(); + auto database = Amass::Singleton::instance()->session(); + Tasks tasks = database->find(); + std::ostringstream oss; + Wt::Dbo::jsonSerialize(tasks, oss); http::response s{boost::beast::http::status::ok, request.version()}; s.set(http::field::server, BOOST_BEAST_VERSION_STRING); s.set(http::field::content_type, "application/json;charset=UTF-8"); s.keep_alive(request.keep_alive()); - s.body() = boost::json::serialize(tasks); + s.body() = oss.str(); s.prepare_payload(); session.reply(std::move(s)); }); - m_router->insert("/api/v1/task/add", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) { + m_router->insert("/api/v1/task/add", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) mutable { using namespace boost::beast; LOG(info) << "add task: " << request.body(); - auto database = Amass::Singleton::instance(); auto rootJson = boost::json::parse(request.body()); auto &root = rootJson.as_object(); @@ -83,10 +86,18 @@ Application::Application(const std::string &path) if (root.contains("content")) { content = root.at("content").as_string(); } - bool ret = database->addTask(root.at("createTime").as_int64(), content, - std::string(root.at("comment").as_string()), root.at("parentId").as_int64()); + auto database = Amass::Singleton::instance()->session(); + auto task = std::make_unique(); + task->createTime = root.at("createTime").as_int64(); + task->content = content; + task->comment = std::string(root.at("comment").as_string()); + auto t = database->add(std::move(task)); + Wt::Dbo::ptr parent = database->find("where id=?").bind(root.at("parentId").as_int64()); + if (parent) { + parent.modify()->children.insert(t); + } boost::json::object reply; - reply["status"] = ret ? 0 : -1; + reply["status"] = 0; http::response s{boost::beast::http::status::ok, request.version()}; s.set(http::field::server, BOOST_BEAST_VERSION_STRING); s.set(http::field::content_type, "application/json;charset=UTF-8"); @@ -99,11 +110,15 @@ Application::Application(const std::string &path) m_router->insert("/api/v1/task/delete/{id}", [this](HttpSession &session, const Request &request,const boost::urls::matches &matches) { using namespace boost::beast; LOG(info) << "delete task: " << matches.at("id"); - auto database = Amass::Singleton::instance(); - auto status = database->removeTask(std::stoi(matches.at("id"))); - + auto database = Amass::Singleton::instance()->session(); + Wt::Dbo::ptr joe = database->find().where("id = ?").bind(std::stoi(matches.at("id"))); + int status = -1; + if (joe) { + joe.remove(); + status = 0; + } boost::json::object reply; - reply["status"] = status ? 0 : -1; + reply["status"] = status; http::response s{boost::beast::http::status::ok, request.version()}; s.set(http::field::server, BOOST_BEAST_VERSION_STRING); s.set(http::field::content_type, "application/json;charset=UTF-8"); @@ -125,8 +140,7 @@ Application::Application(const std::string &path) ServiceLogic::make_200(request, "notify successed.\n", "text/html")); }); // clang-format on - m_router->insert("/api/v1/visit_analysis", [this](HttpSession &session, const Request &request, - const boost::urls::matches &matches) { + m_router->insert("/api/v1/visit_analysis", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) { using namespace boost::beast; auto rootJson = boost::json::parse(request.body()); auto &root = rootJson.as_object(); @@ -166,8 +180,7 @@ Application::Application(const std::string &path) session.reply(std::move(s)); }); - m_router->insert("/api/v1/most_viewed_urls", [this](HttpSession &session, const Request &request, - const boost::urls::matches &matches) { + m_router->insert("/api/v1/most_viewed_urls", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) { using namespace boost::beast; int size = 5; std::error_code error; @@ -200,8 +213,7 @@ Application::Application(const std::string &path) session.reply(std::move(s)); }); - m_router->insert("/api/v1/latest_viewed_urls", [this](HttpSession &session, const Request &request, - const boost::urls::matches &matches) { + m_router->insert("/api/v1/latest_viewed_urls", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) { using namespace boost::beast; int size = 5; std::error_code error; @@ -290,21 +302,21 @@ void Application::alarmTask() { LOG(error) << error.message(); return; } - auto database = Amass::Singleton::instance(); - auto tasks = database->tasks(); + auto session = Amass::Singleton::instance()->session(); + Tasks tasks = session->find(); bool founded = false; std::string content; for (auto &task : tasks) { if (founded) break; - for (auto &child : task.children) { - if (!child.finished) { - content = child.content; + for (auto child : task->children) { + if (!child->finished) { + content = child->content; founded = true; break; } } - if (!founded && !task.finished) { - content = task.content; + if (!founded && !task->finished) { + content = task->content; founded = true; } } diff --git a/Server/main.cpp b/Server/main.cpp index 827d84a..177017a 100644 --- a/Server/main.cpp +++ b/Server/main.cpp @@ -1,6 +1,6 @@ #include "Application.h" #include "BoostLog.h" -#include "Database.h" +#include "Database/Database.h" #include "IoContext.h" #include "Listener.h" #include "Live2dBackend.h" @@ -11,6 +11,7 @@ #include "WeChatContext/CorporationContext.h" #include "WeChatContext/WeChatContext.h" #include "WebApplication.h" +#include #include #include #include diff --git a/UnitTest/DatabaseTest.cpp b/UnitTest/DatabaseTest.cpp index 44de5df..767df65 100644 --- a/UnitTest/DatabaseTest.cpp +++ b/UnitTest/DatabaseTest.cpp @@ -1,5 +1,7 @@ -#include "Database.h" +#include "Database/Database.h" #include "BoostLog.h" +#include "Database/Session.h" +#include #include #include @@ -11,22 +13,69 @@ BOOST_AUTO_TEST_CASE(DatabaseTest) { std::filesystem::remove(path); } Database database; - BOOST_TEST(database.open(path)); + database.open(path); + // BOOST_TEST(database.open(path)); - database.addTask(1234, "Hello"); + auto session = database.session(); - database.addTask(1234, "这是一个测试", "", true); + Wt::Dbo ::Transaction transaction(*session); - database.addHomeBoxItem("手机", "抽屉", 1499); - auto items = database.homeBoxItems(); - BOOST_CHECK_EQUAL(items.size(), 1); + auto task = std::make_unique(); + task->comment = "my_comment"; + task->content = "my_content"; + + auto p = session->add(std::move(task)); + + { + task = std::make_unique(); + task->comment = "my_comment1"; + task->content = "my_content1"; + auto c = session->add(std::move(task)); + p.modify()->children.insert(c); + } + + { + task = std::make_unique(); + task->comment = "my_comment2"; + task->content = "my_content2"; + auto c = session->add(std::move(task)); + p.modify()->children.insert(c); + + { + task = std::make_unique(); + task->comment = "my_comment3"; + task->content = "my_content3"; + auto d = session->add(std::move(task)); + c.modify()->children.insert(d); + } + + { + task = std::make_unique(); + task->comment = "my_comment4"; + task->content = "my_content4"; + auto d = session->add(std::move(task)); + c.modify()->children.insert(d); + } + } + + Wt::Dbo::ptr tt = session->find("where id = 3"); + LOG(info) << tt->parent->content; + LOG(info) << tt->children.size(); + + { + auto item = std::make_unique(); + item->cost = 1499; + item->location = "抽屉"; + item->name = "手机"; + + auto d = session->add(std::move(item)); + } auto now = std::chrono::system_clock::now(); std::time_t now_time = std::chrono::system_clock::to_time_t(now); - database.setTaskFinished(1, true, now_time); database.updateVisitCount("/note", "uuid_123", "chrome", now_time); database.updateVisitCount("/note/1", "uuid_1232", "chrome", now_time); database.updateVisitCount("/note", "uuid_123", "chrome", now_time); database.updateVisitCount("/note", "uuid_1234", "chrome", now_time); -} \ No newline at end of file +} diff --git a/WebApplication/CMakeLists.txt b/WebApplication/CMakeLists.txt index 0ef4c13..ad1bb82 100644 --- a/WebApplication/CMakeLists.txt +++ b/WebApplication/CMakeLists.txt @@ -3,11 +3,9 @@ find_package(Wt REQUIRED Wt) add_library(WebApplication WebApplication.h WebApplication.cpp LoginWidget.h LoginWidget.cpp - User.h User.cpp Hello.h Hello.cpp Restful.h Restful.cpp Dialog.h Dialog.cpp - Session.h Session.cpp ) target_include_directories(WebApplication @@ -16,8 +14,6 @@ target_include_directories(WebApplication target_link_libraries(WebApplication PUBLIC Universal - PRIVATE Wt::Wt - PRIVATE Wt::Dbo PRIVATE Wt::HTTP - PRIVATE Wt::DboSqlite3 + PRIVATE Database ) \ No newline at end of file diff --git a/WebApplication/Hello.cpp b/WebApplication/Hello.cpp index 3227376..790e37d 100644 --- a/WebApplication/Hello.cpp +++ b/WebApplication/Hello.cpp @@ -1,8 +1,9 @@ #include "Hello.h" #include "BoostLog.h" +#include "Database/Database.h" +#include "Database/Session.h" #include "Dialog.h" #include "LoginWidget.h" -#include "Session.h" #include "WebApplication.h" #include #include @@ -12,14 +13,13 @@ #include #include -Hello::Hello(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool &connectionPool, bool embedded) - : Wt::WApplication(env) { +Hello::Hello(const Wt::WEnvironment &env, bool embedded) : Wt::WApplication(env) { messageResourceBundle().use(appRoot() + "wt"); messageResourceBundle().use(appRoot() + "auth_strings"); messageResourceBundle().use(appRoot() + "auth_css_theme"); useStyleSheet("/resources/app.css"); LOG(info) << "app root: " << appRoot(); - m_session = std::make_unique(connectionPool); + m_session = Amass::Singleton::instance()->session(); m_session->login().changed().connect(this, &Hello::authEvent); setTitle("Hello world"); if (!embedded) { @@ -35,7 +35,6 @@ Hello::Hello(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool &connection } else { LOG(error) << "Missing: parameter: 'div'"; } - internalPathChanged().connect(this, &Hello::handlePathChange); auto externalPath = env.getParameter("path"); if (externalPath != nullptr) { m_externalPath = *externalPath; @@ -55,6 +54,7 @@ Hello::Hello(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool &connection root()->addWidget(std::make_unique("

Note: you can also run this application " "from within a web page.

")); } + LOG(info) << "internal path: " << internalPath(); m_root->addWidget(std::make_unique("Your name, please ? ")); m_nameEdit = m_root->addWidget(std::make_unique()); @@ -73,10 +73,8 @@ Hello::Hello(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool &connection auto app = Amass::Singleton::instance(); m_root->addWidget(std::make_unique()); - - if (!m_externalPath.empty()) { - handlePathChange(m_externalPath); - } + internalPathChanged().connect(this, &Hello::handlePathChange); + handlePathChange(m_externalPath.empty() ? internalPath() : m_externalPath); } Hello::~Hello() { diff --git a/WebApplication/Hello.h b/WebApplication/Hello.h index 0570ce6..2a703eb 100644 --- a/WebApplication/Hello.h +++ b/WebApplication/Hello.h @@ -7,7 +7,7 @@ class Session; class Hello : public Wt::WApplication { public: - Hello(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool &connectionPool, bool embedded); + Hello(const Wt::WEnvironment &env, bool embedded); ~Hello(); protected: diff --git a/WebApplication/Restful.cpp b/WebApplication/Restful.cpp index 8763c35..9531ce6 100644 --- a/WebApplication/Restful.cpp +++ b/WebApplication/Restful.cpp @@ -1,5 +1,6 @@ #include "Restful.h" -#include "Session.h" +#include "Database/Database.h" +#include "Database/Session.h" #include #include #include @@ -10,7 +11,7 @@ DBO_INSTANTIATE_TEMPLATES(MyMessage) DbStruct *m_dbStruct; void AuthenticationResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response) { - Session session(m_connectionPool); + auto session = Amass::Singleton::instance()->session(); response.setMimeType("application/json"); response.addHeader("Server", "Wt"); @@ -48,8 +49,7 @@ int DbStruct::rand() { return distribution(rng); } -AuthenticationResource::AuthenticationResource(Wt::Dbo::SqlConnectionPool &connectionPool) - : m_connectionPool(connectionPool) { +AuthenticationResource::AuthenticationResource() { } DbStruct::DbStruct(const std::string &db) : rng(clock()), distribution(1, 10000) { diff --git a/WebApplication/Restful.h b/WebApplication/Restful.h index 9e26a03..f76a788 100644 --- a/WebApplication/Restful.h +++ b/WebApplication/Restful.h @@ -46,11 +46,8 @@ struct DbStruct { class AuthenticationResource : public Wt::WResource { public: - AuthenticationResource(Wt::Dbo::SqlConnectionPool &connectionPool); + AuthenticationResource(); void handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response) final; - -private: - Wt::Dbo::SqlConnectionPool &m_connectionPool; }; class PlaintextResource : public Wt::WResource { diff --git a/WebApplication/User.cpp b/WebApplication/User.cpp deleted file mode 100644 index acf47a0..0000000 --- a/WebApplication/User.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "User.h" -#include -#include - -DBO_INSTANTIATE_TEMPLATES(User) \ No newline at end of file diff --git a/WebApplication/WebApplication.cpp b/WebApplication/WebApplication.cpp index 6cf45c3..ba99a85 100644 --- a/WebApplication/WebApplication.cpp +++ b/WebApplication/WebApplication.cpp @@ -1,8 +1,8 @@ #include "WebApplication.h" #include "BoostLog.h" +#include "Database/Session.h" #include "Hello.h" #include "Restful.h" -#include "Session.h" #include #include #include @@ -23,13 +23,12 @@ WebApplication::WebApplication(uint16_t port, const std::string &documentRoot) { initializeAuthenticationService(); m_server = std::make_unique(std::format("{}/resources", documentRoot), args); - m_sqlConnectionPool = createConnectionPool(std::format("{}/database.sqlite", documentRoot)); m_server->addEntryPoint(Wt::EntryPointType::Application, std::bind(&WebApplication::createApplication, this, std::placeholders::_1, false)); m_server->addEntryPoint(Wt::EntryPointType::WidgetSet, std::bind(&WebApplication::createApplication, this, std::placeholders::_1, true), "/wt/app.js"); - m_server->addResource(std::make_shared(*m_sqlConnectionPool), "/auth"); + m_server->addResource(std::make_shared(), "/auth"); m_server->addResource(std::make_shared(), "/plaintext"); m_server->addResource(std::make_shared(std::format("{}/database.sqlite", documentRoot)), "/db"); @@ -39,15 +38,8 @@ WebApplication::WebApplication(uint16_t port, const std::string &documentRoot) { } } -std::unique_ptr WebApplication::createConnectionPool(const std::string &sqlite3) { - auto connection = std::make_unique(sqlite3); - connection->setProperty("show-queries", "true"); - connection->setDateTimeStorage(Wt::Dbo::SqlDateTimeType::DateTime, Wt::Dbo::backend::DateTimeStorage::PseudoISO8601AsText); - return std::make_unique(std::move(connection), 10); -} - std::unique_ptr WebApplication::createApplication(const Wt::WEnvironment &env, bool embedded) { - return std::make_unique(env, *m_sqlConnectionPool, embedded); + return std::make_unique(env, embedded); } WebApplication::~WebApplication() { diff --git a/WebApplication/WebApplication.h b/WebApplication/WebApplication.h index 7303f1f..19f0c9c 100644 --- a/WebApplication/WebApplication.h +++ b/WebApplication/WebApplication.h @@ -9,10 +9,6 @@ class WServer; class WApplication; class WEnvironment; -namespace Dbo { -class SqlConnectionPool; -} - namespace Auth { class AuthService; class PasswordService; @@ -32,12 +28,10 @@ public: protected: WebApplication(uint16_t port, const std::string &documentRoot); - static std::unique_ptr createConnectionPool(const std::string &sqlite3); std::unique_ptr createApplication(const Wt::WEnvironment &env, bool embedded); private: std::unique_ptr m_server; - std::unique_ptr m_sqlConnectionPool; std::unique_ptr m_authService; std::unique_ptr m_passwordService;