forked from qicosmos/ormpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dbng.hpp
211 lines (177 loc) · 6.77 KB
/
dbng.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
//
// Created by qiyu on 11/3/17.
//
#ifndef ORM_DBNG_HPP
#define ORM_DBNG_HPP
#include <string>
#include <string_view>
#include <vector>
#include <functional>
#include <chrono>
#include "utility.hpp"
namespace ormpp{
template<typename DB>
class dbng{
public:
~dbng(){
disconnect();
}
template <typename... Args>
bool connect(Args&&... args){
return db_.connect(std::forward<Args>(args)...);
}
bool disconnect(){
return db_.disconnect();
}
template<typename T, typename... Args>
bool create_datatable(Args&&... args){
return db_.template create_datatable<T>(std::forward<Args>(args)...);
}
template<typename T, typename... Args>
int insert(const T& t,Args&&... args){
return db_.insert(t, std::forward<Args>(args)...);
}
template<typename T, typename... Args>
int insert(const std::vector<T>& t, Args&&... args){
return db_.insert(t, std::forward<Args>(args)...);
}
template<typename T, typename... Args>
int update(const T& t, Args&&... args) {
return db_.update(t, std::forward<Args>(args)...);
}
template<typename T, typename... Args>
int update(const std::vector<T>& t, Args&&... args){
return db_.update(t, std::forward<Args>(args)...);
}
template<typename T, typename... Args>
bool delete_records(Args&&... where_conditon){
return db_.template delete_records<T>(std::forward<Args>(where_conditon)...);
}
//restriction, all the args are string, the first is the where condition, rest are append conditions
template<typename T, typename... Args>
std::vector<T> query(Args&&... args){
return db_.template query<T>(std::forward<Args>(args)...);
}
//support member variable, such as: query(FID(simple::id), "<", 5)
template<typename Pair, typename U>
auto query(Pair pair, std::string_view oper, U&& val){
auto sql = build_condition(pair, oper, std::forward<U>(val));
using T = typename ormpp::field_attribute<decltype(pair.second)>::type;
return query<T>(sql);
}
template<typename Pair, typename U>
bool delete_records(Pair pair, std::string_view oper, U&& val){
auto sql = build_condition(pair, oper, std::forward<U>(val));
using T = typename ormpp::field_attribute<decltype(pair.second)>::type;
return delete_records<T>(sql);
}
bool execute(const std::string& sql){
return db_.execute(sql);
}
//transaction
bool begin(){
return db_.begin();
}
bool commit(){
return db_.commit();
}
bool rollback(){
return db_.rollback();
}
bool ping() {
return db_.ping();
}
bool has_error() {
return db_.has_error();
}
std::string get_last_error() const {
return db_.get_last_error();
}
int get_last_affect_rows() {
return db_.get_last_affect_rows();
}
private:
template<typename Pair, typename U>
auto build_condition(Pair pair, std::string_view oper, U&& val){
std::string sql = "";
using T = typename field_attribute<decltype(pair.second)>::type;
using V = std::remove_const_t<std::remove_reference_t<U>>;
//if field type is numeric, return type of val is numeric, to string; val is string, no change;
//if field type is string, return type of val is numeric, to string and add ''; val is string, add '';
using return_type = typename field_attribute<decltype(pair.second)>::return_type;
if constexpr(std::is_arithmetic_v<return_type>&&std::is_arithmetic_v<V>){
append(sql, pair.first, oper, std::to_string(std::forward<U>(val)));
}
else if constexpr(!std::is_arithmetic_v<return_type>){
if constexpr(std::is_arithmetic_v<V>)
append(sql, pair.first, oper, to_str(std::to_string(std::forward<U>(val))));
else
append(sql, pair.first, oper, to_str(std::forward<U>(val)));
}
else{
append(sql, pair.first, oper, std::forward<U>(val));
}
return sql;
}
#define HAS_MEMBER(member)\
template<typename T, typename... Args>\
struct has_##member\
{\
private:\
template<typename U> static auto Check(int) -> decltype(std::declval<U>().member(std::declval<Args>()...), std::true_type()); \
template<typename U> static std::false_type Check(...);\
public:\
enum{value = std::is_same<decltype(Check<T>(0)), std::true_type>::value};\
};
HAS_MEMBER(before)
HAS_MEMBER(after)
#define WRAPER(func)\
template<typename... AP, typename... Args>\
auto wraper##_##func(Args&&... args){\
using result_type = decltype(std::declval<decltype(this)>()->func(std::declval<Args>()...));\
bool r = true;\
std::tuple<AP...> tp{};\
for_each_l(tp, [&r, &args...](auto& item){\
if(!r)\
return;\
if constexpr (has_before<decltype(item)>::value)\
r = item.before(std::forward<Args>(args)...);\
}, std::make_index_sequence<sizeof...(AP)>{});\
if(!r)\
return result_type{};\
auto lambda = [this, &args...]{ return this->func(std::forward<Args>(args)...); };\
result_type result = std::invoke(lambda);\
for_each_r(tp, [&r, &result, &args...](auto& item){\
if(!r)\
return;\
if constexpr (has_after<decltype(item), result_type>::value)\
r = item.after(result, std::forward<Args>(args)...);\
}, std::make_index_sequence<sizeof...(AP)>{});\
return result;\
}
template <typename... Args, typename F, std::size_t... Idx>
constexpr void for_each_l(std::tuple<Args...>& t, F&& f, std::index_sequence<Idx...>)
{
(std::forward<F>(f)(std::get<Idx>(t)), ...);
}
template <typename... Args, typename F, std::size_t... Idx>
constexpr void for_each_r(std::tuple<Args...>& t, F&& f, std::index_sequence<Idx...>)
{
constexpr auto size = sizeof...(Idx);
(std::forward<F>(f)(std::get<size-Idx-1>(t)), ...);
}
public:
WRAPER(connect);
WRAPER(execute);
void update_operate_time(){
latest_tm_ = std::chrono::system_clock::now();
}
auto get_latest_operate_time(){
return latest_tm_;
}
private:
DB db_;
std::chrono::system_clock::time_point latest_tm_ = std::chrono::system_clock::now();
};
}
#endif //ORM_DBNG_HPP