From 9bd42502f62125906706b49178e471ceb36db4c9 Mon Sep 17 00:00:00 2001
From: znone <glyc@sina.com.cn>
Date: Wed, 06 Jun 2018 05:30:54 +0000
Subject: [PATCH] 修正在处理MySQL结果集时,移动字符串时的问题。

---
 include/qtl_database_pool.hpp |    9 ++++
 include/qtl_common.hpp        |   31 ++++++++++++++-
 include/qtl_mysql.hpp         |   27 +++++++++++++
 3 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/include/qtl_common.hpp b/include/qtl_common.hpp
index df0c144..e0eb972 100644
--- a/include/qtl_common.hpp
+++ b/include/qtl_common.hpp
@@ -79,6 +79,31 @@
 	typedef StringT string_type;
 	typedef typename string_type::value_type char_type;
 	bind_string_helper(string_type&& value) : m_value(std::forward<string_type>(value)) { }
+	bind_string_helper(const bind_string_helper& src)
+		: m_value(std::forward<std::string>(src.m_value))
+	{
+	}
+	bind_string_helper(bind_string_helper&& src)
+		: m_value(std::forward<std::string>(src.m_value))
+	{
+	}
+	bind_string_helper& operator=(const bind_string_helper& src)
+	{
+		if (this != &src)
+		{
+			m_value = std::forward<std::string>(src.m_value);
+		}
+		return *this;
+	}
+	bind_string_helper& operator=(bind_string_helper&& src)
+	{
+		if (this != &src)
+		{
+			m_value = std::forward<std::string>(src.m_value);
+		}
+		return *this;
+	}
+
 	void clear() { m_value.clear(); }
 	char_type* alloc(size_t n) { m_value.resize(n); return (char_type*)m_value.data(); }
 	void truncate(size_t n) { m_value.resize(n); }
@@ -859,17 +884,17 @@
 	template<typename... ValueProc>
 	void query_multi(const char* query_text, size_t text_length, ValueProc&&... proc)
 	{
-		query_multi_with_params<std::tuple<>>(query_text, text_length, std::make_tuple(), std::forward<ValueProc>(proc)...);
+		query_multi_with_params<std::tuple<>, ValueProc...>(query_text, text_length, std::make_tuple(), std::forward<ValueProc>(proc)...);
 	}
 	template<typename... ValueProc>
 	void query_multi(const char* query_text, ValueProc&&... proc)
 	{
-		query_multi_with_params<std::tuple<>>(query_text, strlen(query_text), std::make_tuple(), std::forward<ValueProc>(proc)...);
+		query_multi_with_params<std::tuple<>, ValueProc...>(query_text, strlen(query_text), std::make_tuple(), std::forward<ValueProc>(proc)...);
 	}
 	template<typename... ValueProc>
 	void query_multi(const std::string& query_text, ValueProc&&... proc)
 	{
-		query_multi_with_params<std::tuple<>>(query_text.data(), query_text.size(), std::make_tuple(), std::forward<ValueProc>(proc)...);
+		query_multi_with_params<std::tuple<>, ValueProc...>(query_text.data(), query_text.size(), std::make_tuple(), std::forward<ValueProc>(proc)...);
 	}
 
 	template<typename Params, typename Values>
diff --git a/include/qtl_database_pool.hpp b/include/qtl_database_pool.hpp
index 1d04e2f..73ca349 100644
--- a/include/qtl_database_pool.hpp
+++ b/include/qtl_database_pool.hpp
@@ -29,7 +29,14 @@
 		if(m_background_thread.joinable())
 		{
 			m_stop_thread=true;
-			m_background_thread.join();
+			try
+			{
+				m_background_thread.join();
+			}
+			catch (std::system_error&)
+			{
+				//igore the error
+			}
 		}
 		clear();
 	}
diff --git a/include/qtl_mysql.hpp b/include/qtl_mysql.hpp
index 3d59a8b..bf0ee64 100644
--- a/include/qtl_mysql.hpp
+++ b/include/qtl_mysql.hpp
@@ -70,6 +70,12 @@
 	{
 		bind();
 	}
+	void bind(bool& v)
+	{
+		init();
+		buffer_type = MYSQL_TYPE_TINY;
+		buffer = &v;
+	}
 	void bind(int8_t& v)
 	{
 		init();
@@ -188,7 +194,9 @@
 class error : public std::exception
 {
 public:
+	error() : m_error(0) { }
 	error(int err, const char* errmsg) : m_error(err), m_errmsg(errmsg) { }
+	explicit error(int err) : m_error(err), m_errmsg(ER(err)) { }
 	explicit error(statement& stmt);
 	explicit error(database& db);
 	error(const error& src) = default;
@@ -363,6 +371,17 @@
 			if(field==NULL) throw_exception();
 			value.clear();
 			typename bind_string_helper<T>::char_type* data=value.alloc(field->length);
+			m_binderAddins[index].m_before_fetch = [this, value](binder& b) mutable {
+				if (value.size() < b.buffer_length)
+				{
+					value.alloc(b.buffer_length);
+					if (b.buffer != value.data())
+					{
+						b.buffer = const_cast<char*>(value.data());
+						mysql_stmt_bind_result(m_stmt, &m_binders.front());
+					}
+				}
+			};
 			m_binderAddins[index].m_after_fetch= [value](const binder& b) mutable {
 				if(*b.is_null) value.clear();
 				else value.truncate(*b.length);
@@ -441,6 +460,11 @@
 
 	bool fetch()
 	{
+		for (size_t i = 0; i != m_binders.size(); i++)
+		{
+			if (m_binderAddins[i].m_before_fetch)
+				m_binderAddins[i].m_before_fetch(m_binders[i]);
+		}
 		int err=mysql_stmt_fetch(m_stmt);
 		if(err==0 || err==MYSQL_DATA_TRUNCATED)
 		{
@@ -511,6 +535,7 @@
 		my_bool m_isNull;
 		my_bool m_error;
 		bool is_truncated;
+		std::function<void(binder&)> m_before_fetch;
 		std::function<void(const binder&)> m_after_fetch;
 	};
 	std::vector<binder_addin> m_binderAddins;
@@ -552,6 +577,8 @@
 class database final : public qtl::base_database<database, statement>
 {
 public:
+	typedef error exception_type;
+
 	database()
 	{
 		m_mysql=mysql_init(NULL);

--
Gitblit v1.9.3