From abf49b44cc47f39d6cceb83866f915bc03b7d900 Mon Sep 17 00:00:00 2001
From: Ferenc Szontágh <szf@fsociety.hu>
Date: Mon, 01 Jul 2024 18:08:34 +0000
Subject: [PATCH] reformat files

---
 include/qtl_mysql.hpp | 3559 ++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 1,801 insertions(+), 1,758 deletions(-)

diff --git a/include/qtl_mysql.hpp b/include/qtl_mysql.hpp
index 2b39807..c07ec69 100644
--- a/include/qtl_mysql.hpp
+++ b/include/qtl_mysql.hpp
@@ -18,1722 +18,1760 @@
 #include "qtl_common.hpp"
 #include "qtl_async.hpp"
 
-#if LIBMYSQL_VERSION_ID >=80000
+#if LIBMYSQL_VERSION_ID >= 80000
 typedef bool my_bool;
-#endif //MySQL 8
+#endif // MySQL 8
 
 #ifdef MARIADB_VERSION_ID
 #define IS_LONGDATA(t) ((t) >= MYSQL_TYPE_TINY_BLOB && (t) <= MYSQL_TYPE_STRING)
-#endif //MariaDB
+#endif // MariaDB
 
 namespace qtl
 {
 
-namespace mysql
-{
+	namespace mysql
+	{
 
-struct init
-{
-	init(int argc=-1, char **argv=nullptr, char **groups=nullptr) 
-	{
-		//my_init();
-		mysql_library_init(argc, argv, groups);
-	}
-	~init()
-	{
-		mysql_library_end();
-	}
-};
-
-struct thread_init
-{
-	thread_init()
-	{
-		mysql_thread_init();
-	}
-	~thread_init()
-	{
-		mysql_thread_end();
-	}
-};
-
-class binder : public MYSQL_BIND
-{
-	friend class statement;
-public:
-	binder()
-	{
-		init();
-	}
-	void init()
-	{
-		memset(this, 0, sizeof(MYSQL_BIND));
-	}
-	void bind()
-	{
-		init();
-		buffer_type=MYSQL_TYPE_NULL;
-	}
-	void bind(null)
-	{
-		bind();
-	}
-	void bind(std::nullptr_t)
-	{
-		bind();
-	}
-	void bind(bool& v)
-	{
-		init();
-		buffer_type = MYSQL_TYPE_BIT;
-		buffer = &v;
-		buffer_length = 1;
-	}
-	void bind(int8_t& v)
-	{
-		init();
-		buffer_type=MYSQL_TYPE_TINY;
-		buffer=&v;
-	}
-	void bind(uint8_t& v)
-	{
-		init();
-		buffer_type=MYSQL_TYPE_TINY;
-		buffer=&v;
-		is_unsigned=true;
-	}
-	void bind(int16_t& v)
-	{
-		init();
-		buffer_type=MYSQL_TYPE_SHORT;
-		buffer=&v;
-	}
-	void bind(uint16_t& v)
-	{
-		init();
-		buffer_type=MYSQL_TYPE_SHORT;
-		buffer=&v;
-		is_unsigned=true;
-	}
-	void bind(int32_t& v)
-	{
-		init();
-		buffer_type=MYSQL_TYPE_LONG;
-		buffer=&v;
-	}
-	void bind(uint32_t& v)
-	{
-		init();
-		buffer_type=MYSQL_TYPE_LONG;
-		buffer=&v;
-		is_unsigned=true;
-	}
-	void bind(int64_t& v)
-	{
-		init();
-		buffer_type=MYSQL_TYPE_LONGLONG;
-		buffer=&v;
-	}
-	void bind(uint64_t& v)
-	{
-		init();
-		buffer_type=MYSQL_TYPE_LONGLONG;
-		buffer=&v;
-		is_unsigned=true;
-	}
-	void bind(double& v)
-	{
-		init();
-		buffer_type=MYSQL_TYPE_DOUBLE;
-		buffer=&v;
-	}
-	void bind(float& v)
-	{
-		init();
-		buffer_type=MYSQL_TYPE_FLOAT;
-		buffer=&v;
-	}
-	void bind(MYSQL_TIME& v, enum_field_types type=MYSQL_TYPE_TIMESTAMP)
-	{
-		init();
-		buffer_type=type;
-		buffer=&v;
-	}
-	void bind(void* data, unsigned long length, enum_field_types type=MYSQL_TYPE_BLOB)
-	{
-		init();
-		buffer_type=type;
-		buffer=data;
-		buffer_length=length;
-	}
-	void bind(const const_blob_data& data, enum_field_types type=MYSQL_TYPE_BLOB)
-	{
-		init();
-		buffer_type=type;
-		buffer=const_cast<void*>(data.data);
-		buffer_length=data.size;
-	}
-	void bind(blob_data& data, enum_field_types type=MYSQL_TYPE_BLOB)
-	{
-		init();
-		buffer_type=type;
-		buffer=data.data;
-		buffer_length=data.size;
-	}
-};
-
-
-template<typename T>
-inline void bind(binder& binder, const T& v)
-{
-	binder.bind(const_cast<T&>(v));
-}
-
-template<typename T>
-inline void bind(binder& binder, T&& v)
-{
-	binder.bind(v);
-}
-
-inline void bind(binder& binder, const char* str, size_t length=0)
-{
-	if(length==0) length=strlen(str);
-	binder.bind(const_cast<char*>(str), static_cast<unsigned long>(length), MYSQL_TYPE_VAR_STRING);
-}
-
-class base_statement;
-class basic_database;
-
-class error : public std::exception
-{
-public:
-	error() : m_error(0) { }
-	error(unsigned int err, const char* errmsg) : m_error(err), m_errmsg(errmsg) { }
-	explicit error(const base_statement& stmt);
-	explicit error(const basic_database& db);
-	error(const error& src) = default;
-	virtual ~error() throw() { }
-	int code() const throw() { return m_error; }
-	operator bool() const { return m_error != 0;  }
-	virtual const char* what() const NOEXCEPT override { return m_errmsg.data(); }
-private:
-	unsigned int m_error;
-	std::string m_errmsg;
-};
-
-class blobbuf : public qtl::blobbuf
-{
-public:
-	blobbuf() : m_stmt(nullptr), m_field(0) 
-	{
-	}
-	blobbuf(const blobbuf&) = default;
-	blobbuf& operator=(const blobbuf&) = default;
-	virtual ~blobbuf() { overflow();  }
-
-	void open(MYSQL_STMT* stmt, int field, const binder& b, std::ios_base::openmode mode)
-	{
-		if (m_stmt && m_field)
+		struct init
 		{
-			overflow();
-		}
-
-		assert(stmt != nullptr);
-		m_stmt = stmt;
-		m_field = field;
-		m_binder = b;
-		if (b.length) m_size = *b.length;
-		init_buffer(mode);
-	}
-
-	void swap(blobbuf& other)
-	{
-		std::swap(m_stmt, other.m_stmt);
-		std::swap(m_binder, other.m_binder);
-		std::swap(m_field, other.m_field);
-		qtl::blobbuf::swap(other);
-	}
-
-private:
-	MYSQL_STMT* m_stmt;
-	binder m_binder;
-	int m_field;
-
-protected:
-	virtual bool read_blob(char* buffer, off_type& count, pos_type position) override
-	{
-		m_binder.buffer = buffer;
-		m_binder.buffer_length = count;
-		int ret = mysql_stmt_fetch_column(m_stmt, &m_binder, m_field, position);
-		switch (ret)
-		{
-		case 0:
-			count = std::min(m_binder.buffer_length, *m_binder.length);
-			return true;
-		case CR_NO_DATA:
-			return false;
-		default:
-			throw error(mysql_stmt_errno(m_stmt), mysql_stmt_error(m_stmt));
-		}
-	}
-
-	virtual void write_blob(const char* buffer, size_t count) override
-	{
-		int ret = mysql_stmt_send_long_data(m_stmt, m_field, buffer, count);
-		if (ret != 0)
-			throw error(mysql_stmt_errno(m_stmt), mysql_stmt_error(m_stmt));
-	}
-};
-
-struct time : public MYSQL_TIME
-{
-	time()
-	{
-		memset(this, 0, sizeof(MYSQL_TIME));
-		time_type = MYSQL_TIMESTAMP_NONE;
-	}
-	time(const struct tm& tm)
-	{
-		memset(this, 0, sizeof(MYSQL_TIME));
-		year = tm.tm_year + 1900;
-		month = tm.tm_mon + 1;
-		day = tm.tm_mday;
-		hour = tm.tm_hour;
-		minute = tm.tm_min;
-		second = tm.tm_sec;
-		time_type = MYSQL_TIMESTAMP_DATETIME;
-	}
-	time(time_t value)
-	{
-		struct tm tm;
-#if defined(_MSC_VER)
-		localtime_s(&tm, &value);
-#elif defined(_POSIX_VERSION)
-		localtime_r(&value, &tm);
-#else
-		tm = *localtime(&value);
-#endif
-		new(this)time(tm);
-	}
-	time(const time& src)
-	{
-		memcpy(this, &src, sizeof(MYSQL_TIME));
-	}
-	time& operator=(const time& src)
-	{
-		if (this != &src)
-			memcpy(this, &src, sizeof(MYSQL_TIME));
-		return *this;
-	}
-
-	static time now()
-	{
-		time_t value;
-		::time(&value);
-		return time(value);
-	}
-
-	time_t as_tm(struct tm& tm) const
-	{
-		tm.tm_year = year - 1900;
-		tm.tm_mon = month - 1;
-		tm.tm_mday = day;
-		tm.tm_hour = hour;
-		tm.tm_min = minute;
-		tm.tm_sec = second;
-		return mktime(&tm);
-	}
-	time_t get_time() const
-	{
-		struct tm tm;
-		return as_tm(tm);
-	}
-};
-
-class base_statement
-{
-protected:
-	base_statement() : m_stmt(nullptr), m_result(nullptr) {}
-	base_statement(const base_statement&) = delete;
-	explicit base_statement(basic_database& db);
-	base_statement(base_statement&& src)
-		: m_stmt(src.m_stmt), m_result(src.m_result),
-		m_binders(std::move(src.m_binders)), m_binderAddins(std::move(src.m_binderAddins))
-	{
-		src.m_stmt=nullptr;
-		src.m_result=nullptr;
-	}
-	base_statement& operator=(const base_statement&) = delete;
-	base_statement& operator=(base_statement&& src)
-	{
-		if(this!=&src)
-		{
-			m_stmt=src.m_stmt;
-			m_result=src.m_result;
-			src.m_stmt=nullptr;
-			src.m_result=nullptr;
-			m_binders=std::move(src.m_binders);
-			m_binderAddins=std::move(src.m_binderAddins);
-		}
-		return *this;
-	}
-
-public:
-	operator MYSQL_STMT*() { return m_stmt; }
-
-	unsigned int get_parameter_count() const { return mysql_stmt_param_count(m_stmt); }
-	unsigned int get_column_count() const { return mysql_stmt_field_count(m_stmt); }
-
-	unsigned long length(unsigned int index) const
-	{
-		return m_binderAddins[index].m_length;
-	}
-
-	bool is_null(unsigned int index) const
-	{
-		return m_binderAddins[index].m_isNull!=0;
-	}
-
-	size_t find_field(const char* name) const
-	{
-		if(m_result)
-		{
-			for(size_t i=0; i!=m_result->field_count; i++)
+			init(int argc = -1, char **argv = nullptr, char **groups = nullptr)
 			{
-				if(strncmp(m_result->fields[i].name, name, m_result->fields[i].name_length)==0)
-					return i;
+				// my_init();
+				mysql_library_init(argc, argv, groups);
 			}
-		}
-		return -1;
-	}
-
-	my_ulonglong affetced_rows()
-	{
-		return mysql_stmt_affected_rows(m_stmt);
-	}
-	my_ulonglong insert_id()
-	{
-		return mysql_stmt_insert_id(m_stmt);
-	}
-
-	binder* get_binder(unsigned long index)
-	{
-		return &m_binders[index];
-	}
-
-	unsigned int error() const
-	{
-		return mysql_stmt_errno(m_stmt);
-	}
-	const char* errmsg() const
-	{
-		return mysql_stmt_error(m_stmt);
-	}
-
-	MYSQL_RES* result() { return m_result; }
-
-	void bind_param(size_t index, const char* param, size_t length)
-	{
-		bind(m_binders[index], param, length);
-	}
-
-	void bind_param(size_t index, const std::nullptr_t&)
-	{
-		m_binders[index].bind();
-	}
-
-	void bind_param(size_t index, std::istream& param)
-	{
-		m_binders[index].bind(nullptr, 0, MYSQL_TYPE_LONG_BLOB);
-		m_binderAddins[index].m_after_fetch = [this, index, &param](const binder&) {
-			std::array<char, blob_buffer_size> buffer;
-			unsigned long readed = 0;
-			while (!param.eof() && !param.fail())
+			~init()
 			{
-				param.read(buffer.data(), buffer.size());
-				readed = (unsigned long)param.gcount();
-				if (readed > 0)
+				mysql_library_end();
+			}
+		};
+
+		struct thread_init
+		{
+			thread_init()
+			{
+				mysql_thread_init();
+			}
+			~thread_init()
+			{
+				mysql_thread_end();
+			}
+		};
+
+		class binder : public MYSQL_BIND
+		{
+			friend class statement;
+
+		public:
+			binder()
+			{
+				init();
+			}
+			void init()
+			{
+				memset(this, 0, sizeof(MYSQL_BIND));
+			}
+			void bind()
+			{
+				init();
+				buffer_type = MYSQL_TYPE_NULL;
+			}
+			void bind(null)
+			{
+				bind();
+			}
+			void bind(std::nullptr_t)
+			{
+				bind();
+			}
+			void bind(bool &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_BIT;
+				buffer = &v;
+				buffer_length = 1;
+			}
+			void bind(int8_t &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_TINY;
+				buffer = &v;
+			}
+			void bind(uint8_t &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_TINY;
+				buffer = &v;
+				is_unsigned = true;
+			}
+			void bind(int16_t &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_SHORT;
+				buffer = &v;
+			}
+			void bind(uint16_t &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_SHORT;
+				buffer = &v;
+				is_unsigned = true;
+			}
+			void bind(int32_t &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_LONG;
+				buffer = &v;
+			}
+			void bind(uint32_t &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_LONG;
+				buffer = &v;
+				is_unsigned = true;
+			}
+			void bind(int64_t &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_LONGLONG;
+				buffer = &v;
+			}
+			void bind(uint64_t &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_LONGLONG;
+				buffer = &v;
+				is_unsigned = true;
+			}
+			void bind(double &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_DOUBLE;
+				buffer = &v;
+			}
+			void bind(float &v)
+			{
+				init();
+				buffer_type = MYSQL_TYPE_FLOAT;
+				buffer = &v;
+			}
+			void bind(MYSQL_TIME &v, enum_field_types type = MYSQL_TYPE_TIMESTAMP)
+			{
+				init();
+				buffer_type = type;
+				buffer = &v;
+			}
+			void bind(void *data, unsigned long length, enum_field_types type = MYSQL_TYPE_BLOB)
+			{
+				init();
+				buffer_type = type;
+				buffer = data;
+				buffer_length = length;
+			}
+			void bind(const const_blob_data &data, enum_field_types type = MYSQL_TYPE_BLOB)
+			{
+				init();
+				buffer_type = type;
+				buffer = const_cast<void *>(data.data);
+				buffer_length = data.size;
+			}
+			void bind(blob_data &data, enum_field_types type = MYSQL_TYPE_BLOB)
+			{
+				init();
+				buffer_type = type;
+				buffer = data.data;
+				buffer_length = data.size;
+			}
+		};
+
+		template <typename T>
+		inline void bind(binder &binder, const T &v)
+		{
+			binder.bind(const_cast<T &>(v));
+		}
+
+		template <typename T>
+		inline void bind(binder &binder, T &&v)
+		{
+			binder.bind(v);
+		}
+
+		inline void bind(binder &binder, const char *str, size_t length = 0)
+		{
+			if (length == 0)
+				length = strlen(str);
+			binder.bind(const_cast<char *>(str), static_cast<unsigned long>(length), MYSQL_TYPE_VAR_STRING);
+		}
+
+		class base_statement;
+		class basic_database;
+
+		class error : public std::exception
+		{
+		public:
+			error() : m_error(0) {}
+			error(unsigned int err, const char *errmsg) : m_error(err), m_errmsg(errmsg) {}
+			explicit error(const base_statement &stmt);
+			explicit error(const basic_database &db);
+			error(const error &src) = default;
+			virtual ~error() throw() {}
+			int code() const throw() { return m_error; }
+			operator bool() const { return m_error != 0; }
+			virtual const char *what() const NOEXCEPT override { return m_errmsg.data(); }
+
+		private:
+			unsigned int m_error;
+			std::string m_errmsg;
+		};
+
+		class blobbuf : public qtl::blobbuf
+		{
+		public:
+			blobbuf() : m_stmt(nullptr), m_field(0)
+			{
+			}
+			blobbuf(const blobbuf &) = default;
+			blobbuf &operator=(const blobbuf &) = default;
+			virtual ~blobbuf() { overflow(); }
+
+			void open(MYSQL_STMT *stmt, int field, const binder &b, std::ios_base::openmode mode)
+			{
+				if (m_stmt && m_field)
 				{
-					if (mysql_stmt_send_long_data(m_stmt, index, buffer.data(), readed) != 0)
-						throw_exception();
+					overflow();
+				}
+
+				assert(stmt != nullptr);
+				m_stmt = stmt;
+				m_field = field;
+				m_binder = b;
+				if (b.length)
+					m_size = *b.length;
+				init_buffer(mode);
+			}
+
+			void swap(blobbuf &other)
+			{
+				std::swap(m_stmt, other.m_stmt);
+				std::swap(m_binder, other.m_binder);
+				std::swap(m_field, other.m_field);
+				qtl::blobbuf::swap(other);
+			}
+
+		private:
+			MYSQL_STMT *m_stmt;
+			binder m_binder;
+			int m_field;
+
+		protected:
+			virtual bool read_blob(char *buffer, off_type &count, pos_type position) override
+			{
+				m_binder.buffer = buffer;
+				m_binder.buffer_length = count;
+				int ret = mysql_stmt_fetch_column(m_stmt, &m_binder, m_field, position);
+				switch (ret)
+				{
+				case 0:
+					count = std::min(m_binder.buffer_length, *m_binder.length);
+					return true;
+				case CR_NO_DATA:
+					return false;
+				default:
+					throw error(mysql_stmt_errno(m_stmt), mysql_stmt_error(m_stmt));
 				}
 			}
-		};
-	}
 
-	void bind_param(size_t index, const blob_writer& param)
-	{
-		m_binders[index].bind(nullptr, 0, MYSQL_TYPE_LONG_BLOB);
-		m_binderAddins[index].m_after_fetch = [this, index, &param](const binder& b) {
-			blobbuf buf;
-			buf.open(m_stmt, index, b, std::ios::out);
-			std::ostream s(&buf);
-			param(s);
-		};
-	}
-
-	template<class Param>
-	void bind_param(size_t index, const Param& param)
-	{
-		bind(m_binders[index], param);
-	}
-
-	template<class Type>
-	void bind_field(size_t index, Type&& value)
-	{
-		if (m_result)
-		{
-			bind(m_binders[index], std::forward<Type>(value));
-			m_binderAddins[index].m_after_fetch = 
-				if_null<typename std::remove_reference<Type>::type>(value);
-		}
-	}
-
-	void bind_field(size_t index, char* value, size_t length)
-	{
-		m_binders[index].bind(value, length - 1, MYSQL_TYPE_VAR_STRING);
-		m_binderAddins[index].m_after_fetch = [](const binder& bind) {
-			if (*bind.is_null)
-				memset(bind.buffer, 0, bind.buffer_length + 1);
-			else
+			virtual void write_blob(const char *buffer, size_t count) override
 			{
-				char* text = reinterpret_cast<char*>(bind.buffer);
-				text[*bind.length] = '\0';
+				int ret = mysql_stmt_send_long_data(m_stmt, m_field, buffer, count);
+				if (ret != 0)
+					throw error(mysql_stmt_errno(m_stmt), mysql_stmt_error(m_stmt));
 			}
 		};
-	}
 
-	template<size_t N>
-	void bind_field(size_t index, std::array<char, N>&& value)
-	{
-		bind_field(index, value.data(), value.size());
-	}
-
-	template<typename T>
-	void bind_field(size_t index, bind_string_helper<T>&& value)
-	{
-		if (m_result)
+		struct time : public MYSQL_TIME
 		{
-			MYSQL_FIELD* field = mysql_fetch_field_direct(m_result, (unsigned int)index);
-			if (field == nullptr) 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)
+			time()
+			{
+				memset(this, 0, sizeof(MYSQL_TIME));
+				time_type = MYSQL_TIMESTAMP_NONE;
+			}
+			time(const struct tm &tm)
+			{
+				memset(this, 0, sizeof(MYSQL_TIME));
+				year = tm.tm_year + 1900;
+				month = tm.tm_mon + 1;
+				day = tm.tm_mday;
+				hour = tm.tm_hour;
+				minute = tm.tm_min;
+				second = tm.tm_sec;
+				time_type = MYSQL_TIMESTAMP_DATETIME;
+			}
+			time(time_t value)
+			{
+				struct tm tm;
+#if defined(_MSC_VER)
+				localtime_s(&tm, &value);
+#elif defined(_POSIX_VERSION)
+				localtime_r(&value, &tm);
+#else
+				tm = *localtime(&value);
+#endif
+				new (this) time(tm);
+			}
+			time(const time &src)
+			{
+				memcpy(this, &src, sizeof(MYSQL_TIME));
+			}
+			time &operator=(const time &src)
+			{
+				if (this != &src)
+					memcpy(this, &src, sizeof(MYSQL_TIME));
+				return *this;
+			}
+
+			static time now()
+			{
+				time_t value;
+				::time(&value);
+				return time(value);
+			}
+
+			time_t as_tm(struct tm &tm) const
+			{
+				tm.tm_year = year - 1900;
+				tm.tm_mon = month - 1;
+				tm.tm_mday = day;
+				tm.tm_hour = hour;
+				tm.tm_min = minute;
+				tm.tm_sec = second;
+				return mktime(&tm);
+			}
+			time_t get_time() const
+			{
+				struct tm tm;
+				return as_tm(tm);
+			}
+		};
+
+		class base_statement
+		{
+		protected:
+			base_statement() : m_stmt(nullptr), m_result(nullptr) {}
+			base_statement(const base_statement &) = delete;
+			explicit base_statement(basic_database &db);
+			base_statement(base_statement &&src)
+				: m_stmt(src.m_stmt), m_result(src.m_result),
+				  m_binders(std::move(src.m_binders)), m_binderAddins(std::move(src.m_binderAddins))
+			{
+				src.m_stmt = nullptr;
+				src.m_result = nullptr;
+			}
+			base_statement &operator=(const base_statement &) = delete;
+			base_statement &operator=(base_statement &&src)
+			{
+				if (this != &src)
 				{
-					value.alloc(b.buffer_length);
-					if (b.buffer != value.data())
+					m_stmt = src.m_stmt;
+					m_result = src.m_result;
+					src.m_stmt = nullptr;
+					src.m_result = nullptr;
+					m_binders = std::move(src.m_binders);
+					m_binderAddins = std::move(src.m_binderAddins);
+				}
+				return *this;
+			}
+
+		public:
+			operator MYSQL_STMT *() { return m_stmt; }
+
+			unsigned int get_parameter_count() const { return mysql_stmt_param_count(m_stmt); }
+			unsigned int get_column_count() const { return mysql_stmt_field_count(m_stmt); }
+
+			unsigned long length(unsigned int index) const
+			{
+				return m_binderAddins[index].m_length;
+			}
+
+			bool is_null(unsigned int index) const
+			{
+				return m_binderAddins[index].m_isNull != 0;
+			}
+
+			size_t find_field(const char *name) const
+			{
+				if (m_result)
+				{
+					for (size_t i = 0; i != m_result->field_count; i++)
 					{
-						b.buffer = const_cast<char*>(value.data());
-						mysql_stmt_bind_result(m_stmt, &m_binders.front());
+						if (strncmp(m_result->fields[i].name, name, m_result->fields[i].name_length) == 0)
+							return i;
 					}
 				}
-			};
-			m_binderAddins[index].m_after_fetch = [value](const binder& b) mutable {
-				if (*b.is_null) value.clear();
-				else value.truncate(*b.length);
-			};
-			m_binders[index].bind((void*)data, field->length, field->type);
-		}
-	}
+				return -1;
+			}
 
-	void bind_field(size_t index, std::ostream&& value)
-	{
-		if (m_result)
-		{
-			MYSQL_FIELD* field = mysql_fetch_field_direct(m_result, (unsigned int)index);
-			assert(IS_LONGDATA(field->type));
-			m_binders[index].bind(nullptr, 0, field->type);
-			m_binderAddins[index].m_after_fetch = [this, index, &value](const binder& b) {
-				unsigned long readed = 0;
-				std::array<char, blob_buffer_size> buffer;
-				binder& bb = const_cast<binder&>(b);
-				if (*b.is_null) return;
-				bb.buffer = const_cast<char*>(buffer.data());
-				bb.buffer_length = buffer.size();
-				while (readed <= *b.length)
+			my_ulonglong affetced_rows()
+			{
+				return mysql_stmt_affected_rows(m_stmt);
+			}
+			my_ulonglong insert_id()
+			{
+				return mysql_stmt_insert_id(m_stmt);
+			}
+
+			binder *get_binder(unsigned long index)
+			{
+				return &m_binders[index];
+			}
+
+			unsigned int error() const
+			{
+				return mysql_stmt_errno(m_stmt);
+			}
+			const char *errmsg() const
+			{
+				return mysql_stmt_error(m_stmt);
+			}
+
+			MYSQL_RES *result() { return m_result; }
+
+			void bind_param(size_t index, const char *param, size_t length)
+			{
+				bind(m_binders[index], param, length);
+			}
+
+			void bind_param(size_t index, const std::nullptr_t &)
+			{
+				m_binders[index].bind();
+			}
+
+			void bind_param(size_t index, std::istream &param)
+			{
+				m_binders[index].bind(nullptr, 0, MYSQL_TYPE_LONG_BLOB);
+				m_binderAddins[index].m_after_fetch = [this, index, &param](const binder &)
 				{
-					int ret = mysql_stmt_fetch_column(m_stmt, &bb, index, readed);
-					if (ret != 0)
-						throw_exception();
-					value.write(buffer.data(), std::min(b.buffer_length, *b.length - b.offset));
-					readed += bb.buffer_length;
+					std::array<char, blob_buffer_size> buffer;
+					unsigned long readed = 0;
+					while (!param.eof() && !param.fail())
+					{
+						param.read(buffer.data(), buffer.size());
+						readed = (unsigned long)param.gcount();
+						if (readed > 0)
+						{
+							if (mysql_stmt_send_long_data(m_stmt, index, buffer.data(), readed) != 0)
+								throw_exception();
+						}
+					}
+				};
+			}
+
+			void bind_param(size_t index, const blob_writer &param)
+			{
+				m_binders[index].bind(nullptr, 0, MYSQL_TYPE_LONG_BLOB);
+				m_binderAddins[index].m_after_fetch = [this, index, &param](const binder &b)
+				{
+					blobbuf buf;
+					buf.open(m_stmt, index, b, std::ios::out);
+					std::ostream s(&buf);
+					param(s);
+				};
+			}
+
+			template <class Param>
+			void bind_param(size_t index, const Param &param)
+			{
+				bind(m_binders[index], param);
+			}
+
+			template <class Type>
+			void bind_field(size_t index, Type &&value)
+			{
+				if (m_result)
+				{
+					bind(m_binders[index], std::forward<Type>(value));
+					m_binderAddins[index].m_after_fetch =
+						if_null<typename std::remove_reference<Type>::type>(value);
 				}
-			};
-		}
-	}
+			}
 
-	void bind_field(size_t index, blobbuf&& value)
-	{
-		if (m_result)
-		{
-			MYSQL_FIELD* field = mysql_fetch_field_direct(m_result, (unsigned int)index);
-			assert(IS_LONGDATA(field->type));
-			m_binders[index].bind(nullptr, 0, field->type);
-			m_binderAddins[index].m_after_fetch = [this, index, &value](const binder& b) {
-				if (*b.is_null) return;
-				value.open(m_stmt, index, b, std::ios::in);
-			};
-		}
-	}
+			void bind_field(size_t index, char *value, size_t length)
+			{
+				m_binders[index].bind(value, length - 1, MYSQL_TYPE_VAR_STRING);
+				m_binderAddins[index].m_after_fetch = [](const binder &bind)
+				{
+					if (*bind.is_null)
+						memset(bind.buffer, 0, bind.buffer_length + 1);
+					else
+					{
+						char *text = reinterpret_cast<char *>(bind.buffer);
+						text[*bind.length] = '\0';
+					}
+				};
+			}
 
-	template<typename Type>
-	void bind_field(size_t index, indicator<Type>&& value)
-	{
-		if (m_result)
-		{
-			qtl::bind_field(*this, index, value.data);
-			binder_addin& addin = m_binderAddins[index];
-			auto fetch_fun = addin.m_after_fetch;
-			addin.m_after_fetch = [&addin, fetch_fun, &value](const binder& b) {
-				value.is_null = *b.is_null != 0;
-				value.length = *b.length;
-				value.is_truncated = addin.is_truncated;
-				if (fetch_fun) fetch_fun(b);
-			};
-		}
-	}
+			template <size_t N>
+			void bind_field(size_t index, std::array<char, N> &&value)
+			{
+				bind_field(index, value.data(), value.size());
+			}
+
+			template <typename T>
+			void bind_field(size_t index, bind_string_helper<T> &&value)
+			{
+				if (m_result)
+				{
+					MYSQL_FIELD *field = mysql_fetch_field_direct(m_result, (unsigned int)index);
+					if (field == nullptr)
+						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);
+					};
+					m_binders[index].bind((void *)data, field->length, field->type);
+				}
+			}
+
+			void bind_field(size_t index, std::ostream &&value)
+			{
+				if (m_result)
+				{
+					MYSQL_FIELD *field = mysql_fetch_field_direct(m_result, (unsigned int)index);
+					assert(IS_LONGDATA(field->type));
+					m_binders[index].bind(nullptr, 0, field->type);
+					m_binderAddins[index].m_after_fetch = [this, index, &value](const binder &b)
+					{
+						unsigned long readed = 0;
+						std::array<char, blob_buffer_size> buffer;
+						binder &bb = const_cast<binder &>(b);
+						if (*b.is_null)
+							return;
+						bb.buffer = const_cast<char *>(buffer.data());
+						bb.buffer_length = buffer.size();
+						while (readed <= *b.length)
+						{
+							int ret = mysql_stmt_fetch_column(m_stmt, &bb, index, readed);
+							if (ret != 0)
+								throw_exception();
+							value.write(buffer.data(), std::min(b.buffer_length, *b.length - b.offset));
+							readed += bb.buffer_length;
+						}
+					};
+				}
+			}
+
+			void bind_field(size_t index, blobbuf &&value)
+			{
+				if (m_result)
+				{
+					MYSQL_FIELD *field = mysql_fetch_field_direct(m_result, (unsigned int)index);
+					assert(IS_LONGDATA(field->type));
+					m_binders[index].bind(nullptr, 0, field->type);
+					m_binderAddins[index].m_after_fetch = [this, index, &value](const binder &b)
+					{
+						if (*b.is_null)
+							return;
+						value.open(m_stmt, index, b, std::ios::in);
+					};
+				}
+			}
+
+			template <typename Type>
+			void bind_field(size_t index, indicator<Type> &&value)
+			{
+				if (m_result)
+				{
+					qtl::bind_field(*this, index, value.data);
+					binder_addin &addin = m_binderAddins[index];
+					auto fetch_fun = addin.m_after_fetch;
+					addin.m_after_fetch = [&addin, fetch_fun, &value](const binder &b)
+					{
+						value.is_null = *b.is_null != 0;
+						value.length = *b.length;
+						value.is_truncated = addin.is_truncated;
+						if (fetch_fun)
+							fetch_fun(b);
+					};
+				}
+			}
 
 #ifdef _QTL_ENABLE_CPP17
 
-	template<typename T>
-	inline void bind_field(size_t index, std::optional<T>&& value)
-	{
-		if (m_result)
-		{
-			qtl::bind_field(*this, index, *value);
-			binder_addin& addin = m_binderAddins[index];
-			auto fetch_fun = addin.m_after_fetch;
-			addin.m_after_fetch = [&addin, fetch_fun, &value](const binder& b) {
-				if (fetch_fun) fetch_fun(b);
-				if (*b.is_null) value.reset();
-			};
-		}
-	}
-
-	inline void bind_field(size_t index, std::any&& value)
-	{
-		if (m_result)
-		{
-			MYSQL_FIELD* field = mysql_fetch_field_direct(m_result, (unsigned int)index);
-			if (field == nullptr) throw_exception();
-			switch (field->type)
+			template <typename T>
+			inline void bind_field(size_t index, std::optional<T> &&value)
 			{
-			case MYSQL_TYPE_NULL:
-				value.reset();
-				break;
-			case MYSQL_TYPE_BIT:
-				value.emplace<bool>();
-				bind_field(index, std::any_cast<bool&>(value));
-				break;
-			case MYSQL_TYPE_TINY:
-				value.emplace<int8_t>();
-				bind_field(index, std::any_cast<int8_t&>(value));
-				break;
-			case MYSQL_TYPE_SHORT:
-				value.emplace<int16_t>();
-				bind_field(index, std::any_cast<int16_t&>(value));
-				break;
-			case MYSQL_TYPE_LONG:
-				value.emplace<int32_t>();
-				bind_field(index, std::any_cast<int32_t&>(value));
-				break;
-			case MYSQL_TYPE_LONGLONG:
-				value.emplace<int64_t>();
-				bind_field(index, std::any_cast<int64_t&>(value));
-				break;
-			case MYSQL_TYPE_FLOAT:
-				value.emplace<float>();
-				bind_field(index, std::any_cast<float&>(value));
-				break;
-			case MYSQL_TYPE_DOUBLE:
-				value.emplace<double>();
-				bind_field(index, std::any_cast<double&>(value));
-				break;
-			case MYSQL_TYPE_DATE:
-			case MYSQL_TYPE_TIME:
-			case MYSQL_TYPE_DATETIME:
-			case MYSQL_TYPE_TIMESTAMP:
-			case MYSQL_TYPE_TIMESTAMP2:
-			case MYSQL_TYPE_DATETIME2:
-			case MYSQL_TYPE_TIME2:
-				value.emplace<qtl::mysql::time>();
-				bind_field(index, std::any_cast<qtl::mysql::time&>(value));
-				break;
-			case MYSQL_TYPE_VARCHAR:
-			case MYSQL_TYPE_VAR_STRING:
-			case MYSQL_TYPE_STRING:
-			case MYSQL_TYPE_ENUM:
-#if LIBMYSQL_VERSION_ID >= 50700
-			case MYSQL_TYPE_JSON:
-#endif 
-			case MYSQL_TYPE_DECIMAL:
-			case MYSQL_TYPE_NEWDECIMAL:
-			case MYSQL_TYPE_GEOMETRY:
-				value.emplace<std::string>();
-				bind_field(index, qtl::bind_string(std::any_cast<std::string&>(value)));
-				break;
-			case MYSQL_TYPE_TINY_BLOB:
-			case MYSQL_TYPE_MEDIUM_BLOB:
-			case MYSQL_TYPE_BLOB:
-			case MYSQL_TYPE_LONG_BLOB:
-				value.emplace<blobbuf>();
-				bind_field(index, std::forward<blobbuf>(std::any_cast<blobbuf&>(value)));
-				break;
-			default:
-				throw mysql::error(CR_UNSUPPORTED_PARAM_TYPE, "Unsupported field type");
+				if (m_result)
+				{
+					qtl::bind_field(*this, index, *value);
+					binder_addin &addin = m_binderAddins[index];
+					auto fetch_fun = addin.m_after_fetch;
+					addin.m_after_fetch = [&addin, fetch_fun, &value](const binder &b)
+					{
+						if (fetch_fun)
+							fetch_fun(b);
+						if (*b.is_null)
+							value.reset();
+					};
+				}
 			}
-			binder_addin& addin = m_binderAddins[index];
-			auto fetch_fun = addin.m_after_fetch;
-			addin.m_after_fetch = [&addin, fetch_fun, &value](const binder& b) {
-				if (fetch_fun) fetch_fun(b);
-				if (*b.is_null) value.reset();
-			};
-		}
-	}
+
+			inline void bind_field(size_t index, std::any &&value)
+			{
+				if (m_result)
+				{
+					MYSQL_FIELD *field = mysql_fetch_field_direct(m_result, (unsigned int)index);
+					if (field == nullptr)
+						throw_exception();
+					switch (field->type)
+					{
+					case MYSQL_TYPE_NULL:
+						value.reset();
+						break;
+					case MYSQL_TYPE_BIT:
+						value.emplace<bool>();
+						bind_field(index, std::any_cast<bool &>(value));
+						break;
+					case MYSQL_TYPE_TINY:
+						value.emplace<int8_t>();
+						bind_field(index, std::any_cast<int8_t &>(value));
+						break;
+					case MYSQL_TYPE_SHORT:
+						value.emplace<int16_t>();
+						bind_field(index, std::any_cast<int16_t &>(value));
+						break;
+					case MYSQL_TYPE_LONG:
+						value.emplace<int32_t>();
+						bind_field(index, std::any_cast<int32_t &>(value));
+						break;
+					case MYSQL_TYPE_LONGLONG:
+						value.emplace<int64_t>();
+						bind_field(index, std::any_cast<int64_t &>(value));
+						break;
+					case MYSQL_TYPE_FLOAT:
+						value.emplace<float>();
+						bind_field(index, std::any_cast<float &>(value));
+						break;
+					case MYSQL_TYPE_DOUBLE:
+						value.emplace<double>();
+						bind_field(index, std::any_cast<double &>(value));
+						break;
+					case MYSQL_TYPE_DATE:
+					case MYSQL_TYPE_TIME:
+					case MYSQL_TYPE_DATETIME:
+					case MYSQL_TYPE_TIMESTAMP:
+					case MYSQL_TYPE_TIMESTAMP2:
+					case MYSQL_TYPE_DATETIME2:
+					case MYSQL_TYPE_TIME2:
+						value.emplace<qtl::mysql::time>();
+						bind_field(index, std::any_cast<qtl::mysql::time &>(value));
+						break;
+					case MYSQL_TYPE_VARCHAR:
+					case MYSQL_TYPE_VAR_STRING:
+					case MYSQL_TYPE_STRING:
+					case MYSQL_TYPE_ENUM:
+#if LIBMYSQL_VERSION_ID >= 50700
+					case MYSQL_TYPE_JSON:
+#endif
+					case MYSQL_TYPE_DECIMAL:
+					case MYSQL_TYPE_NEWDECIMAL:
+					case MYSQL_TYPE_GEOMETRY:
+						value.emplace<std::string>();
+						bind_field(index, qtl::bind_string(std::any_cast<std::string &>(value)));
+						break;
+					case MYSQL_TYPE_TINY_BLOB:
+					case MYSQL_TYPE_MEDIUM_BLOB:
+					case MYSQL_TYPE_BLOB:
+					case MYSQL_TYPE_LONG_BLOB:
+						value.emplace<blobbuf>();
+						bind_field(index, std::forward<blobbuf>(std::any_cast<blobbuf &>(value)));
+						break;
+					default:
+						throw mysql::error(CR_UNSUPPORTED_PARAM_TYPE, "Unsupported field type");
+					}
+					binder_addin &addin = m_binderAddins[index];
+					auto fetch_fun = addin.m_after_fetch;
+					addin.m_after_fetch = [&addin, fetch_fun, &value](const binder &b)
+					{
+						if (fetch_fun)
+							fetch_fun(b);
+						if (*b.is_null)
+							value.reset();
+					};
+				}
+			}
 
 #endif // C++17
 
-	void close()
-	{
-		if (m_result)
-		{
-			mysql_free_result(m_result);
-			m_result = nullptr;
-		}
-		if (m_stmt)
-		{
-			mysql_stmt_close(m_stmt);
-			m_stmt = nullptr;
-		}
-	}
-
-protected:
-	MYSQL_STMT* m_stmt;
-	MYSQL_RES* m_result;
-	std::vector<binder> m_binders;
-
-	struct binder_addin
-	{
-		unsigned long m_length;
-		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;
-
-	void resize_binders(size_t n)
-	{
-		m_binders.resize(n);
-		m_binderAddins.resize(n);
-	}
-	void set_binders()
-	{
-		for(size_t i=0; i!=m_binders.size(); i++)
-		{
-			m_binderAddins[i].m_length=0;
-			m_binders[i].length=&m_binderAddins[i].m_length;
-			m_binderAddins[i].m_isNull=0;
-			m_binders[i].is_null=&m_binderAddins[i].m_isNull;
-			m_binderAddins[i].m_error=0;
-			m_binders[i].error=&m_binderAddins[i].m_error;
-		}
-	}
-
-	void throw_exception() const { throw mysql::error(*this); }
-
-	template<typename Value>
-	struct if_null
-	{
-		explicit if_null(Value& value, Value&& def=Value()) : m_value(value), m_def(std::move(def)) { }
-		void operator()(const binder& b)
-		{
-			if(*b.is_null) m_value=m_def;
-		}
-		Value& m_value;
-		Value m_def;
-	};
-
-};
-
-class statement : public base_statement
-{
-public:
-	statement() = default;
-	explicit statement(basic_database& db) : base_statement(db) { }
-	statement(statement&& src) : base_statement(std::move(src)) { }
-	statement& operator=(statement&& src) 
-	{
-		base_statement::operator =(std::move(src));
-		return *this;
-	}
-	~statement()
-	{
-		close();
-	}
-
-	void open(const char *query_text, unsigned long text_length=0)
-	{
-		mysql_stmt_reset(m_stmt);
-		if(text_length==0) text_length=(unsigned long)strlen(query_text);
-		if(mysql_stmt_prepare(m_stmt, query_text, text_length)!=0)
-			throw_exception();
-	}
-
-	void execute()
-	{
-		resize_binders(0);
-		if(mysql_stmt_execute(m_stmt)!=0)
-			throw_exception();
-	}
-
-	template<typename BindProc>
-	void execute_custom(BindProc&& bind_proc)
-	{
-		unsigned long count = mysql_stmt_param_count(m_stmt);
-		if (count > 0)
-		{
-			resize_binders(count);
-			bind_proc(*this);
-			if (mysql_stmt_bind_param(m_stmt, &m_binders.front()))
-				throw_exception();
-			for (size_t i = 0; i != count; i++)
+			void close()
 			{
-				if (m_binderAddins[i].m_after_fetch)
-					m_binderAddins[i].m_after_fetch(m_binders[i]);
+				if (m_result)
+				{
+					mysql_free_result(m_result);
+					m_result = nullptr;
+				}
+				if (m_stmt)
+				{
+					mysql_stmt_close(m_stmt);
+					m_stmt = nullptr;
+				}
 			}
-		}
-		if (mysql_stmt_execute(m_stmt) != 0)
-			throw_exception();
-	}
 
-	template<typename Types>
-	void execute(const Types& params)
-	{
-		execute_custom([&params](statement& stmt) {
-			qtl::bind_params(stmt, params);
-		});
-	}
+		protected:
+			MYSQL_STMT *m_stmt;
+			MYSQL_RES *m_result;
+			std::vector<binder> m_binders;
 
-	template<typename Types>
-	bool fetch(Types&& values)
-	{
-		if(m_result==nullptr)
-		{
-			unsigned long count=mysql_stmt_field_count(m_stmt);
-			if(count>0)
+			struct binder_addin
 			{
-				m_result=mysql_stmt_result_metadata(m_stmt);
-				if(m_result==nullptr) throw_exception();
-				resize_binders(count);
-				qtl::bind_record(*this, std::forward<Types>(values));
-				set_binders();
-				if(mysql_stmt_bind_result(m_stmt, m_binders.data())!=0)
+				unsigned long m_length;
+				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;
+
+			void resize_binders(size_t n)
+			{
+				m_binders.resize(n);
+				m_binderAddins.resize(n);
+			}
+			void set_binders()
+			{
+				for (size_t i = 0; i != m_binders.size(); i++)
+				{
+					m_binderAddins[i].m_length = 0;
+					m_binders[i].length = &m_binderAddins[i].m_length;
+					m_binderAddins[i].m_isNull = 0;
+					m_binders[i].is_null = &m_binderAddins[i].m_isNull;
+					m_binderAddins[i].m_error = 0;
+					m_binders[i].error = &m_binderAddins[i].m_error;
+				}
+			}
+
+			void throw_exception() const { throw mysql::error(*this); }
+
+			template <typename Value>
+			struct if_null
+			{
+				explicit if_null(Value &value, Value &&def = Value()) : m_value(value), m_def(std::move(def)) {}
+				void operator()(const binder &b)
+				{
+					if (*b.is_null)
+						m_value = m_def;
+				}
+				Value &m_value;
+				Value m_def;
+			};
+		};
+
+		class statement : public base_statement
+		{
+		public:
+			statement() = default;
+			explicit statement(basic_database &db) : base_statement(db) {}
+			statement(statement &&src) : base_statement(std::move(src)) {}
+			statement &operator=(statement &&src)
+			{
+				base_statement::operator=(std::move(src));
+				return *this;
+			}
+			~statement()
+			{
+				close();
+			}
+
+			void open(const char *query_text, unsigned long text_length = 0)
+			{
+				mysql_stmt_reset(m_stmt);
+				if (text_length == 0)
+					text_length = (unsigned long)strlen(query_text);
+				if (mysql_stmt_prepare(m_stmt, query_text, text_length) != 0)
 					throw_exception();
 			}
-		}
-		return fetch();
-	}
 
-	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)
-		{
-			for(size_t i=0; i!=m_binders.size(); i++)
+			void execute()
 			{
-				m_binderAddins[i].is_truncated = (err==MYSQL_DATA_TRUNCATED);
-				if(m_binderAddins[i].m_after_fetch)
-					m_binderAddins[i].m_after_fetch(m_binders[i]);
+				resize_binders(0);
+				if (mysql_stmt_execute(m_stmt) != 0)
+					throw_exception();
 			}
-			return true;
-		}
-		else if(err==1)
-			throw_exception();
-		return false;
-	}
 
-	bool next_result()
-	{
-		if(m_result)
+			template <typename BindProc>
+			void execute_custom(BindProc &&bind_proc)
+			{
+				unsigned long count = mysql_stmt_param_count(m_stmt);
+				if (count > 0)
+				{
+					resize_binders(count);
+					bind_proc(*this);
+					if (mysql_stmt_bind_param(m_stmt, &m_binders.front()))
+						throw_exception();
+					for (size_t i = 0; i != count; i++)
+					{
+						if (m_binderAddins[i].m_after_fetch)
+							m_binderAddins[i].m_after_fetch(m_binders[i]);
+					}
+				}
+				if (mysql_stmt_execute(m_stmt) != 0)
+					throw_exception();
+			}
+
+			template <typename Types>
+			void execute(const Types &params)
+			{
+				execute_custom([&params](statement &stmt)
+							   { qtl::bind_params(stmt, params); });
+			}
+
+			template <typename Types>
+			bool fetch(Types &&values)
+			{
+				if (m_result == nullptr)
+				{
+					unsigned long count = mysql_stmt_field_count(m_stmt);
+					if (count > 0)
+					{
+						m_result = mysql_stmt_result_metadata(m_stmt);
+						if (m_result == nullptr)
+							throw_exception();
+						resize_binders(count);
+						qtl::bind_record(*this, std::forward<Types>(values));
+						set_binders();
+						if (mysql_stmt_bind_result(m_stmt, m_binders.data()) != 0)
+							throw_exception();
+					}
+				}
+				return fetch();
+			}
+
+			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)
+				{
+					for (size_t i = 0; i != m_binders.size(); i++)
+					{
+						m_binderAddins[i].is_truncated = (err == MYSQL_DATA_TRUNCATED);
+						if (m_binderAddins[i].m_after_fetch)
+							m_binderAddins[i].m_after_fetch(m_binders[i]);
+					}
+					return true;
+				}
+				else if (err == 1)
+					throw_exception();
+				return false;
+			}
+
+			bool next_result()
+			{
+				if (m_result)
+				{
+					mysql_free_result(m_result);
+					m_result = nullptr;
+					mysql_stmt_free_result(m_stmt);
+				}
+				int ret = 0;
+				do
+				{
+					ret = mysql_stmt_next_result(m_stmt);
+					if (ret > 0)
+						throw_exception();
+				} while (ret == 0 && mysql_stmt_field_count(m_stmt) <= 0);
+				return ret == 0;
+			}
+
+			bool reset() { return mysql_stmt_reset(m_stmt) != 0; }
+		};
+
+		/*
+		struct LocalInfile
 		{
-			mysql_free_result(m_result);
-			m_result=nullptr;
-			mysql_stmt_free_result(m_stmt);
-		}
-		int ret=0;
-		do
+			int read(char *buf, unsigned int buf_len);
+			void close();
+			int error(char *error_msg, unsigned int error_msg_len);
+		};
+		*/
+		template <typename LocalInfile>
+		struct local_infile_factory
 		{
-			ret=mysql_stmt_next_result(m_stmt);
-			if(ret>0) throw_exception();
-		}while(ret==0 && mysql_stmt_field_count(m_stmt)<=0);
-		return ret==0;
-	}
+			static int local_infile_init(void **ptr, const char *filename, void *userdata)
+			{
+				LocalInfile *object = nullptr;
+				try
+				{
+					object = new LocalInfile(filename);
+				}
+				catch (...)
+				{
+					return -1;
+				}
+				return ptr ? 0 : -1;
+			}
 
-	bool reset() { return mysql_stmt_reset(m_stmt)!=0; }
-};
+			static int local_infile_read(void *ptr, char *buf, unsigned int buf_len)
+			{
+				LocalInfile *object = reinterpret_cast<LocalInfile>(ptr);
+				return object->read(buf, buf_len);
+			}
 
-/*
-struct LocalInfile
-{
-	int read(char *buf, unsigned int buf_len);
-	void close();
-	int error(char *error_msg, unsigned int error_msg_len);
-};
-*/
-template<typename LocalInfile>
-struct local_infile_factory
-{
-	static int local_infile_init(void **ptr, const char *filename, void *userdata)
-	{
-		LocalInfile* object = nullptr;
-		try
+			static void local_infile_end(void *ptr)
+			{
+				LocalInfile *object = reinterpret_cast<LocalInfile>(ptr);
+				object->close();
+				delete object;
+			}
+
+			static int local_infile_error(void *ptr, char *error_msg, unsigned int error_msg_len)
+			{
+				LocalInfile *object = reinterpret_cast<LocalInfile>(ptr);
+				return object->error(error_msg, error_msg_len);
+			}
+		};
+
+		class local_file
 		{
-			object = new LocalInfile(filename);
-		}
-		catch (...)
+		public:
+			local_file(const char *filename)
+			{
+				m_fp = fopen(filename, "rb");
+				if (m_fp == nullptr)
+					throw std::system_error(std::make_error_code(std::errc(errno)));
+			}
+			int read(char *buf, unsigned int buf_len)
+			{
+				return fread(buf, 1, buf_len, m_fp);
+			}
+			void close()
+			{
+				fclose(m_fp);
+			}
+			int error(char *error_msg, unsigned int error_msg_len)
+			{
+				int errcode = errno;
+				memset(error_msg, 0, error_msg_len);
+				strncpy(error_msg, strerror(errcode), error_msg_len - 1);
+				return errcode;
+			}
+
+		private:
+			FILE *m_fp;
+		};
+
+		class basic_database
 		{
-			return -1;
-		}
-		return ptr ? 0 : -1;
-	}
+		protected:
+			basic_database()
+			{
+				m_mysql = mysql_init(nullptr);
+			}
 
-	static int local_infile_read(void *ptr, char *buf, unsigned int buf_len)
-	{
-		LocalInfile* object = reinterpret_cast<LocalInfile>(ptr);
-		return object->read(buf, buf_len);
-	}
+		public:
+			typedef mysql::error exception_type;
 
-	static void local_infile_end(void *ptr)
-	{
-		LocalInfile* object = reinterpret_cast<LocalInfile>(ptr);
-		object->close();
-		delete object;
-	}
+			~basic_database()
+			{
+				if (m_mysql)
+					mysql_close(m_mysql);
+			}
+			basic_database(const basic_database &) = delete;
+			basic_database(basic_database &&src)
+			{
+				m_mysql = src.m_mysql;
+				src.m_mysql = nullptr;
+			}
+			basic_database &operator==(const basic_database &) = delete;
+			basic_database &operator==(basic_database &&src)
+			{
+				if (this != &src)
+				{
+					if (m_mysql)
+						mysql_close(m_mysql);
+					m_mysql = src.m_mysql;
+					src.m_mysql = nullptr;
+				}
+				return *this;
+			}
 
-	static int local_infile_error(void *ptr, char *error_msg, unsigned int error_msg_len)
-	{
-		LocalInfile* object = reinterpret_cast<LocalInfile>(ptr);
-		return object->error(error_msg, error_msg_len);
-	}
-};
+			MYSQL *handle() { return m_mysql; }
 
-class local_file
-{
-public:
-	local_file(const char* filename)
-	{
-		m_fp = fopen(filename, "rb");
-		if (m_fp == nullptr)
-			throw std::system_error(std::make_error_code(std::errc(errno)));
-	}
-	int read(char *buf, unsigned int buf_len)
-	{
-		return fread(buf, 1, buf_len, m_fp);
-	}
-	void close()
-	{
-		fclose(m_fp);
-	}
-	int error(char *error_msg, unsigned int error_msg_len)
-	{
-		int errcode = errno;
-		memset(error_msg, 0, error_msg_len);
-		strncpy(error_msg, strerror(errcode), error_msg_len - 1);
-		return errcode;
-	}
+			void options(enum mysql_option option, const void *arg)
+			{
+				if (mysql_options(m_mysql, option, arg) != 0)
+					throw_exception();
+			}
+			void charset_name(const char *charset)
+			{
+				if (mysql_set_character_set(m_mysql, charset) != 0)
+					throw_exception();
+			}
+			void protocol(mysql_protocol_type type)
+			{
+				return options(MYSQL_OPT_PROTOCOL, &type);
+			}
+			void reconnect(my_bool re)
+			{
+				return options(MYSQL_OPT_RECONNECT, &re);
+			}
 
-private:
-	FILE* m_fp;
-};
+			const char *current() const
+			{
+				return m_mysql->db;
+			}
 
-class basic_database
-{
-protected:
-	basic_database()
-	{
-		m_mysql = mysql_init(nullptr);
-	}
+			unsigned int error() const
+			{
+				return mysql_errno(m_mysql);
+			}
+			const char *errmsg() const
+			{
+				return mysql_error(m_mysql);
+			}
 
-public:
-	typedef mysql::error exception_type;
+			uint64_t affected_rows()
+			{
+				return mysql_affected_rows(m_mysql);
+			}
 
-	~basic_database()
-	{
-		if(m_mysql)
-			mysql_close(m_mysql);
-	}
-	basic_database(const basic_database&) = delete;
-	basic_database(basic_database&& src)
-	{
-		m_mysql=src.m_mysql;
-		src.m_mysql=nullptr;
-	}
-	basic_database& operator==(const basic_database&) = delete;
-	basic_database& operator==(basic_database&& src)
-	{
-		if(this!=&src)
+			unsigned int field_count()
+			{
+				return mysql_field_count(m_mysql);
+			}
+
+			uint64_t insert_id()
+			{
+				return mysql_insert_id(m_mysql);
+			}
+
+		protected:
+			MYSQL *m_mysql;
+			void throw_exception() { throw mysql::error(*this); }
+		};
+
+#if MARIADB_VERSION_ID >= 050500
+
+		class async_connection;
+
+#endif // MariaDB
+
+		class database : public basic_database, public qtl::base_database<database, statement>
 		{
-			if(m_mysql)
+		public:
+			database() = default;
+
+			bool open(const char *host, const char *user, const char *passwd, const char *db,
+					  unsigned long clientflag = 0, unsigned int port = 0, const char *unix_socket = nullptr)
+			{
+				if (m_mysql == nullptr)
+					m_mysql = mysql_init(nullptr);
+				return mysql_real_connect(m_mysql, host, user, passwd, db, port, unix_socket, clientflag) != nullptr;
+			}
+			void close()
+			{
 				mysql_close(m_mysql);
-			m_mysql=src.m_mysql;
-			src.m_mysql=nullptr;
-		}
-		return *this;
-	}
-
-	MYSQL* handle() { return m_mysql; }
-
-	void options(enum mysql_option option, const void *arg)
-	{
-		if(mysql_options(m_mysql, option, arg)!=0)
-		throw_exception();
-	}
-	void charset_name(const char* charset)
-	{
-		if(mysql_set_character_set(m_mysql, charset)!=0)
-			throw_exception();
-	}
-	void protocol(mysql_protocol_type type)
-	{
-		return options(MYSQL_OPT_PROTOCOL, &type);
-	}
-	void reconnect(my_bool re)
-	{
-		return options(MYSQL_OPT_RECONNECT, &re);
-	}
-
-	const char* current() const
-	{
-		return m_mysql->db;
-	}
-
-	unsigned int error() const
-	{
-		return mysql_errno(m_mysql);
-	}
-	const char* errmsg() const
-	{
-		return mysql_error(m_mysql);
-	}
-
-	uint64_t affected_rows()
-	{
-		return mysql_affected_rows(m_mysql);
-	}
-
-	unsigned int field_count()
-	{
-		return mysql_field_count(m_mysql);
-	}
-
-	uint64_t insert_id()
-	{
-		return mysql_insert_id(m_mysql);
-	}
-
-protected:
-	MYSQL* m_mysql;
-	void throw_exception() { throw mysql::error(*this); }
-};
-
-#if MARIADB_VERSION_ID >= 050500
-
-class async_connection;
-
-#endif //MariaDB
-
-class database : public basic_database, public qtl::base_database<database, statement>
-{
-public:
-	database() = default;
-
-	bool open(const char *host, const char *user, const char *passwd, const char *db,
-		unsigned long clientflag = 0, unsigned int port = 0, const char *unix_socket = nullptr)
-	{
-		if (m_mysql == nullptr) m_mysql = mysql_init(nullptr);
-		return mysql_real_connect(m_mysql, host, user, passwd, db, port, unix_socket, clientflag) != nullptr;
-	}
-	void close()
-	{
-		mysql_close(m_mysql);
-		m_mysql = nullptr;
-	}
-
-	statement open_command(const char* query_text, size_t text_length)
-	{
-		statement stmt(*this);
-		stmt.open(query_text, text_length);
-		return stmt;
-	}
-	statement open_command(const char* query_text)
-	{
-		return open_command(query_text, strlen(query_text));
-	}
-	statement open_command(const std::string& query_text)
-	{
-		return open_command(query_text.data(), query_text.length());
-	}
-
-	void refresh(unsigned int options)
-	{
-		if (mysql_refresh(m_mysql, options) < 0)
-			throw_exception();
-	}
-
-	void select(const char* db)
-	{
-		if (mysql_select_db(m_mysql, db) != 0)
-			throw_exception();
-	}
-
-	void simple_execute(const char* query_text, uint64_t* paffected = nullptr)
-	{
-		if (mysql_query(m_mysql, query_text) != 0)
-			throw_exception();
-		if (paffected) *paffected = affected_rows();
-	}
-	void simple_execute(const char* query_text, unsigned long text_length, uint64_t* paffected = nullptr)
-	{
-		if (text_length == 0) text_length = (unsigned long)strlen(query_text);
-		if (mysql_real_query(m_mysql, query_text, text_length) != 0)
-			throw_exception();
-		if (paffected) *paffected = affected_rows();
-	}
-
-	void auto_commit(bool on)
-	{
-		if (mysql_autocommit(m_mysql, on ? 1 : 0) != 0)
-			throw_exception();
-	}
-	void begin_transaction()
-	{
-		auto_commit(false);
-	}
-	void rollback()
-	{
-		if (mysql_rollback(m_mysql) != 0)
-			throw_exception();
-		auto_commit(true);
-	}
-	void commit()
-	{
-		if (mysql_commit(m_mysql) != 0)
-			throw_exception();
-		auto_commit(true);
-	}
-
-	bool is_alive()
-	{
-		return mysql_ping(m_mysql) == 0;
-	}
-
-	template<typename Pred>
-	bool simple_query(const char* query, unsigned long length, Pred&& pred)
-	{
-		simple_execute(query, length);
-
-		unsigned int fieldCount = mysql_field_count(m_mysql);
-		MYSQL_RES* result = mysql_store_result(m_mysql);
-		if (fieldCount > 0 && result)
-		{
-			MYSQL_RES* result = mysql_store_result(m_mysql);
-			MYSQL_ROW row;
-			while (row = mysql_fetch_row(result))
-			{
-				if (!pred(*this, row, fieldCount))
-					break;
+				m_mysql = nullptr;
 			}
-			mysql_free_result(result);
-			return true;
-		}
-		return false;
-	}
 
-	template<typename LocalInfile>
-	void set_local_infile_factory(local_infile_factory<LocalInfile>* factory)
-	{
-		typedef local_infile_factory<LocalInfile> factory_type;
-		if (factory == nullptr)
-		{
-			reset_local_infile();
-		}
-		else
-		{
-			mysql_set_local_infile_handler(m_mysql, &factory_type::local_infile_init,
-				&factory_type::local_infile_read,
-				&factory_type::local_infile_end,
-				&factory_type::local_infile_error, factory);
-		}
-	}
-	void reset_local_infile()
-	{
-		mysql_set_local_infile_default(m_mysql);
-	}
+			statement open_command(const char *query_text, size_t text_length)
+			{
+				statement stmt(*this);
+				stmt.open(query_text, text_length);
+				return stmt;
+			}
+			statement open_command(const char *query_text)
+			{
+				return open_command(query_text, strlen(query_text));
+			}
+			statement open_command(const std::string &query_text)
+			{
+				return open_command(query_text.data(), query_text.length());
+			}
+
+			void refresh(unsigned int options)
+			{
+				if (mysql_refresh(m_mysql, options) < 0)
+					throw_exception();
+			}
+
+			void select(const char *db)
+			{
+				if (mysql_select_db(m_mysql, db) != 0)
+					throw_exception();
+			}
+
+			void simple_execute(const char *query_text, uint64_t *paffected = nullptr)
+			{
+				if (mysql_query(m_mysql, query_text) != 0)
+					throw_exception();
+				if (paffected)
+					*paffected = affected_rows();
+			}
+			void simple_execute(const char *query_text, unsigned long text_length, uint64_t *paffected = nullptr)
+			{
+				if (text_length == 0)
+					text_length = (unsigned long)strlen(query_text);
+				if (mysql_real_query(m_mysql, query_text, text_length) != 0)
+					throw_exception();
+				if (paffected)
+					*paffected = affected_rows();
+			}
+
+			void auto_commit(bool on)
+			{
+				if (mysql_autocommit(m_mysql, on ? 1 : 0) != 0)
+					throw_exception();
+			}
+			void begin_transaction()
+			{
+				auto_commit(false);
+			}
+			void rollback()
+			{
+				if (mysql_rollback(m_mysql) != 0)
+					throw_exception();
+				auto_commit(true);
+			}
+			void commit()
+			{
+				if (mysql_commit(m_mysql) != 0)
+					throw_exception();
+				auto_commit(true);
+			}
+
+			bool is_alive()
+			{
+				return mysql_ping(m_mysql) == 0;
+			}
+
+			template <typename Pred>
+			bool simple_query(const char *query, unsigned long length, Pred &&pred)
+			{
+				simple_execute(query, length);
+
+				unsigned int fieldCount = mysql_field_count(m_mysql);
+				MYSQL_RES *result = mysql_store_result(m_mysql);
+				if (fieldCount > 0 && result)
+				{
+					MYSQL_RES *result = mysql_store_result(m_mysql);
+					MYSQL_ROW row;
+					while (row = mysql_fetch_row(result))
+					{
+						if (!pred(*this, row, fieldCount))
+							break;
+					}
+					mysql_free_result(result);
+					return true;
+				}
+				return false;
+			}
+
+			template <typename LocalInfile>
+			void set_local_infile_factory(local_infile_factory<LocalInfile> *factory)
+			{
+				typedef local_infile_factory<LocalInfile> factory_type;
+				if (factory == nullptr)
+				{
+					reset_local_infile();
+				}
+				else
+				{
+					mysql_set_local_infile_handler(m_mysql, &factory_type::local_infile_init,
+												   &factory_type::local_infile_read,
+												   &factory_type::local_infile_end,
+												   &factory_type::local_infile_error, factory);
+				}
+			}
+			void reset_local_infile()
+			{
+				mysql_set_local_infile_default(m_mysql);
+			}
 
 #if MARIADB_VERSION_ID >= 050500
 
-	async_connection async_mode();
+			async_connection async_mode();
 
-#endif //MariaDB
-
-};
+#endif // MariaDB
+		};
 
 #if MARIADB_VERSION_ID >= 100000
 
-inline int event_flags(int status) NOEXCEPT
-{
-	int flags = 0;
-	if (status&MYSQL_WAIT_READ)
-		flags |= event::ef_read;
-	if (status&MYSQL_WAIT_WRITE)
-		flags |= event::ef_write;
-	if (status&MYSQL_WAIT_EXCEPT)
-		flags |= event::ef_exception;
-	return flags;
-}
-
-inline int mysql_status(int flags) NOEXCEPT
-{
-	int status = 0;
-	if (flags&event::ef_read)
-		status |= MYSQL_WAIT_READ;
-	if (flags&event::ef_write)
-		status |= MYSQL_WAIT_WRITE;
-	if (flags&event::ef_exception)
-		status |= MYSQL_WAIT_EXCEPT;
-	if (flags&event::ef_timeout)
-		status |= MYSQL_WAIT_TIMEOUT;
-	return status;
-}
-
-class async_connection;
-
-class async_statement : public base_statement
-{
-public:
-	async_statement() = default;
-	async_statement(async_connection& db);
-	async_statement(async_statement&& src) 
-		: base_statement(std::move(src))
-	{
-		m_event=src.m_event;
-		src.m_event=nullptr;
-	}
-	async_statement& operator=(async_statement&& src)
-	{
-		base_statement::operator =(std::move(src));
-		m_event=src.m_event;
-		src.m_event=nullptr;
-		return *this;
-	}
-	~async_statement()
-	{
-		close();
-	}
-
-	/*
-		Handler defiens as:
-		void handler(const qtl::mysql::error& e);
-	 */
-	template<typename Handler>
-	void open(Handler&& handler, const char *query_text, size_t text_length=0)
-	{
-		if(text_length==0) text_length=strlen(query_text);
-		if(m_stmt)
+		inline int event_flags(int status) NOEXCEPT
 		{
-			std::string text(query_text, text_length);
-			reset([this, text, handler](const mysql::error& e) mutable {
+			int flags = 0;
+			if (status & MYSQL_WAIT_READ)
+				flags |= event::ef_read;
+			if (status & MYSQL_WAIT_WRITE)
+				flags |= event::ef_write;
+			if (status & MYSQL_WAIT_EXCEPT)
+				flags |= event::ef_exception;
+			return flags;
+		}
+
+		inline int mysql_status(int flags) NOEXCEPT
+		{
+			int status = 0;
+			if (flags & event::ef_read)
+				status |= MYSQL_WAIT_READ;
+			if (flags & event::ef_write)
+				status |= MYSQL_WAIT_WRITE;
+			if (flags & event::ef_exception)
+				status |= MYSQL_WAIT_EXCEPT;
+			if (flags & event::ef_timeout)
+				status |= MYSQL_WAIT_TIMEOUT;
+			return status;
+		}
+
+		class async_connection;
+
+		class async_statement : public base_statement
+		{
+		public:
+			async_statement() = default;
+			async_statement(async_connection &db);
+			async_statement(async_statement &&src)
+				: base_statement(std::move(src))
+			{
+				m_event = src.m_event;
+				src.m_event = nullptr;
+			}
+			async_statement &operator=(async_statement &&src)
+			{
+				base_statement::operator=(std::move(src));
+				m_event = src.m_event;
+				src.m_event = nullptr;
+				return *this;
+			}
+			~async_statement()
+			{
+				close();
+			}
+
+			/*
+				Handler defiens as:
+				void handler(const qtl::mysql::error& e);
+			 */
+			template <typename Handler>
+			void open(Handler &&handler, const char *query_text, size_t text_length = 0)
+			{
+				if (text_length == 0)
+					text_length = strlen(query_text);
+				if (m_stmt)
+				{
+					std::string text(query_text, text_length);
+					reset([this, text, handler](const mysql::error &e) mutable
+						  {
 				if(e)
 				{
 					handler(e);
 					return;
 				}
 
-				prepare(text.data(), text.size(), std::forward<Handler>(handler));
-			});
-		}
-		else
-		{
-			prepare(query_text, text_length, std::forward<Handler>(handler));
-		}
-	}
-
-	/*
-		ExecuteHandler defiens as:
-		void handler(const qtl::mysql::error& e, uint64_t affected);
-	 */
-	template<typename ExecuteHandler>
-	void execute(ExecuteHandler&& handler)
-	{
-		resize_binders(0);
-		int ret=0;
-		int status = mysql_stmt_execute_start(&ret, m_stmt);
-		if(status)
-			wait_execute(status, std::forward<ExecuteHandler>(handler));
-		else if(ret)
-			handler(mysql::error(*this), 0);
-		else
-			handler(mysql::error(), affetced_rows());
-	}
-
-	template<typename Types, typename Handler>
-	void execute(const Types& params, Handler&& handler)
-	{
-		unsigned long count=mysql_stmt_param_count(m_stmt);
-		if(count>0)
-		{
-			resize_binders(count);
-			qtl::bind_params(*this, params);
-			if(mysql_stmt_bind_param(m_stmt, &m_binders.front()))
-				throw_exception();
-			for(size_t i=0; i!=count; i++)
-			{
-				if(m_binderAddins[i].m_after_fetch)
-					m_binderAddins[i].m_after_fetch(m_binders[i]);
-			}
-		}
-		execute(std::forward<Handler>(handler));
-	}
-
-	template<typename Types, typename RowHandler, typename FinishHandler>
-	void fetch(Types&& values, RowHandler&& row_handler, FinishHandler&& finish_handler)
-	{
-		if(m_result==nullptr)
-		{
-			unsigned long count=mysql_stmt_field_count(m_stmt);
-			if(count>0)
-			{
-				m_result=mysql_stmt_result_metadata(m_stmt);
-				if(m_result==nullptr) throw_exception();
-				resize_binders(count);
-				qtl::bind_record(*this, std::forward<Types>(values));
-				set_binders();
-				if(mysql_stmt_bind_result(m_stmt, m_binders.data())!=0)
+				prepare(text.data(), text.size(), std::forward<Handler>(handler)); });
+				}
+				else
 				{
-					finish_handler(mysql::error(*this));
-					return;
+					prepare(query_text, text_length, std::forward<Handler>(handler));
 				}
 			}
-		}
-		fetch(std::forward<RowHandler>(row_handler), std::forward<FinishHandler>(finish_handler));
-	}
 
-	template<typename RowHandler, typename FinishHandler>
-	void fetch(RowHandler&& row_handler, FinishHandler&& finish_handler)
-	{
-		int ret = 0;
-		int status = start_fetch(&ret);
-		if (status == 0)
-			status = after_fetch(status, ret, std::forward<RowHandler>(row_handler), std::forward<FinishHandler>(finish_handler));
-		if (status)
-			wait_fetch(status, std::forward<RowHandler>(row_handler), std::forward<FinishHandler>(finish_handler));
-	}
-
-	template<typename Handler>
-	void reset(Handler&& handler)
-	{
-		my_bool ret=false;
-		int status = mysql_stmt_reset_start(&ret, m_stmt);
-		if(status)
-			wait_operation<my_bool>(status, &mysql_stmt_reset_cont, handler);
-		else
-			handler( (ret) ? mysql::error(*this) : mysql::error());
-	}
-
-	void close()
-	{
-		base_statement::close();
-	}
-
-	template<typename Handler>
-	void close(Handler&& handler)
-	{
-		if(m_result)
-		{
-			my_bool ret=0;
-			int status = mysql_stmt_free_result_start(&ret, m_stmt);
-			if(status)
+			/*
+				ExecuteHandler defiens as:
+				void handler(const qtl::mysql::error& e, uint64_t affected);
+			 */
+			template <typename ExecuteHandler>
+			void execute(ExecuteHandler &&handler)
 			{
-				this->wait_free_result(status, [this, handler](const mysql::error& e) mutable {
-					m_result=nullptr;
-					if (e)
-						handler(e);
-					else
-						close(handler);
-				});
-			}
-			else if(ret)
-				handler(mysql::error(*this));
-			else
-				m_result=nullptr;
-		}
-		if(m_stmt)
-		{
-			my_bool ret=0;
-			int status = mysql_stmt_close_start(&ret, m_stmt);
-			if(status)
-			{
-				wait_operation<my_bool>(status, &mysql_stmt_close_cont, [this, handler](const mysql::error& e) mutable {
-					m_stmt=nullptr;
-					handler(e);
-				});;
-			}
-			else
-			{
-				m_stmt = nullptr;
-				handler((ret) ? mysql::error(*this) : mysql::error());
-			}
-		}
-	}
-
-	template<typename Handler>
-	void next_result(Handler&& handler)
-	{
-		if(m_result)
-		{
-			mysql_free_result(m_result);
-			m_result = nullptr;
-		}
-		int ret=0;
-		do
-		{
-			int status = mysql_stmt_next_result_start(&ret, m_stmt);
-			if (status)
-			{
-				wait_next_result(status, std::forward<Handler>(handler));
-				return;
-			}
-		}while(ret==0 && mysql_stmt_field_count(m_stmt)<=0);
-		handler((ret) ? mysql::error(*this) : mysql::error());
-	}
-
-
-private:
-	event* m_event;
-
-	template<typename Handler>
-	void prepare(const char *query_text, size_t text_length, Handler&& handler)
-	{
-		int ret;
-		int status=mysql_stmt_prepare_start(&ret, m_stmt, query_text, (unsigned long)text_length);
-		if(status)
-			wait_operation<int>(status, &mysql_stmt_prepare_cont, handler);
-		else
-			handler((ret) ? mysql::error(*this) : mysql::error());
-	}
-
-	template<typename Ret, typename Func, typename Handler>
-	void wait_operation(int status, Func func, Handler&& handler)
-	{
-		m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
-			[this, func, handler](int flags) mutable {
-				Ret ret = 0;
-				int status = func(&ret, m_stmt, mysql_status(flags));
-				if (status)
-					wait_operation<Ret>(status, func, handler);
-				else
-					handler((ret) ? mysql::error(*this) : mysql::error());
-		});
-	}
-
-	template<typename ExecuteHandler>
-	void wait_execute(int status, ExecuteHandler&& handler)
-	{
-		m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
-			[this, handler](int flags) mutable {
+				resize_binders(0);
 				int ret = 0;
-				int status = mysql_stmt_execute_cont(&ret, m_stmt, mysql_status(flags));
+				int status = mysql_stmt_execute_start(&ret, m_stmt);
 				if (status)
-					wait_execute(status, handler);
-				else if(ret)
+					wait_execute(status, std::forward<ExecuteHandler>(handler));
+				else if (ret)
 					handler(mysql::error(*this), 0);
 				else
 					handler(mysql::error(), affetced_rows());
-		});
-	}
+			}
 
-	template<typename RowHandler, typename FinishHandler>
-	void wait_fetch(int status, RowHandler&& row_handler, FinishHandler&& finish_handler)
-	{
-		m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
-			[this, row_handler, finish_handler](int flags) mutable {
+			template <typename Types, typename Handler>
+			void execute(const Types &params, Handler &&handler)
+			{
+				unsigned long count = mysql_stmt_param_count(m_stmt);
+				if (count > 0)
+				{
+					resize_binders(count);
+					qtl::bind_params(*this, params);
+					if (mysql_stmt_bind_param(m_stmt, &m_binders.front()))
+						throw_exception();
+					for (size_t i = 0; i != count; i++)
+					{
+						if (m_binderAddins[i].m_after_fetch)
+							m_binderAddins[i].m_after_fetch(m_binders[i]);
+					}
+				}
+				execute(std::forward<Handler>(handler));
+			}
+
+			template <typename Types, typename RowHandler, typename FinishHandler>
+			void fetch(Types &&values, RowHandler &&row_handler, FinishHandler &&finish_handler)
+			{
+				if (m_result == nullptr)
+				{
+					unsigned long count = mysql_stmt_field_count(m_stmt);
+					if (count > 0)
+					{
+						m_result = mysql_stmt_result_metadata(m_stmt);
+						if (m_result == nullptr)
+							throw_exception();
+						resize_binders(count);
+						qtl::bind_record(*this, std::forward<Types>(values));
+						set_binders();
+						if (mysql_stmt_bind_result(m_stmt, m_binders.data()) != 0)
+						{
+							finish_handler(mysql::error(*this));
+							return;
+						}
+					}
+				}
+				fetch(std::forward<RowHandler>(row_handler), std::forward<FinishHandler>(finish_handler));
+			}
+
+			template <typename RowHandler, typename FinishHandler>
+			void fetch(RowHandler &&row_handler, FinishHandler &&finish_handler)
+			{
 				int ret = 0;
-				int status = mysql_stmt_fetch_cont(&ret, m_stmt, mysql_status(flags));
+				int status = start_fetch(&ret);
 				if (status == 0)
 					status = after_fetch(status, ret, std::forward<RowHandler>(row_handler), std::forward<FinishHandler>(finish_handler));
 				if (status)
 					wait_fetch(status, std::forward<RowHandler>(row_handler), std::forward<FinishHandler>(finish_handler));
-		});
-	}
+			}
 
-	int start_fetch(int* ret)
-	{
-		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]);
-		}
-		return mysql_stmt_fetch_start(ret, m_stmt);
-	}
+			template <typename Handler>
+			void reset(Handler &&handler)
+			{
+				my_bool ret = false;
+				int status = mysql_stmt_reset_start(&ret, m_stmt);
+				if (status)
+					wait_operation<my_bool>(status, &mysql_stmt_reset_cont, handler);
+				else
+					handler((ret) ? mysql::error(*this) : mysql::error());
+			}
 
-	template<typename RowHandler, typename FinishHandler>
-	int after_fetch(int status, int ret, RowHandler&& row_handler, FinishHandler&& finish_handler)
-	{
-		while (status == 0)
-		{
-			if (ret == 0 || ret == MYSQL_DATA_TRUNCATED)
+			void close()
+			{
+				base_statement::close();
+			}
+
+			template <typename Handler>
+			void close(Handler &&handler)
+			{
+				if (m_result)
+				{
+					my_bool ret = 0;
+					int status = mysql_stmt_free_result_start(&ret, m_stmt);
+					if (status)
+					{
+						this->wait_free_result(status, [this, handler](const mysql::error &e) mutable
+											   {
+					m_result=nullptr;
+					if (e)
+						handler(e);
+					else
+						close(handler); });
+					}
+					else if (ret)
+						handler(mysql::error(*this));
+					else
+						m_result = nullptr;
+				}
+				if (m_stmt)
+				{
+					my_bool ret = 0;
+					int status = mysql_stmt_close_start(&ret, m_stmt);
+					if (status)
+					{
+						wait_operation<my_bool>(status, &mysql_stmt_close_cont, [this, handler](const mysql::error &e) mutable
+												{
+					m_stmt=nullptr;
+					handler(e); });
+						;
+					}
+					else
+					{
+						m_stmt = nullptr;
+						handler((ret) ? mysql::error(*this) : mysql::error());
+					}
+				}
+			}
+
+			template <typename Handler>
+			void next_result(Handler &&handler)
+			{
+				if (m_result)
+				{
+					mysql_free_result(m_result);
+					m_result = nullptr;
+				}
+				int ret = 0;
+				do
+				{
+					int status = mysql_stmt_next_result_start(&ret, m_stmt);
+					if (status)
+					{
+						wait_next_result(status, std::forward<Handler>(handler));
+						return;
+					}
+				} while (ret == 0 && mysql_stmt_field_count(m_stmt) <= 0);
+				handler((ret) ? mysql::error(*this) : mysql::error());
+			}
+
+		private:
+			event *m_event;
+
+			template <typename Handler>
+			void prepare(const char *query_text, size_t text_length, Handler &&handler)
+			{
+				int ret;
+				int status = mysql_stmt_prepare_start(&ret, m_stmt, query_text, (unsigned long)text_length);
+				if (status)
+					wait_operation<int>(status, &mysql_stmt_prepare_cont, handler);
+				else
+					handler((ret) ? mysql::error(*this) : mysql::error());
+			}
+
+			template <typename Ret, typename Func, typename Handler>
+			void wait_operation(int status, Func func, Handler &&handler)
+			{
+				m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
+										[this, func, handler](int flags) mutable
+										{
+											Ret ret = 0;
+											int status = func(&ret, m_stmt, mysql_status(flags));
+											if (status)
+												wait_operation<Ret>(status, func, handler);
+											else
+												handler((ret) ? mysql::error(*this) : mysql::error());
+										});
+			}
+
+			template <typename ExecuteHandler>
+			void wait_execute(int status, ExecuteHandler &&handler)
+			{
+				m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
+										[this, handler](int flags) mutable
+										{
+											int ret = 0;
+											int status = mysql_stmt_execute_cont(&ret, m_stmt, mysql_status(flags));
+											if (status)
+												wait_execute(status, handler);
+											else if (ret)
+												handler(mysql::error(*this), 0);
+											else
+												handler(mysql::error(), affetced_rows());
+										});
+			}
+
+			template <typename RowHandler, typename FinishHandler>
+			void wait_fetch(int status, RowHandler &&row_handler, FinishHandler &&finish_handler)
+			{
+				m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
+										[this, row_handler, finish_handler](int flags) mutable
+										{
+											int ret = 0;
+											int status = mysql_stmt_fetch_cont(&ret, m_stmt, mysql_status(flags));
+											if (status == 0)
+												status = after_fetch(status, ret, std::forward<RowHandler>(row_handler), std::forward<FinishHandler>(finish_handler));
+											if (status)
+												wait_fetch(status, std::forward<RowHandler>(row_handler), std::forward<FinishHandler>(finish_handler));
+										});
+			}
+
+			int start_fetch(int *ret)
 			{
 				for (size_t i = 0; i != m_binders.size(); i++)
 				{
-					m_binderAddins[i].is_truncated = (ret == MYSQL_DATA_TRUNCATED);
-					if (m_binderAddins[i].m_after_fetch)
-						m_binderAddins[i].m_after_fetch(m_binders[i]);
+					if (m_binderAddins[i].m_before_fetch)
+						m_binderAddins[i].m_before_fetch(m_binders[i]);
 				}
-				if (row_handler())
-					status = start_fetch(&ret);
-				else
+				return mysql_stmt_fetch_start(ret, m_stmt);
+			}
+
+			template <typename RowHandler, typename FinishHandler>
+			int after_fetch(int status, int ret, RowHandler &&row_handler, FinishHandler &&finish_handler)
+			{
+				while (status == 0)
 				{
-					finish_handler(mysql::error());
-					break;
-				}
+					if (ret == 0 || ret == MYSQL_DATA_TRUNCATED)
+					{
+						for (size_t i = 0; i != m_binders.size(); i++)
+						{
+							m_binderAddins[i].is_truncated = (ret == MYSQL_DATA_TRUNCATED);
+							if (m_binderAddins[i].m_after_fetch)
+								m_binderAddins[i].m_after_fetch(m_binders[i]);
+						}
+						if (row_handler())
+							status = start_fetch(&ret);
+						else
+						{
+							finish_handler(mysql::error());
+							break;
+						}
+					}
+					else if (ret == 1)
+					{
+						finish_handler(mysql::error(*this));
+						break;
+					}
+					else
+					{
+						finish_handler(mysql::error());
+						break;
+					}
+				};
+				return status;
 			}
-			else if (ret == 1)
+
+			template <typename ResultHandler>
+			void wait_free_result(int status, ResultHandler &&handler) NOEXCEPT
 			{
-				finish_handler(mysql::error(*this));
-				break;
+				m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
+										[this, handler](int flags) mutable
+										{
+											my_bool ret = false;
+											int status = mysql_stmt_free_result_cont(&ret, m_stmt, mysql_status(flags));
+											if (status)
+												wait_free_result(status, handler);
+											else
+												handler(mysql::error());
+										});
 			}
-			else
+
+			template <typename Handler>
+			void wait_next_result(int status, Handler &&handler)
 			{
-				finish_handler(mysql::error());
-				break;
+				m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
+										[this, handler](int flags) mutable
+										{
+											int ret = 0;
+											int status = mysql_stmt_next_result_cont(&ret, m_stmt, mysql_status(flags));
+											if (status)
+												wait_next_result(status, handler);
+											else if (ret)
+												handler(mysql::error(*this));
+											else if (mysql_stmt_field_count(m_stmt) > 0)
+												handler(mysql::error());
+											else
+												next_result(std::forward<Handler>(handler));
+										});
 			}
 		};
-		return status;
-	}
 
-	template<typename ResultHandler>
-	void wait_free_result(int status, ResultHandler&& handler) NOEXCEPT
-	{
-		m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
-			[this, handler](int flags) mutable {
-				my_bool ret = false;
-				int status = mysql_stmt_free_result_cont(&ret, m_stmt, mysql_status(flags));
+		class async_connection : public basic_database, public qtl::async_connection<async_connection, async_statement>
+		{
+		public:
+			async_connection() = default;
+
+			/*
+				OpenHandler defines as:
+					void handler(const qtl::mysql::error& e) NOEXCEPT;
+			*/
+			template <typename EventLoop, typename OpenHandler>
+			void open(EventLoop &ev, OpenHandler &&handler, const char *host, const char *user, const char *passwd, const char *db,
+					  unsigned long clientflag = 0, unsigned int port = 0, const char *unix_socket = nullptr)
+			{
+				if (m_mysql == nullptr)
+					m_mysql = mysql_init(nullptr);
+
+				mysql_options(m_mysql, MYSQL_OPT_NONBLOCK, 0);
+
+				MYSQL *ret = nullptr;
+				int status = mysql_real_connect_start(&ret, m_mysql, host, user, passwd, db, port, unix_socket, clientflag);
+				bind(ev);
 				if (status)
-					wait_free_result(status, handler);
+					wait_connect(status, std::forward<OpenHandler>(handler));
 				else
-					handler(mysql::error());
-		});
-	}
+					handler((ret == nullptr) ? mysql::error(*this) : mysql::error());
+			}
 
-	template<typename Handler>
-	void wait_next_result(int status, Handler&& handler)
-	{
-		m_event->set_io_handler(event_flags(status), mysql_get_timeout_value(m_stmt->mysql),
-			[this, handler](int flags) mutable {
-			int ret = 0;
-			int status = mysql_stmt_next_result_cont(&ret, m_stmt, mysql_status(flags));
-			if (status)
-				wait_next_result(status, handler);
-			else if (ret)
-				handler(mysql::error(*this));
-			else if (mysql_stmt_field_count(m_stmt) > 0)
-				handler(mysql::error());
-			else
-				next_result(std::forward<Handler>(handler));
-		});
-	}
-
-};
-
-class async_connection : public basic_database, public qtl::async_connection<async_connection, async_statement>
-{
-public:
-	async_connection() = default;
-
-	/*
-		OpenHandler defines as:
-			void handler(const qtl::mysql::error& e) NOEXCEPT;
-	*/
-	template<typename EventLoop, typename OpenHandler>
-	void open(EventLoop& ev, OpenHandler&& handler, const char *host, const char *user, const char *passwd, const char *db,
-		unsigned long clientflag = 0, unsigned int port = 0, const char *unix_socket = nullptr)
-	{
-		if (m_mysql == nullptr)
-			m_mysql = mysql_init(nullptr);
-
-		mysql_options(m_mysql, MYSQL_OPT_NONBLOCK, 0);
-
-		MYSQL* ret = nullptr;
-		int status = mysql_real_connect_start(&ret, m_mysql, host, user, passwd, db, port, unix_socket, clientflag);
-		bind(ev);
-		if (status)
-			wait_connect(status, std::forward<OpenHandler>(handler));
-		else
-			handler((ret == nullptr) ? mysql::error(*this) : mysql::error());
-	}
-
-	/*
-		CloseHandler defines as:
-			void handler() NOEXCEPT;
-	*/
-	template<typename CloseHandler >
-	void close(CloseHandler&& handler) NOEXCEPT
-	{
-		int status  = mysql_close_start(m_mysql);
-		if (status)
-		{
-			wait_close(status, [this, handler]() mutable {
+			/*
+				CloseHandler defines as:
+					void handler() NOEXCEPT;
+			*/
+			template <typename CloseHandler>
+			void close(CloseHandler &&handler) NOEXCEPT
+			{
+				int status = mysql_close_start(m_mysql);
+				if (status)
+				{
+					wait_close(status, [this, handler]() mutable
+							   {
 				handler();
-				m_mysql = nullptr;
-			});
-		}
-		else
-		{
-			handler();
-			m_mysql = nullptr;
-		}
-	}
+				m_mysql = nullptr; });
+				}
+				else
+				{
+					handler();
+					m_mysql = nullptr;
+				}
+			}
 
-	/*
-		Handler defines as:
-			void handler(const qtl::mysql::error& e) NOEXCEPT;
-	*/
-	template<typename Handler>
-	void refresh(Handler&& handler, unsigned int options) NOEXCEPT
-	{
-		int ret = 0;
-		int status = mysql_refresh_start(&ret, m_mysql, options);
-		if (status)
-			wait_operation(status, &mysql_refresh_cont, std::forward<Handler>(handler));
-		else
-			handler((ret) ? mysql::error(*this) : mysql::error());
-	}
+			/*
+				Handler defines as:
+					void handler(const qtl::mysql::error& e) NOEXCEPT;
+			*/
+			template <typename Handler>
+			void refresh(Handler &&handler, unsigned int options) NOEXCEPT
+			{
+				int ret = 0;
+				int status = mysql_refresh_start(&ret, m_mysql, options);
+				if (status)
+					wait_operation(status, &mysql_refresh_cont, std::forward<Handler>(handler));
+				else
+					handler((ret) ? mysql::error(*this) : mysql::error());
+			}
 
-	template<typename Handler>
-	void select(Handler&& handler, const char* db) NOEXCEPT
-	{
-		int ret = 0;
-		int status = mysql_select_db_start(&ret, m_mysql, db);
-		if (status)
-			wait_operation(status, &mysql_select_db_cont, std::forward<Handler>(handler));
-		else
-			handler((ret) ? mysql::error(*this) : mysql::error());
-	}
+			template <typename Handler>
+			void select(Handler &&handler, const char *db) NOEXCEPT
+			{
+				int ret = 0;
+				int status = mysql_select_db_start(&ret, m_mysql, db);
+				if (status)
+					wait_operation(status, &mysql_select_db_cont, std::forward<Handler>(handler));
+				else
+					handler((ret) ? mysql::error(*this) : mysql::error());
+			}
 
-	template<typename Handler>
-	void is_alive(Handler&& handler) NOEXCEPT
-	{
-		int ret = 0;
-		int status = mysql_ping_start(&ret, m_mysql);
-		if (status)
-			wait_operation(status, &mysql_ping_cont, std::forward<Handler>(handler));
-		else
-			handler((ret) ? mysql::error(*this) : mysql::error());
-	}
+			template <typename Handler>
+			void is_alive(Handler &&handler) NOEXCEPT
+			{
+				int ret = 0;
+				int status = mysql_ping_start(&ret, m_mysql);
+				if (status)
+					wait_operation(status, &mysql_ping_cont, std::forward<Handler>(handler));
+				else
+					handler((ret) ? mysql::error(*this) : mysql::error());
+			}
 
-	/*
-		Handler defines as:
-			void handler(const qtl::mysql::error& e, uint64_t affected) NOEXCEPT;
-	*/
-	template<typename ExecuteHandler>
-	void simple_execute(ExecuteHandler&& handler, const char* query_text) NOEXCEPT
-	{
-		int ret = 0;
-		int status = mysql_query_start(&ret, m_mysql, query_text);
-		if (status)
-		{
-			wait_operation(status, &mysql_query_cont, [this, handler](const mysql::error& e) {
+			/*
+				Handler defines as:
+					void handler(const qtl::mysql::error& e, uint64_t affected) NOEXCEPT;
+			*/
+			template <typename ExecuteHandler>
+			void simple_execute(ExecuteHandler &&handler, const char *query_text) NOEXCEPT
+			{
+				int ret = 0;
+				int status = mysql_query_start(&ret, m_mysql, query_text);
+				if (status)
+				{
+					wait_operation(status, &mysql_query_cont, [this, handler](const mysql::error &e)
+								   {
 				uint64_t affected = 0;
 				if (!e) affected = affected_rows();
-				handler(e, affected);
-			});
-		}
-		else
-		{
-			uint64_t affected = 0;
-			if (ret >= 0) affected = affected_rows();
-			handler((ret) ? mysql::error(*this) : mysql::error(), affected);
-		}
-	}
+				handler(e, affected); });
+				}
+				else
+				{
+					uint64_t affected = 0;
+					if (ret >= 0)
+						affected = affected_rows();
+					handler((ret) ? mysql::error(*this) : mysql::error(), affected);
+				}
+			}
 
-	template<typename ExecuteHandler>
-	void simple_execute(ExecuteHandler&& handler, const char* query_text, unsigned long text_length) NOEXCEPT
-	{
-		int ret = 0;
-		int status = mysql_real_query_start(&ret, m_mysql, query_text, text_length);
-		if (status)
-		{
-			wait_operation(status, &mysql_real_query_cont, [this, handler](const mysql::error& e) mutable {
+			template <typename ExecuteHandler>
+			void simple_execute(ExecuteHandler &&handler, const char *query_text, unsigned long text_length) NOEXCEPT
+			{
+				int ret = 0;
+				int status = mysql_real_query_start(&ret, m_mysql, query_text, text_length);
+				if (status)
+				{
+					wait_operation(status, &mysql_real_query_cont, [this, handler](const mysql::error &e) mutable
+								   {
 				uint64_t affected = 0;
 				if (!e) affected = affected_rows();
-				handler(e, affected);
-			});
-		}
-		else
-		{
-			uint64_t affected = 0;
-			if (ret >= 0) affected = affected_rows();
-			handler((ret) ? mysql::error(*this) : mysql::error(), affected);
-		}
-	}
+				handler(e, affected); });
+				}
+				else
+				{
+					uint64_t affected = 0;
+					if (ret >= 0)
+						affected = affected_rows();
+					handler((ret) ? mysql::error(*this) : mysql::error(), affected);
+				}
+			}
 
-	template<typename Handler>
-	void auto_commit(Handler&& handler, bool on) NOEXCEPT
-	{
-		my_bool ret;
-		int status = mysql_autocommit_start(&ret, m_mysql, on ? 1 : 0);
-		if(status)
-			wait_operation(status, &mysql_autocommit_cont, std::forward<Handler>(handler));
-		else
-			handler((ret) ? mysql::error(*this) : mysql::error());
-	}
+			template <typename Handler>
+			void auto_commit(Handler &&handler, bool on) NOEXCEPT
+			{
+				my_bool ret;
+				int status = mysql_autocommit_start(&ret, m_mysql, on ? 1 : 0);
+				if (status)
+					wait_operation(status, &mysql_autocommit_cont, std::forward<Handler>(handler));
+				else
+					handler((ret) ? mysql::error(*this) : mysql::error());
+			}
 
-	template<typename Handler>
-	void begin_transaction(Handler&& handler) NOEXCEPT
-	{
-		auto_commit(handler, false);
-	}
+			template <typename Handler>
+			void begin_transaction(Handler &&handler) NOEXCEPT
+			{
+				auto_commit(handler, false);
+			}
 
-	template<typename Handler>
-	void rollback(Handler&& handler) NOEXCEPT
-	{
-		my_bool ret;
-		int status = mysql_rollback_start(&ret, m_mysql);
-		if (status)
-			wait_operation(status, &mysql_rollback_cont, std::forward<Handler>(handler));
-		else
-			handler((ret) ? mysql::error(*this) : mysql::error());
-	}
+			template <typename Handler>
+			void rollback(Handler &&handler) NOEXCEPT
+			{
+				my_bool ret;
+				int status = mysql_rollback_start(&ret, m_mysql);
+				if (status)
+					wait_operation(status, &mysql_rollback_cont, std::forward<Handler>(handler));
+				else
+					handler((ret) ? mysql::error(*this) : mysql::error());
+			}
 
-	template<typename Handler>
-	void commit(Handler&& handler) NOEXCEPT
-	{
-		my_bool ret;
-		int status = mysql_commit_start(&ret, m_mysql);
-		if (status)
-			wait_operation(status, &mysql_commit_cont, std::forward<Handler>(handler));
-		else
-			handler((ret) ? mysql::error(*this) : mysql::error());
-	}
+			template <typename Handler>
+			void commit(Handler &&handler) NOEXCEPT
+			{
+				my_bool ret;
+				int status = mysql_commit_start(&ret, m_mysql);
+				if (status)
+					wait_operation(status, &mysql_commit_cont, std::forward<Handler>(handler));
+				else
+					handler((ret) ? mysql::error(*this) : mysql::error());
+			}
 
-	/*
-		RowHandler defines as:
-			bool row_handler(MYSQL_ROW row, int field_count) NOEXCEPT;
-		ResultHandler defines as:
-			void result_handler(const qtl::mysql::error& e, size_t row_count) NOEXCEPT;
-	*/
-	template<typename RowHandler, typename ResultHandler>
-	void simple_query(const char* query, unsigned long length, RowHandler&& row_handler, ResultHandler&& result_handler) NOEXCEPT
-	{
-		simple_execute([this, row_handler, result_handler](const mysql::error& e, uint64_t affected) mutable {
+			/*
+				RowHandler defines as:
+					bool row_handler(MYSQL_ROW row, int field_count) NOEXCEPT;
+				ResultHandler defines as:
+					void result_handler(const qtl::mysql::error& e, size_t row_count) NOEXCEPT;
+			*/
+			template <typename RowHandler, typename ResultHandler>
+			void simple_query(const char *query, unsigned long length, RowHandler &&row_handler, ResultHandler &&result_handler) NOEXCEPT
+			{
+				simple_execute([this, row_handler, result_handler](const mysql::error &e, uint64_t affected) mutable
+							   {
 			if (e)
 			{
 				result_handler(e, 0);
@@ -1755,180 +1793,185 @@
 			else
 			{
 				result_handler(mysql::error(), 0);
+			} }, query, length);
 			}
-		}, query, length);
+
+			template <typename Handler>
+			void open_command(const char *query_text, size_t text_length, Handler &&handler)
+			{
+				std::shared_ptr<async_statement> stmt = std::make_shared<async_statement>(*this);
+				stmt->open([stmt, handler](const mysql::error &e) mutable
+						   { handler(e, stmt); }, query_text, (unsigned long)text_length);
+			}
+
+			socket_type socket() const NOEXCEPT { return mysql_get_socket(m_mysql); }
+
+		private:
+			template <typename OpenHandler>
+			void wait_connect(int status, OpenHandler &&handler) NOEXCEPT
+			{
+				m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
+												[this, handler](int flags) mutable
+												{
+													MYSQL *ret = nullptr;
+													int status = mysql_real_connect_cont(&ret, m_mysql, mysql_status(flags));
+													if (status)
+														wait_connect(status, handler);
+													else
+														handler((ret == nullptr) ? mysql::error(*this) : mysql::error());
+												});
+			}
+
+			template <typename CloseHandler>
+			void wait_close(int status, CloseHandler &&handler) NOEXCEPT
+			{
+				m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
+												[this, handler](int flags) mutable
+												{
+													MYSQL *ret = nullptr;
+													int status = mysql_close_cont(m_mysql, mysql_status(flags));
+													if (status)
+														wait_close(status, handler);
+													else
+														handler();
+												});
+			}
+
+			template <typename Func, typename Handler>
+			void wait_operation(int status, Func func, Handler &&handler) NOEXCEPT
+			{
+				m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
+												[this, func, handler](int flags) mutable
+												{
+													int ret = 0;
+													int status = func(&ret, m_mysql, mysql_status(flags));
+													if (status)
+														wait_operation(status, func, handler);
+													else
+														handler((ret) ? mysql::error(*this) : mysql::error());
+												});
+			}
+
+			template <typename RowHandler, typename ResultHandler>
+			void wait_query(int status, int field_count, RowHandler &&row_handler, ResultHandler &&result_handler) NOEXCEPT
+			{
+				m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
+												[this, field_count, row_handler, result_handler](int flags) mutable
+												{
+													MYSQL_RES *result = 0;
+													int status = mysql_store_result_cont(&result, m_mysql, mysql_status(flags));
+													if (status)
+														wait_query(status, field_count, row_handler, result_handler);
+													else if (result)
+														fetch_rows(result, field_count, 0, row_handler, result_handler);
+													else
+														result_handler(mysql::error(*this), 0);
+												});
+			}
+
+			template <typename RowHandler, typename ResultHandler>
+			void fetch_rows(MYSQL_RES *result, int field_count, size_t row_count, RowHandler &&row_handler, ResultHandler &&result_handler) NOEXCEPT
+			{
+				MYSQL_ROW row;
+				int status = mysql_fetch_row_start(&row, result);
+				if (status)
+					wait_fetch(status, result, field_count, row_count, row_handler, result_handler);
+				else if (row && row_handler(row, field_count))
+					fetch_rows(result, field_count, row_count + 1, row_handler, result_handler);
+				else
+					free_result(result, row_count, result_handler);
+			}
+
+			template <typename ResultHandler>
+			void free_result(MYSQL_RES *result, size_t row_count, ResultHandler &&result_handler) NOEXCEPT
+			{
+				int status = mysql_free_result_start(result);
+				if (status)
+					wait_free_result(status, result, row_count, result_handler);
+				else
+					result_handler(mysql::error(), row_count);
+			}
+
+			template <typename RowHandler, typename ResultHandler>
+			void wait_fetch(int status, MYSQL_RES *result, int field_count, size_t row_count, RowHandler &&row_handler, ResultHandler &&result_handler)
+			{
+				m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
+												[this, result, field_count, row_count, row_handler, result_handler](int flags) mutable
+												{
+													MYSQL_ROW row;
+													int status = mysql_fetch_row_cont(&row, result, mysql_status(flags));
+													if (status)
+														wait_fetch(status, result, field_count, row_count, row_handler, result_handler);
+													else if (result && row_handler(row, field_count))
+														fetch_rows(result, field_count, row_count + 1, row_handler, result_handler);
+													else
+														free_result(result, row_count, result_handler);
+												});
+			}
+
+			template <typename ResultHandler>
+			void wait_free_result(int status, MYSQL_RES *result, size_t row_count, ResultHandler &&handler) NOEXCEPT
+			{
+				m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
+												[this, result, row_count, handler](int flags) mutable
+												{
+													MYSQL *ret = nullptr;
+													int status = mysql_free_result_cont(result, mysql_status(flags));
+													if (status)
+														wait_free_result(status, result, row_count, handler);
+													else
+														handler(mysql::error(), row_count);
+												});
+			}
+		};
+
+		inline async_statement::async_statement(async_connection &db)
+			: base_statement(static_cast<basic_database &>(db))
+		{
+			m_event = db.event();
+		}
+
+#endif // MariaDB 10.0
+
+		typedef qtl::transaction<database> transaction;
+
+		template <typename Record>
+		using query_iterator = qtl::query_iterator<statement, Record>;
+
+		template <typename Record>
+		using query_result = qtl::query_result<statement, Record>;
+
+		template <typename Params>
+		inline statement &operator<<(statement &stmt, const Params &params)
+		{
+			stmt.reset();
+			stmt.execute(params);
+			return stmt;
+		}
+
+		inline error::error(const base_statement &stmt)
+		{
+			const char *errmsg = stmt.errmsg();
+			m_error = stmt.error();
+			if (errmsg)
+				m_errmsg = errmsg;
+		}
+
+		inline error::error(const basic_database &db)
+		{
+			const char *errmsg = db.errmsg();
+			m_error = db.error();
+			if (errmsg)
+				m_errmsg = errmsg;
+		}
+
+		inline base_statement::base_statement(basic_database &db)
+		{
+			m_stmt = mysql_stmt_init(db.handle());
+			m_result = nullptr;
+		}
+
 	}
-
-	template<typename Handler>
-	void open_command(const char* query_text, size_t text_length, Handler&& handler)
-	{
-		std::shared_ptr<async_statement> stmt=std::make_shared<async_statement>(*this);
-		stmt->open([stmt, handler](const mysql::error& e) mutable {
-			handler(e, stmt);
-		}, query_text, (unsigned long)text_length);
-	}
-
-	socket_type socket() const NOEXCEPT { return mysql_get_socket(m_mysql); }
-
-private:
-	template<typename OpenHandler>
-	void wait_connect(int status, OpenHandler&& handler) NOEXCEPT
-	{
-		m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
-			[this, handler](int flags) mutable {
-			MYSQL* ret = nullptr;
-			int status = mysql_real_connect_cont(&ret, m_mysql, mysql_status(flags));
-			if (status)
-				wait_connect(status, handler);
-			else
-				handler((ret == nullptr) ? mysql::error(*this) : mysql::error());
-		});
-	}
-
-	template<typename CloseHandler>
-	void wait_close(int status, CloseHandler&& handler) NOEXCEPT
-	{
-		m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
-			[this, handler](int flags) mutable {
-			MYSQL* ret = nullptr;
-			int status = mysql_close_cont(m_mysql, mysql_status(flags));
-			if (status)
-				wait_close(status, handler);
-			else
-				handler();
-		});
-	}
-
-	template<typename Func, typename Handler>
-	void wait_operation(int status, Func func, Handler&& handler) NOEXCEPT
-	{
-		m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
-			[this, func, handler](int flags) mutable {
-			int ret = 0;
-			int status = func(&ret, m_mysql, mysql_status(flags));
-			if (status)
-				wait_operation(status, func, handler);
-			else
-				handler((ret) ? mysql::error(*this) : mysql::error());
-		});
-	}
-
-	template<typename RowHandler, typename ResultHandler>
-	void wait_query(int status, int field_count, RowHandler&& row_handler, ResultHandler&& result_handler) NOEXCEPT
-	{
-		m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
-			[this, field_count, row_handler, result_handler](int flags) mutable {
-			MYSQL_RES* result = 0;
-			int status = mysql_store_result_cont(&result, m_mysql, mysql_status(flags));
-			if (status)
-				wait_query(status, field_count, row_handler, result_handler);
-			else if (result)
-				fetch_rows(result, field_count, 0, row_handler, result_handler);
-			else
-				result_handler(mysql::error(*this), 0);
-		});
-	}
-
-	template<typename RowHandler, typename ResultHandler>
-	void fetch_rows(MYSQL_RES* result, int field_count, size_t row_count, RowHandler&& row_handler, ResultHandler&& result_handler) NOEXCEPT
-	{
-		MYSQL_ROW row;
-		int status = mysql_fetch_row_start(&row, result);
-		if (status)
-			wait_fetch(status, result, field_count, row_count, row_handler, result_handler);
-		else if(row && row_handler(row, field_count))
-			fetch_rows(result, field_count, row_count + 1, row_handler, result_handler);
-		else
-			free_result(result, row_count, result_handler);
-	}
-
-	template<typename ResultHandler>
-	void free_result(MYSQL_RES* result, size_t row_count, ResultHandler&& result_handler) NOEXCEPT
-	{
-		int status = mysql_free_result_start(result);
-		if (status)
-			wait_free_result(status, result, row_count, result_handler);
-		else
-			result_handler(mysql::error(), row_count);
-	}
-
-	template<typename RowHandler, typename ResultHandler>
-	void wait_fetch(int status, MYSQL_RES* result, int field_count,  size_t row_count, RowHandler&& row_handler, ResultHandler&& result_handler)
-	{
-		m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
-			[this, result, field_count, row_count, row_handler, result_handler](int flags) mutable {
-			MYSQL_ROW row;
-			int status = mysql_fetch_row_cont(&row, result, mysql_status(flags));
-			if (status)
-				wait_fetch(status, result, field_count, row_count, row_handler, result_handler);
-			else if (result && row_handler(row, field_count))
-				fetch_rows(result, field_count, row_count+1, row_handler, result_handler);
-			else
-				free_result(result, row_count, result_handler);
-		});
-	}
-
-	template<typename ResultHandler>
-	void wait_free_result(int status, MYSQL_RES* result, size_t row_count, ResultHandler&& handler) NOEXCEPT
-	{
-		m_event_handler->set_io_handler(event_flags(status), mysql_get_timeout_value(m_mysql),
-			[this, result, row_count, handler](int flags) mutable {
-			MYSQL* ret = nullptr;
-			int status = mysql_free_result_cont(result, mysql_status(flags));
-			if (status)
-				wait_free_result(status, result, row_count, handler);
-			else
-				handler(mysql::error(), row_count);
-		});
-	}
-
-};
-
-inline 	async_statement::async_statement(async_connection& db) 
-: base_statement(static_cast<basic_database&>(db)) 
-{
-	m_event=db.event();
-}
-
-#endif //MariaDB 10.0
-
-typedef qtl::transaction<database> transaction;
-
-template<typename Record>
-using query_iterator = qtl::query_iterator<statement, Record>;
-
-template<typename Record>
-using query_result = qtl::query_result<statement, Record>;
-
-template<typename Params>
-inline statement& operator<<(statement& stmt, const Params& params)
-{
-	stmt.reset();
-	stmt.execute(params);
-	return stmt;
-}
-
-inline error::error(const base_statement& stmt)
-{
-	const char* errmsg=stmt.errmsg();
-	m_error=stmt.error();
-	if(errmsg) m_errmsg=errmsg;
-}
-
-inline error::error(const basic_database& db)
-{
-	const char* errmsg=db.errmsg();
-	m_error=db.error();
-	if(errmsg) m_errmsg=errmsg;
-}
-
-inline base_statement::base_statement(basic_database& db)
-{
-	m_stmt=mysql_stmt_init(db.handle());
-	m_result=nullptr;
-}
-
-}
 
 }
 

--
Gitblit v1.9.3