载入中...
搜索中...
未找到
Database.h
浏览该文件的文档.
1#pragma once
2#include "common/Export.h"
3
4
5#include "common/Module.h"
6
7#include <cstdint>
8#include <functional>
9#include <memory>
10#include <stdexcept>
11#include <string>
12#include <unordered_map>
13#include <utility>
14#include <variant>
15#include <vector>
16
17namespace Poco::Data {
18class Session;
19}
20
21namespace eve::database {
22
23class Model;
24class Query;
25
26using Value = std::variant<std::monostate, std::int64_t, double, std::string, bool>;
27using Row = std::unordered_map<std::string, Value>;
28
30template <class T>
32struct Field {
33 std::string name;
35 std::function<Value(const T&)> read;
37 std::function<void(T&, const Value&)> write;
38 std::string sqlType = "TEXT";
39 bool primaryKey = false;
40};
41
42template <class T>
44struct Mapping {
45 std::string table;
46 std::vector<Field<T>> fields;
47
49 Row toRow(const T& object) const {
50 Row row;
51 for (const auto& field : fields) row[field.name] = field.read(object);
52 return row;
53 }
54
56 T fromRow(const Row& row) const {
57 T object{};
58 for (const auto& field : fields) {
59 auto it = row.find(field.name);
60 if (it != row.end()) field.write(object, it->second);
61 }
62 return object;
63 }
64};
65
71public:
73 Connection(std::string connector, std::string connectionString);
76
77 Connection(const Connection&) = delete;
78 Connection& operator=(const Connection&) = delete;
79
81 bool isConnected() const;
83 void close();
85 int execute(const std::string& sql);
87 std::vector<Row> query(const std::string& sql);
89 std::string queryJson(const std::string& sql);
91 int insert(const std::string& table, const Row& values);
93 int update(const std::string& table, const Row& values, const std::string& whereClause);
95 int remove(const std::string& table, const std::string& whereClause);
96
98 int insertJson(const std::string& table, const std::string& json);
100 int updateJson(const std::string& table, const std::string& json, const std::string& whereClause);
101
103 int updateByKey(const std::string& table, const Row& values, const std::string& key, const Value& id);
105 int removeByKey(const std::string& table, const std::string& key, const Value& id);
107 std::vector<Row> queryByKey(const std::string& table, const std::string& key, const Value& id);
109 Model* model(std::string table, std::string primaryKey = "id");
111 Query* from(std::string table);
112
114 template <class T>
116 int save(const Mapping<T>& mapping, const T& object) {
118 return insert(mapping.table, mapping.toRow(object));
119 }
120
122 template <class Range, class Mapper>
124 int exportECS(const std::string& table, const Range& entities, Mapper mapper) {
125 int count = 0;
127 execute("BEGIN");
128 try {
129 for (const auto& entity : entities) count += insert(table, mapper(entity));
131 execute("COMMIT");
132 } catch (...) {
133 try {
135 execute("ROLLBACK");
136 } catch (...) {
137 }
138 throw;
139 }
140 return count;
141 }
142
143private:
144 std::unique_ptr<Poco::Data::Session> session_;
145};
146
149public:
151 Query(Connection* connection, std::string table);
153 Query* where(const std::string& column, const std::string& op, Value value);
155 Query* whereJson(const std::string& column, const std::string& op, const std::string& valueJson);
157 Query* orderBy(const std::string& column, bool ascending = true);
159 Query* limit(int count);
161 Query* offset(int count);
163 std::vector<Row> all();
165 std::string allJson();
167 std::string firstJson();
169 int count();
170
171private:
172 std::string selectSql(bool countOnly, int forcedLimit = -1) const;
173 Connection* connection_;
174 std::string table_;
175 std::vector<std::string> predicates_;
176 std::vector<std::string> ordering_;
177 int limit_ = -1;
178 int offset_ = 0;
179};
180
182template <class T>
185public:
187 Repository(Connection& connection, Mapping<T> mapping) : connection_(connection), mapping_(std::move(mapping)) {}
188
190 void createTable(bool ifNotExists = true) {
191 if (mapping_.fields.empty()) throw std::invalid_argument("ORM mapping has no fields");
192 std::string sql = "CREATE TABLE ";
193 if (ifNotExists) sql += "IF NOT EXISTS ";
194 sql += mapping_.table + " (";
195 for (std::size_t i = 0; i < mapping_.fields.size(); ++i) {
196 const auto& field = mapping_.fields[i];
197 if (i) sql += ',';
198 sql += field.name + " " + field.sqlType;
199 if (field.primaryKey) sql += " PRIMARY KEY";
200 }
201 connection_.execute(sql + ")");
202 }
203
205 int insert(const T& object) { return connection_.insert(mapping_.table, mapping_.toRow(object)); }
206
208 std::vector<T> all() {
209 std::vector<T> objects;
210 for (const auto& row : connection_.query("SELECT * FROM " + mapping_.table))
211 objects.push_back(mapping_.fromRow(row));
212 return objects;
213 }
214
216 bool find(const Value& id, T& object) {
217 auto rows = connection_.queryByKey(mapping_.table, primaryKey().name, id);
218 if (rows.empty()) return false;
219 object = mapping_.fromRow(rows.front());
220 return true;
221 }
222
224 int update(const T& object) {
225 const auto& key = primaryKey();
226 Row values = mapping_.toRow(object);
227 Value id = values.at(key.name);
228 values.erase(key.name);
229 return connection_.updateByKey(mapping_.table, values, key.name, id);
230 }
231
233 int remove(const Value& id) { return connection_.removeByKey(mapping_.table, primaryKey().name, id); }
234
236 std::vector<T> select(const std::function<void(Query&)>& configure) {
238 Query query(&connection_, mapping_.table);
240 configure(query);
241 std::vector<T> objects;
242 for (const auto& row : query.all()) objects.push_back(mapping_.fromRow(row));
243 return objects;
244 }
245
246private:
247 const Field<T>& primaryKey() const {
248 for (const auto& field : mapping_.fields)
249 if (field.primaryKey) return field;
250 throw std::logic_error("ORM mapping requires one primary key field");
251 }
252
253 Connection& connection_;
254 Mapping<T> mapping_;
255};
256
259public:
261 Model(Connection* connection, std::string table, std::string primaryKey);
263 int insertJson(const std::string& json);
265 std::string allJson();
267 std::string findJson(const std::string& idJson);
269 int updateJson(const std::string& idJson, const std::string& json);
271 int remove(const std::string& idJson);
273 Query* query();
274
275private:
276 Connection* connection_;
277 std::string table_;
278 std::string primaryKey_;
279};
280
285class Database : public Module {
286public:
289 Database() = default;
291 ~Database() override = default;
292
294 Connection* connect(std::string connector, std::string connectionString);
296 Connection* connectSQLite(std::string path);
297};
298
299} // namespace eve::database
double value
std::string from
int column
std::map< std::string, Var > values
#define EVENGINE_API_FOUNDATION
每个链接组(link group)各自的导出宏。
Definition Export.h:106
int rows
std::uint32_t key
size_t offset
std::string name
std::string path
Definition PlayHost.cpp:110
std::vector< std::string > fields
Definition PlayHost.cpp:111
std::vector< ecs::EntityHandle > entities
glm::mat4 model
std::uint32_t count
Json object
int limit
Definition TreeMesh.cpp:164
EVENGINE_API_FOUNDATION public API.
Definition Module.h:46
SQLite connection with a small ORM layer on top of Poco::Data. Tables/columns are quoted identifiers;...
Definition Database.h:70
int save(const Mapping< T > &mapping, const T &object)
ORM helper: persists one mapped object.
Definition Database.h:116
std::vector< Row > query(const std::string &sql)
Runs a SELECT and returns every row as name/value maps.
Definition Database.cpp:103
Connection & operator=(const Connection &)=delete
std::vector< Row > queryByKey(const std::string &table, const std::string &key, const Value &id)
Selects rows where key == id.
Definition Database.cpp:165
int insert(const std::string &table, const Row &values)
Inserts a row map; returns the affected row count.
Definition Database.cpp:121
Connection(const Connection &)=delete
int removeByKey(const std::string &table, const std::string &key, const Value &id)
Deletes a single row by primary key value.
Definition Database.cpp:161
int exportECS(const std::string &table, const Range &entities, Mapper mapper)
ORM helper: persists a range of mapped entities in one transaction.
Definition Database.h:124
int execute(const std::string &sql)
Executes a statement; returns the affected row count.
Definition Database.cpp:98
int updateByKey(const std::string &table, const Row &values, const std::string &key, const Value &id)
Updates a single row by primary key value.
Definition Database.cpp:157
Database module (eve.Database): SQLite connection factory. Script: db <- eve.Database(); conn <- db....
Definition Database.h:285
Database()=default
Constructs a Database.
Connection * connectSQLite(std::string path)
Opens a SQLite database file (":memory:" is supported).
Definition Database.cpp:260
~Database() override=default
Releases Database resources.
Connection * connect(std::string connector, std::string connectionString)
Opens a connection with an explicit Poco connector name.
Definition Database.cpp:257
Runtime ORM model exposed to Squirrel.
Definition Database.h:258
Composable filtered/sorted/paged query shared by C++ and scripts.
Definition Database.h:148
Typed active-record repository built from a Mapping<T>.
Definition Database.h:184
std::vector< T > all()
All.
Definition Database.h:208
std::vector< T > select(const std::function< void(Query &)> &configure)
Select.
Definition Database.h:236
int update(const T &object)
Updates update.
Definition Database.h:224
int insert(const T &object)
Inserts insert.
Definition Database.h:205
bool find(const Value &id, T &object)
Finds find.
Definition Database.h:216
void createTable(bool ifNotExists=true)
Creates table.
Definition Database.h:190
Repository(Connection &connection, Mapping< T > mapping)
Constructs a Repository.
Definition Database.h:187
int remove(const Value &id)
Removes remove.
Definition Database.h:233
std::unordered_map< std::string, Value > Row
Definition Database.h:27
std::variant< std::monostate, std::int64_t, double, std::string, bool > Value
Definition Database.h:26
A named field used by the small, explicit ORM mapping layer.
Definition Database.h:32
std::function< void(T &, const Value &)> write
Void.
Definition Database.h:37
std::string sqlType
Definition Database.h:38
std::string name
Definition Database.h:33
std::function< Value(const T &)> read
Value.
Definition Database.h:35
Mapping public API.
Definition Database.h:44
T fromRow(const Row &row) const
From row.
Definition Database.h:56
std::string table
Definition Database.h:45
std::vector< Field< T > > fields
Definition Database.h:46
Row toRow(const T &object) const
To row.
Definition Database.h:49