From 14337cf5b302c5385f0ae1393caf6df7e83fc539 Mon Sep 17 00:00:00 2001
From: znone <glyc@sina.com.cn>
Date: Sat, 07 Dec 2019 06:52:19 +0000
Subject: [PATCH] 1. 允许绑定字段到std::optional和std::any 2. 增加函数bind_fields可以一次绑定到多个字段 3. 查询函数返回数据库对象自身,以支持链式调用
---
include/qtl_mysql.hpp | 237 ++++++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 169 insertions(+), 68 deletions(-)
diff --git a/include/qtl_mysql.hpp b/include/qtl_mysql.hpp
index 834e3c1..8174bca 100644
--- a/include/qtl_mysql.hpp
+++ b/include/qtl_mysql.hpp
@@ -10,6 +10,7 @@
#include <string>
#include <vector>
#include <array>
+#include <utility>
#include <functional>
#include <algorithm>
#include <system_error>
@@ -83,8 +84,9 @@
void bind(bool& v)
{
init();
- buffer_type = MYSQL_TYPE_TINY;
+ buffer_type = MYSQL_TYPE_BIT;
buffer = &v;
+ buffer_length = 1;
}
void bind(int8_t& v)
{
@@ -275,6 +277,71 @@
}
};
+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:
@@ -409,7 +476,8 @@
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);
+ m_binderAddins[index].m_after_fetch =
+ if_null<typename std::remove_reference<Type>::type>(value);
}
}
@@ -518,6 +586,104 @@
}
}
+#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)
+ {
+ 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:
+ case MYSQL_TYPE_JSON:
+ 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)
@@ -571,7 +737,7 @@
template<typename Value>
struct if_null
{
- if_null(Value& value, Value&& def=Value()) : m_value(value), m_def(std::move(def)) { }
+ 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;
@@ -1000,71 +1166,6 @@
#endif //MariaDB
-};
-
-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);
- }
};
#if MARIADB_VERSION_ID >= 100000
--
Gitblit v1.9.3