From 8d787261f12dfe711bc3bb4e088bf9bf42592b49 Mon Sep 17 00:00:00 2001
From: znone <glyc@sina.com.cn>
Date: Tue, 11 Sep 2018 03:07:25 +0000
Subject: [PATCH] 可以通过 qtl::custom_bind 把不同数据集用不同的绑定函数绑定到同一结构。
---
include/qtl_common.hpp | 83 +++++++++++++++++++++++++++++++++++++++++
include/apply_tuple.h | 12 ++++++
README.md | 25 +++++++++++-
3 files changed, 118 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 06806b7..f800776 100644
--- a/README.md
+++ b/README.md
@@ -102,7 +102,7 @@
}
```
#### 8. 指示器
-可以用指示器获取查询结果的更多信息。指示器包含以下成员:
+可以用指示器(indicator)获取查询结果的更多信息。指示器包含以下成员:
- data 存储字段的数据
- is_null 字段是否为空
- length 数据的实际长度
@@ -127,7 +127,28 @@
```
-#### 10.处理返回多个结果集的查询
+#### 10. 在不同查询中复用同一数据结构
+通常希望复用结构,将其绑定到多个不同的查询的结果集,这时候 qtl::bind_record就不够用了。需要利用 qtl::custom_bind 实现不同的绑定函数才能实现这一需求。有如下绑定函数:
+
+```C++
+void my_bind(TestMysqlRecord&& v, qtl::sqlite::statement& command)
+{
+ qtl::bind_field(command, "id", v.id);
+ qtl::bind_field(command, 1, v.name);
+ qtl::bind_field(command, 2, v.create_time);
+}
+```
+以下代码说明如何将其用于查询:
+```C++
+db->query_explicit("select * from test where id=?", id,
+ qtl::custom_bind(TestMysqlRecord(), &my_bind),
+ [](const TestMysqlRecord& record) {
+ printf("ID=\"%d\", Name=\"%s\"\n", record.id, record.name);
+ });
+```
+qtl::bind_record不是唯一的方法。通过派生类也能实现类似的需求(qtl::record_with_tag)。
+
+#### 11.处理返回多个结果集的查询
有些查询语句会返回多个结果集。使用函数query执行这些查询只能得到第一个结果集。要处理所有结果集需要使用query_multi或query_multi_with_params。query_multi不会为没有结果集的查询调用回调函数。例如:
```SQL
CREATE PROCEDURE test_proc()
diff --git a/include/apply_tuple.h b/include/apply_tuple.h
index 6857925..2f47dbc 100644
--- a/include/apply_tuple.h
+++ b/include/apply_tuple.h
@@ -6,6 +6,8 @@
#include <type_traits>
#include <utility>
+#if __cplusplus < 201703L
+
namespace detail
{
template<size_t N>
@@ -46,4 +48,14 @@
>::value>::apply_tuple(std::forward<F>(f), std::forward<T>(t));
}
+#else
+
+template <class F, class Tuple>
+inline constexpr decltype(auto) apply_tuple(F&& f, Tuple&& t)
+{
+ return std::apply(std;:forward<F>(f), std::forward<Tuple>(t));
+}
+
+#endif // C++17
+
#endif //_APPLY_TUPLE_H_
diff --git a/include/qtl_common.hpp b/include/qtl_common.hpp
index eb616a1..6388a17 100644
--- a/include/qtl_common.hpp
+++ b/include/qtl_common.hpp
@@ -278,6 +278,12 @@
command.bind_field(index, value, length);
}
+template<typename Command, typename T>
+inline void bind_field(Command& command, const char* name, std::reference_wrapper<T>&& value)
+{
+ return bind_field(command, value.get());
+}
+
namespace detail
{
@@ -618,6 +624,15 @@
}
};
+template<typename Command, typename T>
+struct record_binder<Command, std::reference_wrapper<T>>
+{
+ inline void operator()(Command& command, std::reference_wrapper<T>&& value) const
+ {
+ bind_field(command, static_cast<size_t>(0), std::forward<typename std::remove_reference<T>::type>(value.get()));
+ }
+};
+
template<typename Command, typename... Types>
struct record_binder<Command, std::tuple<Types...>>
{
@@ -643,6 +658,74 @@
{
};
+template<typename T, typename Pred>
+struct custom_binder_type : public T
+{
+ typedef T value_type;
+
+ explicit custom_binder_type(Pred pred) : m_pred(pred) { }
+ custom_binder_type(value_type&& v, Pred pred)
+ : value_type(std::forward<value_type>(v)), m_pred(pred)
+ {
+ }
+ template<typename... Args>
+ custom_binder_type(Pred pred, Args&&... args)
+ : value_type(std::forward<Args>(args)...), m_pred(pred)
+ {
+ }
+
+ template<typename Command>
+ void bind(Command& command)
+ {
+ m_pred(std::forward<T>(*this), command); // Pred maybe member function
+ }
+
+private:
+ Pred m_pred;
+};
+
+template<typename T, typename Pred>
+struct custom_binder_type<std::reference_wrapper<T>, Pred> : public std::reference_wrapper<T>
+{
+ typedef std::reference_wrapper<T> value_type;
+
+ explicit custom_binder_type(Pred pred) : m_pred(pred) { }
+ custom_binder_type(value_type&& v, Pred pred)
+ : value_type(std::forward<value_type>(v)), m_pred(pred)
+ {
+ }
+ template<typename... Args>
+ custom_binder_type(Pred pred, Args&&... args)
+ : T(std::forward<Args>(args)...), m_pred(pred)
+ {
+ }
+
+ template<typename Command>
+ void bind(Command& command)
+ {
+ m_pred(std::forward<T>(*this), command); // Pred maybe member function
+ }
+
+private:
+ Pred m_pred;
+};
+
+
+template<typename T, typename Pred>
+inline custom_binder_type<T, Pred> custom_bind(T&& v, Pred pred)
+{
+ return custom_binder_type<T, Pred>(std::forward<T>(v), pred);
+}
+
+template<typename Command, typename T, typename Pred>
+struct record_binder<Command, custom_binder_type<T, Pred>>
+{
+ void operator()(Command& command, custom_binder_type<T, Pred>&& values) const
+ {
+ values.bind(command);
+ }
+};
+
template<typename Command, typename T>
inline void bind_record(Command& command, T&& value)
{
--
Gitblit v1.9.3