WebFramework v3.0.12
Web framework for C++.
Loading...
Searching...
No Matches
SQLiteManager.h
1#pragma once
2
3#include "Import/WebFrameworkCore.h"
4
5#include "SQLiteDatabaseModel.h"
6
7namespace framework
8{
9 namespace sqlite
10 {
11 class WEB_FRAMEWORK_API SQLiteManager
12 {
13 private:
14 class WEB_FRAMEWORK_API Database
15 {
16 private:
17 class WEB_FRAMEWORK_API ModelsData
18 {
19 private:
20 std::vector<std::pair<std::shared_ptr<SQLiteDatabaseModel>, size_t>> data;
21
22 public:
23 ModelsData() = default;
24
25 template<std::derived_from<SQLiteDatabaseModel> T, typename... Args>
26 std::shared_ptr<T> add(std::shared_ptr<SQLiteDatabase> database, Args&&... args);
27
28 template<std::derived_from<SQLiteDatabaseModel> T>
29 std::shared_ptr<T> get() const;
30
31 ~ModelsData() = default;
32 };
33
34 private:
35 std::shared_ptr<SQLiteDatabase> database;
36 std::unordered_map<std::string_view, ModelsData> models;
37 mutable std::shared_mutex mutex;
38
39 public:
40 Database(const std::string& databaseName);
41
42 template<std::derived_from<SQLiteDatabaseModel> T, typename... Args>
43 std::shared_ptr<T> add(Args&&... args);
44
45 template<std::derived_from<SQLiteDatabaseModel> T>
46 std::shared_ptr<T> get() const;
47
48 ~Database() = default;
49 };
50
51 private:
52 std::unordered_map<std::string_view, std::unique_ptr<Database>> databases;
53 mutable std::shared_mutex mutex;
54
55 public:
56 SQLiteManager() = default;
57
58 template<std::derived_from<SQLiteDatabaseModel> T, typename... Args>
59 std::shared_ptr<T> add(Args&&... args);
60
61 template<std::derived_from<SQLiteDatabaseModel> T>
62 std::shared_ptr<T> get() const;
63
64 ~SQLiteManager() = default;
65
66 friend class SQLiteDatabaseModel;
67 };
68
69 template<std::derived_from<SQLiteDatabaseModel> T, typename... Args>
70 std::shared_ptr<T> SQLiteManager::Database::ModelsData::add(std::shared_ptr<SQLiteDatabase> database, Args&&... args)
71 {
72 size_t typeHash = typeid(T).hash_code();
73
74 for (const auto& [model, hash] : data)
75 {
76 if (typeHash == hash)
77 {
78 return std::dynamic_pointer_cast<T>(model);
79 }
80 }
81
82 T* model = static_cast<T*>(malloc(sizeof(T)));
83
84 if (!model)
85 {
86 throw std::bad_alloc();
87 }
88
89 memset(model, 0, sizeof(T));
90
91 model->databaseConstructor = database;
92
93 model = new (model)(T)(std::forward<Args>(args)...);
94
95 if (!model->database)
96 {
97 model->database = database;
98 }
99
100 return std::dynamic_pointer_cast<T>(data.emplace_back(std::shared_ptr<T>(model), typeHash).first);
101 }
102
103 template<std::derived_from<SQLiteDatabaseModel> T>
104 std::shared_ptr<T> SQLiteManager::Database::ModelsData::get() const
105 {
106 size_t typeHash = typeid(T).hash_code();
107
108 for (const auto& [model, hash] : data)
109 {
110 if (typeHash == hash)
111 {
112 return std::dynamic_pointer_cast<T>(model);
113 }
114 }
115
116 return nullptr;
117 }
118
119 template<std::derived_from<SQLiteDatabaseModel> T, typename... Args>
120 std::shared_ptr<T> SQLiteManager::Database::add(Args&&... args)
121 {
122 std::unique_lock<std::shared_mutex> lock(mutex);
123 ModelsData* data = nullptr;
124
125 if (auto modelsData = models.find(T::tableName); modelsData != models.end())
126 {
127 data = &modelsData->second;
128 }
129 else
130 {
131 modelsData = models.try_emplace(T::tableName, ModelsData()).first;
132
133 data = &modelsData->second;
134 }
135
136 return data->add<T>(database, std::forward<Args>(args)...);
137 }
138
139 template<std::derived_from<SQLiteDatabaseModel> T>
140 std::shared_ptr<T> SQLiteManager::Database::get() const
141 {
142 std::shared_lock<std::shared_mutex> lock(mutex);
143
144 if (auto modelsData = models.find(T::tableName); modelsData != models.end())
145 {
146 const ModelsData& data = modelsData->second;
147
148 return data.get<T>();
149 }
150
151 return nullptr;
152 }
153
154 template<std::derived_from<SQLiteDatabaseModel> T, typename... Args>
155 std::shared_ptr<T> SQLiteManager::add(Args&&... args)
156 {
157 static_assert(T::databaseName.size(), "SQLiteDatabaseModel::databaseName is empty");
158 static_assert(T::tableName.size(), "SQLiteDatabaseModel::tableName is empty");
159
160 std::unique_lock<std::shared_mutex> lock(mutex);
161 std::unique_ptr<Database>* database = nullptr;
162
163 if (auto it = databases.find(T::databaseName); it != databases.end())
164 {
165 database = &it->second;
166 }
167 else
168 {
169 it = databases.try_emplace(T::databaseName, std::make_unique<Database>(std::string(T::databaseName))).first;
170
171 database = &it->second;
172 }
173
174 return (*database)->add<T>(std::forward<Args>(args)...);
175 }
176
177 template<std::derived_from<SQLiteDatabaseModel> T>
178 std::shared_ptr<T> SQLiteManager::get() const
179 {
180 const Database* database = nullptr;
181
182 {
183 std::shared_lock<std::shared_mutex> lock(mutex);
184
185 if (auto it = databases.find(T::databaseName); it != databases.end())
186 {
187 database = &(*it->second);
188 }
189 }
190
191 return database ? database->get<T>() : nullptr;
192 }
193 }
194}
Providing SELECT, INSERT, UPDATE, DELETE or raw queries for SQLiteDatabase.