acl  3.5.3.0
db_handle.hpp
浏览该文件的文档.
1 #pragma once
2 #include "../acl_cpp_define.hpp"
3 #include <vector>
4 #include "../stdlib/string.hpp"
5 #include "../stdlib/noncopyable.hpp"
6 #include "../connpool/connect_client.hpp"
7 
8 #if !defined(ACL_DB_DISABLE)
9 
10 namespace acl {
11 
12 /**
13  * 数据库查询结果集的行记录类型定义
14  */
16 {
17 public:
18  /**
19  * 构造函数
20  * @param names {const std::vector<const char*>&} 数据库表中字段名列表
21  */
22  db_row(const std::vector<const char*>& names);
23  ~db_row(void);
24 
25  /**
26  * 取得数据表中的某个对应下标值的字段名
27  * @param ifield {size_t} 下标值
28  * @return {const char*} 返回空说明该下标值越界
29  */
30  const char* field_name(size_t ifield) const;
31 
32  /**
33  * 从查询结果的记录行中根据字段名取得相应的字段值
34  * @param name {const char*} 数据表的字段名
35  * @return {const char*} 对应的字段值,为空则表示字段值不存在或
36  * 字段名非法
37  */
38  const char* field_value(const char* name) const;
39 
40  /**
41  * 从查询结果的记录行中根据字段名取得相应的字段值,
42  * 功能与 field_value 相同
43  * @param name {const char*} 数据表的字段名
44  * @return {const char*} 对应的字段值,为空则表示字段值不存在或
45  * 字段名非法
46  */
47  const char* operator[](const char* name) const;
48 
49  /**
50  * 从查询结果的记录行中取得对应下标的字段值
51  * @param ifield {size_t} 下标值,该值应 < 字段名的个数
52  * @return {const char*} 对应的字段值,为空则表示下标值非法或
53  * 字段值不存在
54  */
55  const char* field_value(size_t ifield) const;
56 
57  /**
58  * 从查询结果的记录行中取得对应下标的字段值,功能与 field_value 相同
59  * @param ifield {size_t} 下标值,该值应 < 字段名的个数
60  * @return {const char*} 对应的字段值,为空则表示下标值非法或
61  * 字段值不存在
62  */
63  const char* operator[](size_t ifield) const;
64 
65  /**
66  * 从查询结果的记录行中取得对应下标的整数类型的字段值
67  * @param ifield {size_t} 下标值
68  * @param null_value {int} 当结果为空时,返回此值表示未有相应结果
69  * @return {int} 当返回值与用户输入的 null_value 相同表明没有查到结果
70  */
71  int field_int(size_t ifield, int null_value = 0) const;
72 
73  /**
74  * 从查询结果的记录行中取得字段名的整数类型的字段值
75  * @param name {const char*} 下标值
76  * @param null_value {int} 当结果为空时,返回此值表示未有相应结果
77  * @return {int} 当返回值与用户输入的 null_value 相同表明没有查到结果
78  */
79  int field_int(const char* name, int null_value = 0) const;
80 
81 
82  /**
83  * 从查询结果的记录行中取得对应下标的整数类型的字段值
84  * @param ifield {size_t} 下标值
85  * @param null_value {acl_int64} 当结果为空时,返回此值表示未有相应结果
86  * @return {acl_int64} 当返回值与用户输入的 null_value 值相同时表明
87  * 没有查到结果
88  */
89 #if defined(_WIN32) || defined(_WIN64)
90  __int64 field_int64(size_t ifield, __int64 null_value = 0) const;
91 #else
92  long long int field_int64(size_t ifield,
93  long long int null_value = 0) const;
94 #endif
95 
96  /**
97  * 从查询结果的记录行中取得字段名的整数类型的字段值
98  * @param name {const char*} 下标值
99  * @param null_value {acl_int64} 当结果为空时,返回此值表示未有相应结果
100  * @return {acl_int64} 当返回值与用户输入的 null_value 值相同时表明
101  * 没有查到结果
102  */
103 #if defined(_WIN32) || defined(_WIN64)
104  __int64 field_int64(const char* name, __int64 null_value = 0) const;
105 #else
106  long long int field_int64(const char* name,
107  long long int null_value = 0) const;
108 #endif
109 
110  /**
111  * 从查询结果的记录行中取得字段名的浮点类型的字段值
112  * @param ifield {size_t} 下标值
113  * @param null_value {double} 当结果为空时,返回此值表示未有相应结果
114  * @return {double} 当返回值与用户输入的 null_value 值相同时表明没有
115  * 查到结果
116  */
117  double field_double(size_t ifield, double null_value = 0.0) const;
118 
119  /**
120  * 从查询结果的记录行中取得字段名的浮点类型的字段值
121  * @param name {const char*} 下标值
122  * @param null_value {double} 当结果为空时,返回此值表示未有相应结果
123  * @return {double} 当返回值与用户输入的 null_value 值相同时表明没有
124  * 查到结果
125  */
126  double field_double(const char* name, double null_value = 0.0) const;
127 
128  /**
129  * 从查询结果的记录行中取得对应下标的字符串类型的字段值
130  * @param ifield {size_t} 下标值
131  * @return {const char*} 当返回值 NULL 时表明没有查到结果
132  */
133  const char* field_string(size_t ifield) const;
134 
135  /**
136  * 从查询结果的记录行中取得字段名的字符串类型的字段值
137  * @param name {const char*} 下标值
138  * @return {const char*} 当返回值 NULL 时表明没有查到结果
139  */
140  const char* field_string(const char* name) const;
141 
142  /**
143  * 从查询结果的记录行中取得对应下标的字符串类型的字段值长度
144  * @param ifield {size_t} 下标值
145  * @return {size_t}
146  */
147  size_t field_length(size_t ifield) const;
148  /**
149  * 从查询结果的记录行中取得字段名的字符串类型的字段值长度
150  * @param name {const char*} 下标值
151  * @return {size_t}
152  */
153  size_t field_length(const char* name) const;
154 
155  /**
156  * 向记录行添加一个字段值,添加字段值的顺序应该与字段名的顺序一致
157  * @param value {const char*} 该行记录的某个字段值
158  * @param len {size_t} value 数据长度
159  */
160  void push_back(const char* value, size_t len);
161 
162  /**
163  * 行记录中字段值的个数
164  * @return {size_t}
165  */
166  size_t length(void) const;
167 
168  /**
169  * 清除结果值(即 values_)
170  */
171  void clear(void);
172 
173 private:
174  // 数据表的字段名集合的引用
175  const std::vector<const char*>& names_;
176 
177  // 数据结果行的字段集合
178  std::vector<const char*> values_;
179 
180  // 数据结果行字段长度集合
181  std::vector<size_t> lengths_;
182 };
183 
184 /**
185  * 数据库查询结果的行记录集合类型定义
186  */
188 {
189 public:
190  db_rows();
191  virtual ~db_rows();
192 
193  /**
194  * 从查询的行记录集合中根据表字段名对应的字段值取出结果记录集合
195  * @param name {const char*} 数据表字段名(不区分大小写)
196  * @param value {const char*} 数据表字段值(区分大小写)
197  * @return {const std::vector<const db_row*>&} 返回行记录集合类型对象,
198  * 可以通过调用 db_rows.empty() 来判断结果是否为空
199  */
200  const std::vector<const db_row*>& get_rows(
201  const char* name, const char* value);
202 
203  /**
204  * 取得所有的查询结果集
205  * @return {const std::vector<db_row*>&} 返回行记录集合类型对象,
206  * 可以通过调用 db_rows.empty() 来判断结果是否为空
207  */
208  const std::vector<db_row*>& get_rows() const;
209 
210  /**
211  * 从查询的行记录集合中根据索引下标取得对应的某行记录
212  * @param idx {size_t} 索引下标,该值应该 < 结果集大小
213  * @return {const db_row*} 返回空表示输入下标值非法或字段值本身
214  * 为空
215  */
216  const db_row* operator[](size_t idx) const;
217 
218  /**
219  * 判断结果集是否为空
220  * @return {bool} 是否为空
221  */
222  bool empty() const;
223 
224  /**
225  * 结果集的行记录个数
226  * @return {size_t} 行记录个数
227  */
228  size_t length() const;
229 
230 public:
231  // 数据表字段名
232  std::vector<const char*> names_;
233 
234  // 查询结果行集合,其中的元素 db_row 必须是动态添加进去的,
235  // 因为在本类对象析构时会自动 delete rows_ 中的所有元素对象
236  std::vector<db_row*> rows_;
237 
238  // 临时结果行集合
239  std::vector<const db_row*> rows_tmp_;
240 
241  // 存储临时结果集对象
242  void* result_tmp_;
243 
244  // 用来释放临时结果集对象
245  void (*result_free)(void* result);
246 };
247 
248 class db_pool;
249 class query;
250 
251 /**
252  * 数据库操作句柄对象类型
253  */
255 {
256 public:
257  db_handle(void);
258  virtual ~db_handle(void);
259 
260  /////////////////////////////////////////////////////////////////////
261 
262  /**
263  * 基类 connect_client 虚函数的实现
264  * @return {bool} 打开数据库连接是否成功
265  */
266  bool open();
267 
268  /////////////////////////////////////////////////////////////////////
269 
270  /**
271  * 返回数据库的类型描述
272  * @return {const char*}
273  */
274  virtual const char* dbtype() const = 0;
275 
276  /**
277  * 获得上次数据库操作的出错错误号
278  * @return {int}
279  */
280  virtual int get_errno() const
281  {
282  return -1;
283  }
284 
285  /**
286  * 获得上次数据库操作的出错错描述
287  * @return {const char*}
288  */
289  virtual const char* get_error() const
290  {
291  return "unkonwn error";
292  }
293 
294  /**
295  * 纯虚接口,子类必须实现此接口用于打开数据库
296  * @param charset {const char*} 打开数据库连接时采用的字符集
297  * @return {bool} 打开是否成功
298  */
299  virtual bool dbopen(const char* charset = NULL) = 0;
300 
301  /**
302  * 数据库是否已经打开了
303  * @return {bool} 返回 true 表明数据库已经打开了
304  */
305  virtual bool is_opened() const = 0;
306 
307  /**
308  * 纯虚接口,子类必须实现此接口用于判断数据表是否存在
309  * @return {bool} 是否存在
310  */
311  virtual bool tbl_exists(const char* tbl_name) = 0;
312 
313  /**
314  * 纯虚接口,子类必须实现此接口用于关闭数据库
315  * @return {bool} 关闭是否成功
316  */
317  virtual bool close() = 0;
318 
319  /**
320  * 纯虚接口,子类必须实现此接口用于执行 SELECT SQL 语句
321  * @param sql {const char*} 标准的 SQL 语句,非空,并且一定得要注意该
322  * SQL 语句必须经过转义处理,以防止 SQL 注入攻击
323  * @param result {db_rows*} 如果非空,则将查询结果填充进该结果对象中,
324  * 否则,会引用 db_handle 内部的一个临时存储对象
325  * @return {bool} 执行是否成功
326  */
327  virtual bool sql_select(const char* sql, db_rows* result = NULL) = 0;
328 
329  /**
330  * 纯虚接口,子类必须实现此接口用于执行 INSERT/UPDATE/DELETE SQL 语句
331  * @param sql {const char*} 标准的 SQL 语句,非空,并且一定得要注意该
332  * SQL 语句必须经过转义处理,以防止 SQL 注入攻击
333  * @return {bool} 执行是否成功
334  */
335  virtual bool sql_update(const char* sql) = 0;
336 
337  /**
338  * 开始执行事务
339  * @return {bool}
340  */
341  virtual bool begin_transaction() { return false; }
342 
343  /**
344  * 提交事务
345  * @return {bool}
346  */
347  virtual bool commit() { return false; }
348 
349  /**
350  * 事务回滚
351  * @return {bool}
352  */
353  virtual bool rollback() { return false; }
354 
355  /**
356  * 更安全易用的查询过程,调用此函数功能等同于 sql_select,只是查询
357  * 对象 query 构建的 sql 语句是安全的,可以防止 sql 注入,该方法
358  * 执行 SELECT SQL 语句
359  * @param query {query&}
360  * @param result {db_rows*} 如果非空,则将查询结果填充进该结果对象中,
361  * 否则,会引用 db_handle 内部的一个临时存储对象
362  * @return {bool} 执行是否成功
363  */
364  bool exec_select(query& query, db_rows* result = NULL);
365 
366  /**
367  * 更安全易用的更新过程,调用此函数功能等同于 sql_update,只是查询
368  * 对象 query 构建的 sql 语句是安全的,可以防止 sql 注入,该方法
369  * 执行 INSERT/UPDATE/DELETE SQL 语句
370  * @param query {query&}
371  * @return {bool} 执行是否成功
372  */
373  bool exec_update(query& query);
374 
375  /**
376  * 虚接口,为防止 sql 注入,用户应针对字符串字段调用此函数将一些特殊
377  * 字符进行转义,该接口对常见的特殊字符进行了转义,子类也可以实现自己
378  * 的转义方法
379  * @param in {const char*} 输入字符串
380  * @param len {size_t} 字符串长度
381  * @param out {string&} 存储转换结果
382  * @return {string&} 子类应该返回输入的缓冲区的引用,以便于用户在拼接
383  * SQL 的时候比较方便
384  */
385  virtual string& escape_string(const char* in, size_t len, string& out);
386 
387  /**
388  * 上次 sql 操作影响的记录行数
389  * @return {int} 影响的行数,-1 表示出错
390  */
391  virtual int affect_count() const = 0;
392 
393  /////////////////////////////////////////////////////////////////////
394 
395  /**
396  * 获得执行 SQL 语句后的结果
397  * @return {const db_rows*},返回结果若非空,则用完后需要调用
398  * free_result() 以释放结果对象
399  */
400  const db_rows* get_result() const;
401 
402  /**
403  * 从查询的行记录集合中根据表字段名对应的字段值取出结果记录集合
404  * @param name {const char*} 数据表字段名(不区分大小写)
405  * @param value {const char*} 数据表字段值(区分大小写)
406  * @return {const std::vector<const db_row*>*} 返回行记录集合类型对象,
407  * 若返回结果集非空,则必须调用 free_result() 以释放结果对象
408  */
409  const std::vector<const db_row*>* get_rows(
410  const char* name, const char* value);
411 
412  /**
413  * 取得所有的查询结果集
414  * @return {const std::vector<db_row*>*} 返回行记录集合类型对象,
415  * 若返回结果集非空,则必须调用 free_result() 以释放结果对象
416  */
417  const std::vector<db_row*>* get_rows() const;
418 
419  /**
420  * 获得执行 SQL 语句后的第一行结果,针对唯一键的数据查询比较方便
421  * @return {const db_row*} 返回空表示查询结果为空,否则, 则必须调用
422  * free_result() 函数来释放中间的结果内存,否则会引起内存泄露
423  */
424  const db_row* get_first_row() const;
425 
426  /**
427  * 释放上次查询的结果,当查询完成后,调用该函数来释放上次查询的结果,该函数被
428  * 多次调用并无害处,因为当第一次调用时会自动将内部变量 result_ 置空,
429  * 另外,要求子类必须在每次执行 SQL 查询前先调用此方法,以免用户忘记
430  * 调用而造成内存泄露;此外,本类对象在析构时会自动再调用本方法释放可能
431  * 未释放的内存
432  */
433  void free_result();
434 
435  /**
436  * 获得某个对应下标值的行记录
437  * @param idx {size_t} 下标值,必须小于查询结果的总数
438  * @return {const db_row*} 结果,如果为空,则有可能是下标越界,
439  * 也有可能是结果为空
440  */
441  const db_row* operator[](size_t idx) const;
442 
443  /**
444  * 取得查询(sql_select)结果的行记录数
445  * @return {size_t} 结果行记录数,若为 0 则表示结果为空
446  */
447  size_t length() const;
448 
449  /**
450  * 查询(sql_select)执行完后结果是否为空
451  * @return {bool} 返回 true 表示查询结果为空
452  */
453  bool empty() const;
454 
455  /**
456  * 输出数据库查询结果
457  * @param max {size_t} 输出至屏幕的行记录数的最大值限制,如果该值为 0
458  * 则输出所有的结果集
459  */
460  void print_out(size_t max = 0) const;
461 
462  /////////////////////////////////////////////////////////////////
463  /**
464  * 设置本实例的唯一 ID
465  * @param id {const char*} 唯一 ID
466  * @return {db_handle&}
467  */
468  db_handle& set_id(const char* id);
469 
470  /**
471  * 获得本实例的唯一 ID
472  * @return {const char*} 为空时,表示未曾设置过唯一ID
473  */
474  const char* get_id() const
475  {
476  return id_;
477  }
478 
479  /**
480  * 设置本数据库连接句柄当前被使用的时间
481  * @param now {time_t}
482  * @return {db_handle&}
483  */
484  db_handle& set_when(time_t now);
485 
486  /**
487  * 获得该连接句柄上次被使用的时间
488  * @return {time_t}
489  */
490  time_t get_when() const
491  {
492  return when_;
493  }
494 
495  /**
496  * 当采用动态加载方式加载动态库时,可以使用此函数设置动态库的加载全路径
497  */
498  static void set_loadpath(const char* path);
499 
500  /**
501  * 当设置了动态库的动态加载全路径时,可以通过本函数获得动态库加载全路径
502  * @return {const char*} 当未设置时则返回 NULL
503  */
504  static const char* get_loadpath();
505 
506 protected:
507  // 临时结果对象
509 
510  // 实例唯一 ID
511  char* id_;
512 
513  // 该数据库连接句柄最近被使用的时间
514  time_t when_;
515 };
516 
517 } // namespace acl
518 
519 #endif // !defined(ACL_DB_DISABLE)
virtual bool rollback()
Definition: db_handle.hpp:353
HTTP_API void const char * name
Definition: lib_http.h:620
db_rows * result_
Definition: db_handle.hpp:508
std::vector< const char * > names_
Definition: db_handle.hpp:232
void * result_tmp_
Definition: db_handle.hpp:242
virtual int get_errno() const
Definition: db_handle.hpp:280
std::vector< const db_row * > rows_tmp_
Definition: db_handle.hpp:239
virtual bool commit()
Definition: db_handle.hpp:347
const char * get_id() const
Definition: db_handle.hpp:474
virtual bool begin_transaction()
Definition: db_handle.hpp:341
time_t get_when() const
Definition: db_handle.hpp:490
std::vector< db_row * > rows_
Definition: db_handle.hpp:236
#define ACL_CPP_API
virtual const char * get_error() const
Definition: db_handle.hpp:289