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_odbc.hpp | 3479 ++++++++++++++++++++++++++++++-----------------------------
1 files changed, 1,755 insertions(+), 1,724 deletions(-)
diff --git a/include/qtl_odbc.hpp b/include/qtl_odbc.hpp
index 3233ead..5de6fcd 100644
--- a/include/qtl_odbc.hpp
+++ b/include/qtl_odbc.hpp
@@ -18,8 +18,7 @@
#if (ODBCVER >= 0x0380) && (_WIN32_WINNT >= 0x0602)
#define QTL_ODBC_ENABLE_ASYNC_MODE 1
-#endif //ODBC 3.80 && Windows
-
+#endif // ODBC 3.80 && Windows
#include "qtl_common.hpp"
#include "qtl_async.hpp"
@@ -27,1343 +26,1365 @@
namespace qtl
{
-namespace odbc
-{
+ namespace odbc
+ {
-template<SQLSMALLINT> class object;
-class base_database;
+ template <SQLSMALLINT>
+ class object;
+ class base_database;
-class error : public std::exception
-{
-public:
- error() : m_errno(SQL_SUCCESS) { }
- template<SQLSMALLINT Type>
- error(const object<Type>& h, SQLINTEGER code);
- error(SQLINTEGER code, const char* msg) : m_errno(code), m_errmsg(msg) { }
- SQLINTEGER code() const { return m_errno; }
- operator bool() const { return m_errno!=SQL_SUCCESS && m_errno!=SQL_SUCCESS_WITH_INFO; }
- virtual const char* what() const throw() override { return m_errmsg.data(); }
-private:
- SQLINTEGER m_errno;
- std::string m_errmsg;
-};
-
-template<SQLSMALLINT Type>
-class object
-{
-public:
- enum { handler_type=Type };
- object() : m_handle(SQL_NULL_HANDLE) { };
- object(const object&) = delete;
- object(object&& src) : m_handle(src.m_handle)
- {
- src.m_handle=SQL_NULL_HANDLE;
- }
- explicit object(SQLHANDLE parent)
- {
- verify_error(SQLAllocHandle(handler_type, parent, &m_handle));
- }
- ~object()
- {
- close();
- }
- object& operator=(const object&) = delete;
- object& operator=(object&& src)
- {
- if(this!=&src)
+ class error : public std::exception
{
- close();
- m_handle=src.m_handle;
- src.m_handle=NULL;
- }
- return *this;
- }
- SQLHANDLE handle() const { return m_handle; }
+ public:
+ error() : m_errno(SQL_SUCCESS) {}
+ template <SQLSMALLINT Type>
+ error(const object<Type> &h, SQLINTEGER code);
+ error(SQLINTEGER code, const char *msg) : m_errno(code), m_errmsg(msg) {}
+ SQLINTEGER code() const { return m_errno; }
+ operator bool() const { return m_errno != SQL_SUCCESS && m_errno != SQL_SUCCESS_WITH_INFO; }
+ virtual const char *what() const throw() override { return m_errmsg.data(); }
- void close()
- {
- if(m_handle)
+ private:
+ SQLINTEGER m_errno;
+ std::string m_errmsg;
+ };
+
+ template <SQLSMALLINT Type>
+ class object
{
- verify_error(SQLFreeHandle(handler_type, m_handle));
- m_handle=SQL_NULL_HANDLE;
- }
- }
-
- void verify_error(SQLINTEGER code) const
- {
- if (code < 0)
- throw odbc::error(*this, code);
- }
-
-protected:
- SQLHANDLE m_handle;
-};
-
-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(object<SQL_HANDLE_STMT>* stmt, SQLSMALLINT field, std::ios_base::openmode mode)
- {
- if (m_stmt && m_field)
- {
- overflow();
- }
-
- assert(stmt != SQL_NULL_HANDLE);
- m_stmt = stmt;
- m_field = field;
- m_size = INTMAX_MAX;
- init_buffer(mode);
- }
-
-private:
- object<SQL_HANDLE_STMT>* m_stmt;
- SQLSMALLINT m_field;
-
-protected:
- virtual bool read_blob(char* buffer, off_type& count, pos_type position) override
- {
- SQLLEN indicator=0;
- SQLRETURN ret = SQLGetData(m_stmt->handle(), m_field + 1, SQL_C_BINARY, buffer, static_cast<SQLINTEGER>(count), const_cast<SQLLEN*>(&indicator));
- if (ret != SQL_NO_DATA)
- {
- count = (indicator > count) || (indicator == SQL_NO_TOTAL) ?
- count : indicator;
- m_stmt->verify_error(ret);
- return true;
- }
- else return false;
- }
-
- virtual void write_blob(const char* buffer, size_t count) override
- {
- m_stmt->verify_error(SQLPutData(m_stmt->handle(), (SQLPOINTER)buffer, count));
- }
-};
-
-class environment final : public object<SQL_HANDLE_ENV>
-{
-public:
- environment() : object(SQL_NULL_HANDLE)
- {
-#if ODBCVER >= 0x0380
- const SQLPOINTER version = (SQLPOINTER)SQL_OV_ODBC3_80;
-#else
- const SQLPOINTER version = (SQLPOINTER)SQL_OV_ODBC3;
-#endif
- verify_error(SQLSetEnvAttr(m_handle, SQL_ATTR_ODBC_VERSION, version, SQL_IS_INTEGER));
- }
- environment(environment&& src) : object(std::forward<environment>(src)) { }
-
- int32_t version() const
- {
- int32_t ver = 0;
- verify_error(SQLGetEnvAttr(m_handle, SQL_ATTR_ODBC_VERSION, &ver, sizeof(DWORD), NULL));
- return ver;
- }
-};
-
-class base_statement : public object<SQL_HANDLE_STMT>
-{
-public:
- explicit base_statement(base_database& db);
- base_statement(base_statement&& src)
- : object(std::forward<base_statement>(src)), m_params(std::forward<std::vector<param_data>>(src.m_params))
- {
- m_binded_cols=src.m_binded_cols;
- src.m_binded_cols=false;
- m_blob_buffer=src.m_blob_buffer;
- src.m_blob_buffer=NULL;
- }
- ~base_statement()
- {
- if(m_blob_buffer)
- free(m_blob_buffer);
- }
- base_statement& operator=(base_statement&& src)
- {
- if(this!=&src)
- {
- object::operator =(std::forward<base_statement>(src));
- m_params=std::forward<std::vector<param_data>>(src.m_params);
- m_binded_cols=src.m_binded_cols;
- src.m_binded_cols=false;
- m_blob_buffer=src.m_blob_buffer;
- src.m_blob_buffer=NULL;
- }
- return *this;
- }
-
- void bind_param(size_t index, const std::nullptr_t&)
- {
- m_params[index].m_indicator=SQL_NULL_DATA;
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1),
- SQL_PARAM_INPUT, SQL_C_DEFAULT, SQL_DEFAULT, 0, 0, NULL, 0, &m_params[index].m_indicator));
- }
- void bind_param(size_t index, const qtl::null&)
- {
- bind_param(index, nullptr);
- }
- void bind_param(size_t index, const int8_t& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_STINYINT, SQL_TINYINT,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const uint8_t& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_UTINYINT, SQL_TINYINT,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const int16_t& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_SMALLINT,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const uint16_t& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_USHORT, SQL_SMALLINT,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const int32_t& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const uint32_t& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const int64_t& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const uint64_t& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_BIGINT,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const double& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const float& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const bool& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const DATE_STRUCT& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_DATE, SQL_DATE,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const TIME_STRUCT& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_TIME, SQL_TIME,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const TIMESTAMP_STRUCT& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const SQLGUID& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_GUID, SQL_GUID,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const SQL_NUMERIC_STRUCT& v)
- {
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_NUMERIC,
- 0, 0, (SQLPOINTER)&v, 0, NULL));
- }
- void bind_param(size_t index, const char* v, size_t n=SQL_NTS, SQLULEN size=0)
- {
- m_params[index].m_indicator=n;
- if(size==0) size=strlen(v);
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
- size, 0, (SQLPOINTER)v, 0, &m_params[index].m_indicator));
- }
- void bind_param(size_t index, const wchar_t* v, size_t n=SQL_NTS, SQLULEN size=0)
- {
- m_params[index].m_indicator=n;
- if(size==0) size=wcslen(v);
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR,
- size, 0, (SQLPOINTER)v, 0, &m_params[index].m_indicator));
- }
- void bind_param(size_t index, const std::string& v)
- {
- bind_param(index, v.data(), v.size(), v.size());
- }
- void bind_param(size_t index, const std::wstring& v)
- {
- bind_param(index, v.data(), v.size(), v.size());
- }
- void bind_param(size_t index, const const_blob_data& v)
- {
- m_params[index].m_indicator=v.size;
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_BINARY, SQL_BINARY,
- v.size, 0, (SQLPOINTER)v.data, 0, &m_params[index].m_indicator));
- }
- void bind_param(size_t index, std::istream& s)
- {
- if(m_blob_buffer==NULL)
- m_blob_buffer=malloc(blob_buffer_size);
- m_params[index].m_data=m_blob_buffer;
- m_params[index].m_size=blob_buffer_size;
- m_params[index].m_indicator=SQL_LEN_DATA_AT_EXEC(m_params[index].m_size);
- verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY,
- INT_MAX, 0, &m_params[index], 0, &m_params[index].m_indicator));
- m_params[index].m_after_fetch=[this, &s](const param_data& p) {
- SQLLEN readed=SQL_NULL_DATA;
- while(!s.eof() && !s.fail())
+ public:
+ enum
{
- s.read((char*)p.m_data, p.m_size);
- readed=(unsigned long)s.gcount();
- if(readed>0)
+ handler_type = Type
+ };
+ object() : m_handle(SQL_NULL_HANDLE){};
+ object(const object &) = delete;
+ object(object &&src) : m_handle(src.m_handle)
+ {
+ src.m_handle = SQL_NULL_HANDLE;
+ }
+ explicit object(SQLHANDLE parent)
+ {
+ verify_error(SQLAllocHandle(handler_type, parent, &m_handle));
+ }
+ ~object()
+ {
+ close();
+ }
+ object &operator=(const object &) = delete;
+ object &operator=(object &&src)
+ {
+ if (this != &src)
{
- verify_error(SQLPutData(m_handle, p.m_data, readed));
+ close();
+ m_handle = src.m_handle;
+ src.m_handle = NULL;
+ }
+ return *this;
+ }
+ SQLHANDLE handle() const { return m_handle; }
+
+ void close()
+ {
+ if (m_handle)
+ {
+ verify_error(SQLFreeHandle(handler_type, m_handle));
+ m_handle = SQL_NULL_HANDLE;
}
}
- };
- }
- void bind_param(size_t index, const blob_writer& param)
- {
- m_params[index].m_data = nullptr;
- m_params[index].m_size = blob_buffer_size;
- m_params[index].m_indicator = SQL_LEN_DATA_AT_EXEC(m_params[index].m_size);
- verify_error(SQLBindParameter(m_handle, static_cast<SQLSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY,
- INT_MAX, 0, &m_params[index], 0, &m_params[index].m_indicator));
- m_params[index].m_after_fetch = [this, index, ¶m](const param_data& b) {
- blobbuf buf;
- buf.open(this, static_cast<SQLSMALLINT>(index), std::ios::out);
- std::ostream s(&buf);
- param(s);
- };
- }
+ void verify_error(SQLINTEGER code) const
+ {
+ if (code < 0)
+ throw odbc::error(*this, code);
+ }
- void bind_field(size_t index, bool&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_BIT, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, int8_t&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_STINYINT, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, uint8_t&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_UTINYINT, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, int16_t&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_SSHORT, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, uint16_t&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_USHORT, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, int32_t&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_SLONG, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, uint32_t&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_ULONG, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, int64_t&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_SBIGINT, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, uint64_t&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_UBIGINT, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, float&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_FLOAT, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, double&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_DOUBLE, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, DATE_STRUCT&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_TYPE_DATE, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, TIME_STRUCT&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_TYPE_TIME, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, TIMESTAMP_STRUCT&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_TYPE_TIMESTAMP, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, SQLGUID&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_GUID, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, SQL_NUMERIC_STRUCT&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_NUMERIC, &v, 0, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, char* v, size_t n)
- {
- m_params[index].m_data=v;
- m_params[index].m_size=n;
- m_params[index].m_after_fetch=[](const param_data& p) {
- if(p.m_indicator==SQL_NULL_DATA)
- memset(p.m_data, 0, p.m_size*sizeof(char));
- else
- {
- char* text=reinterpret_cast<char*>(p.m_data);
- text[p.m_indicator]='\0';
- }
+ protected:
+ SQLHANDLE m_handle;
};
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_CHAR, v, n, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, wchar_t* v, size_t n)
- {
- m_params[index].m_data=v;
- m_params[index].m_size=n;
- m_params[index].m_after_fetch=[](const param_data& p) {
- if(p.m_indicator==SQL_NULL_DATA)
- memset(p.m_data, 0, p.m_size*sizeof(wchar_t));
- else
- {
- wchar_t* text=reinterpret_cast<wchar_t*>(p.m_data);
- text[p.m_indicator]='\0';
- }
- };
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_WCHAR, v, n, &m_params[index].m_indicator));
- }
- template<typename T>
- void bind_field(size_t index, qtl::bind_string_helper<T>&& v)
- {
- SQLLEN length=0;
- verify_error(SQLColAttribute(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_DESC_LENGTH, NULL, 0, NULL, &length));
- typename qtl::bind_string_helper<T>::char_type* data=v.alloc(length);
- bind_field(index, data, length+1);
- m_params[index].m_after_fetch=[v](const param_data& p) mutable {
- if(p.m_indicator==SQL_NULL_DATA)
- v.clear();
- else
- v.truncate(p.m_indicator);
- };
- }
- template<size_t N>
- void bind_field(size_t index, std::array<char, N>&& value)
- {
- bind_field(index, value.data(), value.size());
- }
- template<size_t N>
- void bind_field(size_t index, std::array<wchar_t, N>&& value)
- {
- bind_field(index, value.data(), value.size());
- }
- void bind_field(size_t index, qtl::blob_data&& v)
- {
- verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_BINARY, v.data, v.size, &m_params[index].m_indicator));
- }
- void bind_field(size_t index, std::ostream&& v)
- {
- if(m_blob_buffer==NULL)
- m_blob_buffer=malloc(blob_buffer_size);
- m_params[index].m_data=m_blob_buffer;
- m_params[index].m_size=blob_buffer_size;
- m_params[index].m_after_fetch=[this, index, &v](const param_data& p) {
- SQLRETURN ret=SQLGetData(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_BINARY, p.m_data, p.m_size, const_cast<SQLLEN*>(&p.m_indicator));
- while(ret!=SQL_NO_DATA)
- {
- size_t n = (p.m_indicator > blob_buffer_size) || (p.m_indicator == SQL_NO_TOTAL) ?
- blob_buffer_size : p.m_indicator;
- verify_error(ret);
- v.write((const char*)p.m_data, n);
- ret=SQLGetData(m_handle, static_cast<SQLUSMALLINT>(index+1), SQL_C_BINARY, p.m_data, p.m_size, const_cast<SQLLEN*>(&p.m_indicator));
- }
- };
- }
- void bind_field(size_t index, blobbuf&& value)
- {
- m_params[index].m_data = nullptr;
- m_params[index].m_size = 0;
- m_params[index].m_after_fetch = [this, index, &value](const param_data& p) {
- value.open(this, static_cast<SQLSMALLINT>(index), std::ios::in);
- };
- }
+ 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(); }
- template<typename Type>
- void bind_field(size_t index, indicator<Type>&& value)
- {
- qtl::bind_field(*this, index, value.data);
- param_data& param=m_params[index];
- auto fetch_fun=param.m_after_fetch;
- param.m_after_fetch=[fetch_fun, &value](const param_data& p) {
- value.is_truncated=false;
- if(p.m_indicator==SQL_NULL_DATA)
+ void open(object<SQL_HANDLE_STMT> *stmt, SQLSMALLINT field, std::ios_base::openmode mode)
{
- value.is_null=true;
- value.length=0;
+ if (m_stmt && m_field)
+ {
+ overflow();
+ }
+
+ assert(stmt != SQL_NULL_HANDLE);
+ m_stmt = stmt;
+ m_field = field;
+ m_size = INTMAX_MAX;
+ init_buffer(mode);
}
- else if(p.m_indicator>=0)
+
+ private:
+ object<SQL_HANDLE_STMT> *m_stmt;
+ SQLSMALLINT m_field;
+
+ protected:
+ virtual bool read_blob(char *buffer, off_type &count, pos_type position) override
{
- value.is_null=false;
- value.length=p.m_indicator;
- if(p.m_size>0 && p.m_indicator>=p.m_size)
- value.is_truncated=true;
+ SQLLEN indicator = 0;
+ SQLRETURN ret = SQLGetData(m_stmt->handle(), m_field + 1, SQL_C_BINARY, buffer, static_cast<SQLINTEGER>(count), const_cast<SQLLEN *>(&indicator));
+ if (ret != SQL_NO_DATA)
+ {
+ count = (indicator > count) || (indicator == SQL_NO_TOTAL) ? count : indicator;
+ m_stmt->verify_error(ret);
+ return true;
+ }
+ else
+ return false;
}
- if(fetch_fun) fetch_fun(p);
+
+ virtual void write_blob(const char *buffer, size_t count) override
+ {
+ m_stmt->verify_error(SQLPutData(m_stmt->handle(), (SQLPOINTER)buffer, count));
+ }
};
- }
+
+ class environment final : public object<SQL_HANDLE_ENV>
+ {
+ public:
+ environment() : object(SQL_NULL_HANDLE)
+ {
+#if ODBCVER >= 0x0380
+ const SQLPOINTER version = (SQLPOINTER)SQL_OV_ODBC3_80;
+#else
+ const SQLPOINTER version = (SQLPOINTER)SQL_OV_ODBC3;
+#endif
+ verify_error(SQLSetEnvAttr(m_handle, SQL_ATTR_ODBC_VERSION, version, SQL_IS_INTEGER));
+ }
+ environment(environment &&src) : object(std::forward<environment>(src)) {}
+
+ int32_t version() const
+ {
+ int32_t ver = 0;
+ verify_error(SQLGetEnvAttr(m_handle, SQL_ATTR_ODBC_VERSION, &ver, sizeof(DWORD), NULL));
+ return ver;
+ }
+ };
+
+ class base_statement : public object<SQL_HANDLE_STMT>
+ {
+ public:
+ explicit base_statement(base_database &db);
+ base_statement(base_statement &&src)
+ : object(std::forward<base_statement>(src)), m_params(std::forward<std::vector<param_data>>(src.m_params))
+ {
+ m_binded_cols = src.m_binded_cols;
+ src.m_binded_cols = false;
+ m_blob_buffer = src.m_blob_buffer;
+ src.m_blob_buffer = NULL;
+ }
+ ~base_statement()
+ {
+ if (m_blob_buffer)
+ free(m_blob_buffer);
+ }
+ base_statement &operator=(base_statement &&src)
+ {
+ if (this != &src)
+ {
+ object::operator=(std::forward<base_statement>(src));
+ m_params = std::forward<std::vector<param_data>>(src.m_params);
+ m_binded_cols = src.m_binded_cols;
+ src.m_binded_cols = false;
+ m_blob_buffer = src.m_blob_buffer;
+ src.m_blob_buffer = NULL;
+ }
+ return *this;
+ }
+
+ void bind_param(size_t index, const std::nullptr_t &)
+ {
+ m_params[index].m_indicator = SQL_NULL_DATA;
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1),
+ SQL_PARAM_INPUT, SQL_C_DEFAULT, SQL_DEFAULT, 0, 0, NULL, 0, &m_params[index].m_indicator));
+ }
+ void bind_param(size_t index, const qtl::null &)
+ {
+ bind_param(index, nullptr);
+ }
+ void bind_param(size_t index, const int8_t &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_STINYINT, SQL_TINYINT,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const uint8_t &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_UTINYINT, SQL_TINYINT,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const int16_t &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_SMALLINT,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const uint16_t &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_USHORT, SQL_SMALLINT,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const int32_t &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const uint32_t &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const int64_t &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const uint64_t &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_BIGINT,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const double &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const float &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const bool &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const DATE_STRUCT &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_DATE, SQL_DATE,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const TIME_STRUCT &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_TIME, SQL_TIME,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const TIMESTAMP_STRUCT &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const SQLGUID &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_GUID, SQL_GUID,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const SQL_NUMERIC_STRUCT &v)
+ {
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_NUMERIC,
+ 0, 0, (SQLPOINTER)&v, 0, NULL));
+ }
+ void bind_param(size_t index, const char *v, size_t n = SQL_NTS, SQLULEN size = 0)
+ {
+ m_params[index].m_indicator = n;
+ if (size == 0)
+ size = strlen(v);
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
+ size, 0, (SQLPOINTER)v, 0, &m_params[index].m_indicator));
+ }
+ void bind_param(size_t index, const wchar_t *v, size_t n = SQL_NTS, SQLULEN size = 0)
+ {
+ m_params[index].m_indicator = n;
+ if (size == 0)
+ size = wcslen(v);
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR,
+ size, 0, (SQLPOINTER)v, 0, &m_params[index].m_indicator));
+ }
+ void bind_param(size_t index, const std::string &v)
+ {
+ bind_param(index, v.data(), v.size(), v.size());
+ }
+ void bind_param(size_t index, const std::wstring &v)
+ {
+ bind_param(index, v.data(), v.size(), v.size());
+ }
+ void bind_param(size_t index, const const_blob_data &v)
+ {
+ m_params[index].m_indicator = v.size;
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_BINARY, SQL_BINARY,
+ v.size, 0, (SQLPOINTER)v.data, 0, &m_params[index].m_indicator));
+ }
+ void bind_param(size_t index, std::istream &s)
+ {
+ if (m_blob_buffer == NULL)
+ m_blob_buffer = malloc(blob_buffer_size);
+ m_params[index].m_data = m_blob_buffer;
+ m_params[index].m_size = blob_buffer_size;
+ m_params[index].m_indicator = SQL_LEN_DATA_AT_EXEC(m_params[index].m_size);
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY,
+ INT_MAX, 0, &m_params[index], 0, &m_params[index].m_indicator));
+ m_params[index].m_after_fetch = [this, &s](const param_data &p)
+ {
+ SQLLEN readed = SQL_NULL_DATA;
+ while (!s.eof() && !s.fail())
+ {
+ s.read((char *)p.m_data, p.m_size);
+ readed = (unsigned long)s.gcount();
+ if (readed > 0)
+ {
+ verify_error(SQLPutData(m_handle, p.m_data, readed));
+ }
+ }
+ };
+ }
+
+ void bind_param(size_t index, const blob_writer ¶m)
+ {
+ m_params[index].m_data = nullptr;
+ m_params[index].m_size = blob_buffer_size;
+ m_params[index].m_indicator = SQL_LEN_DATA_AT_EXEC(m_params[index].m_size);
+ verify_error(SQLBindParameter(m_handle, static_cast<SQLSMALLINT>(index + 1), SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY,
+ INT_MAX, 0, &m_params[index], 0, &m_params[index].m_indicator));
+ m_params[index].m_after_fetch = [this, index, ¶m](const param_data &b)
+ {
+ blobbuf buf;
+ buf.open(this, static_cast<SQLSMALLINT>(index), std::ios::out);
+ std::ostream s(&buf);
+ param(s);
+ };
+ }
+
+ void bind_field(size_t index, bool &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_BIT, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, int8_t &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_STINYINT, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, uint8_t &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_UTINYINT, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, int16_t &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_SSHORT, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, uint16_t &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_USHORT, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, int32_t &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_SLONG, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, uint32_t &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_ULONG, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, int64_t &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_SBIGINT, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, uint64_t &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_UBIGINT, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, float &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_FLOAT, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, double &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_DOUBLE, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, DATE_STRUCT &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_TYPE_DATE, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, TIME_STRUCT &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_TYPE_TIME, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, TIMESTAMP_STRUCT &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_TYPE_TIMESTAMP, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, SQLGUID &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_GUID, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, SQL_NUMERIC_STRUCT &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_NUMERIC, &v, 0, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, char *v, size_t n)
+ {
+ m_params[index].m_data = v;
+ m_params[index].m_size = n;
+ m_params[index].m_after_fetch = [](const param_data &p)
+ {
+ if (p.m_indicator == SQL_NULL_DATA)
+ memset(p.m_data, 0, p.m_size * sizeof(char));
+ else
+ {
+ char *text = reinterpret_cast<char *>(p.m_data);
+ text[p.m_indicator] = '\0';
+ }
+ };
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_CHAR, v, n, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, wchar_t *v, size_t n)
+ {
+ m_params[index].m_data = v;
+ m_params[index].m_size = n;
+ m_params[index].m_after_fetch = [](const param_data &p)
+ {
+ if (p.m_indicator == SQL_NULL_DATA)
+ memset(p.m_data, 0, p.m_size * sizeof(wchar_t));
+ else
+ {
+ wchar_t *text = reinterpret_cast<wchar_t *>(p.m_data);
+ text[p.m_indicator] = '\0';
+ }
+ };
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_WCHAR, v, n, &m_params[index].m_indicator));
+ }
+ template <typename T>
+ void bind_field(size_t index, qtl::bind_string_helper<T> &&v)
+ {
+ SQLLEN length = 0;
+ verify_error(SQLColAttribute(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_DESC_LENGTH, NULL, 0, NULL, &length));
+ typename qtl::bind_string_helper<T>::char_type *data = v.alloc(length);
+ bind_field(index, data, length + 1);
+ m_params[index].m_after_fetch = [v](const param_data &p) mutable
+ {
+ if (p.m_indicator == SQL_NULL_DATA)
+ v.clear();
+ else
+ v.truncate(p.m_indicator);
+ };
+ }
+ template <size_t N>
+ void bind_field(size_t index, std::array<char, N> &&value)
+ {
+ bind_field(index, value.data(), value.size());
+ }
+ template <size_t N>
+ void bind_field(size_t index, std::array<wchar_t, N> &&value)
+ {
+ bind_field(index, value.data(), value.size());
+ }
+ void bind_field(size_t index, qtl::blob_data &&v)
+ {
+ verify_error(SQLBindCol(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_BINARY, v.data, v.size, &m_params[index].m_indicator));
+ }
+ void bind_field(size_t index, std::ostream &&v)
+ {
+ if (m_blob_buffer == NULL)
+ m_blob_buffer = malloc(blob_buffer_size);
+ m_params[index].m_data = m_blob_buffer;
+ m_params[index].m_size = blob_buffer_size;
+ m_params[index].m_after_fetch = [this, index, &v](const param_data &p)
+ {
+ SQLRETURN ret = SQLGetData(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_BINARY, p.m_data, p.m_size, const_cast<SQLLEN *>(&p.m_indicator));
+ while (ret != SQL_NO_DATA)
+ {
+ size_t n = (p.m_indicator > blob_buffer_size) || (p.m_indicator == SQL_NO_TOTAL) ? blob_buffer_size : p.m_indicator;
+ verify_error(ret);
+ v.write((const char *)p.m_data, n);
+ ret = SQLGetData(m_handle, static_cast<SQLUSMALLINT>(index + 1), SQL_C_BINARY, p.m_data, p.m_size, const_cast<SQLLEN *>(&p.m_indicator));
+ }
+ };
+ }
+
+ void bind_field(size_t index, blobbuf &&value)
+ {
+ m_params[index].m_data = nullptr;
+ m_params[index].m_size = 0;
+ m_params[index].m_after_fetch = [this, index, &value](const param_data &p)
+ {
+ value.open(this, static_cast<SQLSMALLINT>(index), std::ios::in);
+ };
+ }
+
+ template <typename Type>
+ void bind_field(size_t index, indicator<Type> &&value)
+ {
+ qtl::bind_field(*this, index, value.data);
+ param_data ¶m = m_params[index];
+ auto fetch_fun = param.m_after_fetch;
+ param.m_after_fetch = [fetch_fun, &value](const param_data &p)
+ {
+ value.is_truncated = false;
+ if (p.m_indicator == SQL_NULL_DATA)
+ {
+ value.is_null = true;
+ value.length = 0;
+ }
+ else if (p.m_indicator >= 0)
+ {
+ value.is_null = false;
+ value.length = p.m_indicator;
+ if (p.m_size > 0 && p.m_indicator >= p.m_size)
+ value.is_truncated = true;
+ }
+ if (fetch_fun)
+ fetch_fun(p);
+ };
+ }
#ifdef _QTL_ENABLE_CPP17
- template<typename Type>
- void bind_field(size_t index, std::optional<Type>&& value)
- {
- qtl::bind_field(*this, index, *value);
- param_data& param = m_params[index];
- auto fetch_fun = param.m_after_fetch;
- param.m_after_fetch = [fetch_fun, &value](const param_data& p) {
- if (fetch_fun) fetch_fun(p);
- if (p.m_indicator == SQL_NULL_DATA)
- value.reset();
- };
- }
+ template <typename Type>
+ void bind_field(size_t index, std::optional<Type> &&value)
+ {
+ qtl::bind_field(*this, index, *value);
+ param_data ¶m = m_params[index];
+ auto fetch_fun = param.m_after_fetch;
+ param.m_after_fetch = [fetch_fun, &value](const param_data &p)
+ {
+ if (fetch_fun)
+ fetch_fun(p);
+ if (p.m_indicator == SQL_NULL_DATA)
+ value.reset();
+ };
+ }
- void bind_field(size_t index, std::any&& value)
- {
- SQLLEN type = 0, isUnsigned=SQL_FALSE;
- verify_error(SQLColAttribute(m_handle, index + 1, SQL_DESC_TYPE, NULL, 0, NULL, &type));
- verify_error(SQLColAttribute(m_handle, index + 1, SQL_DESC_UNSIGNED, NULL, 0, NULL, &isUnsigned));
- switch (type)
- {
- case SQL_BIT:
- value.emplace<bool>();
- bind_field(index, std::forward<bool>(std::any_cast<bool&>(value)));
- break;
- case SQL_TINYINT:
- if (isUnsigned)
+ void bind_field(size_t index, std::any &&value)
{
- value.emplace<uint8_t>();
- bind_field(index, std::forward<uint8_t>(std::any_cast<uint8_t&>(value)));
+ SQLLEN type = 0, isUnsigned = SQL_FALSE;
+ verify_error(SQLColAttribute(m_handle, index + 1, SQL_DESC_TYPE, NULL, 0, NULL, &type));
+ verify_error(SQLColAttribute(m_handle, index + 1, SQL_DESC_UNSIGNED, NULL, 0, NULL, &isUnsigned));
+ switch (type)
+ {
+ case SQL_BIT:
+ value.emplace<bool>();
+ bind_field(index, std::forward<bool>(std::any_cast<bool &>(value)));
+ break;
+ case SQL_TINYINT:
+ if (isUnsigned)
+ {
+ value.emplace<uint8_t>();
+ bind_field(index, std::forward<uint8_t>(std::any_cast<uint8_t &>(value)));
+ }
+ else
+ {
+ value.emplace<int8_t>();
+ bind_field(index, std::forward<int8_t>(std::any_cast<int8_t &>(value)));
+ }
+ break;
+ case SQL_SMALLINT:
+ if (isUnsigned)
+ {
+ value.emplace<uint16_t>();
+ bind_field(index, std::forward<uint16_t>(std::any_cast<uint16_t &>(value)));
+ }
+ else
+ {
+ value.emplace<int16_t>();
+ bind_field(index, std::forward<int16_t>(std::any_cast<int16_t &>(value)));
+ }
+ break;
+ case SQL_INTEGER:
+ if (isUnsigned)
+ {
+ value.emplace<uint32_t>();
+ bind_field(index, std::forward<uint32_t>(std::any_cast<uint32_t &>(value)));
+ }
+ else
+ {
+ value.emplace<int32_t>();
+ bind_field(index, std::forward<int32_t>(std::any_cast<int32_t &>(value)));
+ }
+ break;
+ case SQL_BIGINT:
+ if (isUnsigned)
+ {
+ value.emplace<uint64_t>();
+ bind_field(index, std::forward<uint64_t>(std::any_cast<uint64_t &>(value)));
+ }
+ else
+ {
+ value.emplace<int64_t>();
+ bind_field(index, std::forward<int64_t>(std::any_cast<int64_t &>(value)));
+ }
+ break;
+ case SQL_FLOAT:
+ value.emplace<float>();
+ bind_field(index, std::forward<float>(std::any_cast<float &>(value)));
+ break;
+ case SQL_DOUBLE:
+ value.emplace<double>();
+ bind_field(index, std::forward<double>(std::any_cast<double &>(value)));
+ break;
+ case SQL_NUMERIC:
+ value.emplace<SQL_NUMERIC_STRUCT>();
+ bind_field(index, std::forward<SQL_NUMERIC_STRUCT>(std::any_cast<SQL_NUMERIC_STRUCT &>(value)));
+ break;
+ case SQL_TIME:
+ value.emplace<SQL_TIME_STRUCT>();
+ bind_field(index, std::forward<SQL_TIME_STRUCT>(std::any_cast<SQL_TIME_STRUCT &>(value)));
+ break;
+ case SQL_DATE:
+ value.emplace<SQL_DATE_STRUCT>();
+ bind_field(index, std::forward<SQL_DATE_STRUCT>(std::any_cast<SQL_DATE_STRUCT &>(value)));
+ break;
+ case SQL_TIMESTAMP:
+ value.emplace<SQL_TIMESTAMP_STRUCT>();
+ bind_field(index, std::forward<SQL_TIMESTAMP_STRUCT>(std::any_cast<SQL_TIMESTAMP_STRUCT &>(value)));
+ break;
+ case SQL_INTERVAL_MONTH:
+ case SQL_INTERVAL_YEAR:
+ case SQL_INTERVAL_YEAR_TO_MONTH:
+ case SQL_INTERVAL_DAY:
+ case SQL_INTERVAL_HOUR:
+ case SQL_INTERVAL_MINUTE:
+ case SQL_INTERVAL_SECOND:
+ case SQL_INTERVAL_DAY_TO_HOUR:
+ case SQL_INTERVAL_DAY_TO_MINUTE:
+ case SQL_INTERVAL_DAY_TO_SECOND:
+ case SQL_INTERVAL_HOUR_TO_MINUTE:
+ case SQL_INTERVAL_HOUR_TO_SECOND:
+ case SQL_INTERVAL_MINUTE_TO_SECOND:
+ value.emplace<SQL_INTERVAL_STRUCT>();
+ bind_field(index, std::forward<SQL_INTERVAL_STRUCT>(std::any_cast<SQL_INTERVAL_STRUCT &>(value)));
+ break;
+ case SQL_CHAR:
+ value.emplace<std::string>();
+ bind_field(index, qtl::bind_string(std::any_cast<std::string &>(value)));
+ break;
+ case SQL_GUID:
+ value.emplace<SQLGUID>();
+ bind_field(index, std::forward<SQLGUID>(std::any_cast<SQLGUID &>(value)));
+ break;
+ case SQL_BINARY:
+ value.emplace<blobbuf>();
+ bind_field(index, std::forward<blobbuf>(std::any_cast<blobbuf &>(value)));
+ break;
+ default:
+ throw odbc::error(*this, SQL_ERROR);
+ }
+ param_data ¶m = m_params[index];
+ auto fetch_fun = param.m_after_fetch;
+ param.m_after_fetch = [fetch_fun, &value](const param_data &p)
+ {
+ if (fetch_fun)
+ fetch_fun(p);
+ if (p.m_indicator == SQL_NULL_DATA)
+ value.reset();
+ };
}
- else
- {
- value.emplace<int8_t>();
- bind_field(index, std::forward<int8_t>(std::any_cast<int8_t&>(value)));
- }
- break;
- case SQL_SMALLINT:
- if (isUnsigned)
- {
- value.emplace<uint16_t>();
- bind_field(index, std::forward<uint16_t>(std::any_cast<uint16_t&>(value)));
- }
- else
- {
- value.emplace<int16_t>();
- bind_field(index, std::forward<int16_t>(std::any_cast<int16_t&>(value)));
- }
- break;
- case SQL_INTEGER:
- if (isUnsigned)
- {
- value.emplace<uint32_t>();
- bind_field(index, std::forward<uint32_t>(std::any_cast<uint32_t&>(value)));
- }
- else
- {
- value.emplace<int32_t>();
- bind_field(index, std::forward<int32_t>(std::any_cast<int32_t&>(value)));
- }
- break;
- case SQL_BIGINT:
- if (isUnsigned)
- {
- value.emplace<uint64_t>();
- bind_field(index, std::forward<uint64_t>(std::any_cast<uint64_t&>(value)));
- }
- else
- {
- value.emplace<int64_t>();
- bind_field(index, std::forward<int64_t>(std::any_cast<int64_t&>(value)));
- }
- break;
- case SQL_FLOAT:
- value.emplace<float>();
- bind_field(index, std::forward<float>(std::any_cast<float&>(value)));
- break;
- case SQL_DOUBLE:
- value.emplace<double>();
- bind_field(index, std::forward<double>(std::any_cast<double&>(value)));
- break;
- case SQL_NUMERIC:
- value.emplace<SQL_NUMERIC_STRUCT>();
- bind_field(index, std::forward<SQL_NUMERIC_STRUCT>(std::any_cast<SQL_NUMERIC_STRUCT&>(value)));
- break;
- case SQL_TIME:
- value.emplace<SQL_TIME_STRUCT>();
- bind_field(index, std::forward<SQL_TIME_STRUCT>(std::any_cast<SQL_TIME_STRUCT&>(value)));
- break;
- case SQL_DATE:
- value.emplace<SQL_DATE_STRUCT>();
- bind_field(index, std::forward<SQL_DATE_STRUCT>(std::any_cast<SQL_DATE_STRUCT&>(value)));
- break;
- case SQL_TIMESTAMP:
- value.emplace<SQL_TIMESTAMP_STRUCT>();
- bind_field(index, std::forward<SQL_TIMESTAMP_STRUCT>(std::any_cast<SQL_TIMESTAMP_STRUCT&>(value)));
- break;
- case SQL_INTERVAL_MONTH:
- case SQL_INTERVAL_YEAR:
- case SQL_INTERVAL_YEAR_TO_MONTH:
- case SQL_INTERVAL_DAY:
- case SQL_INTERVAL_HOUR:
- case SQL_INTERVAL_MINUTE:
- case SQL_INTERVAL_SECOND:
- case SQL_INTERVAL_DAY_TO_HOUR:
- case SQL_INTERVAL_DAY_TO_MINUTE:
- case SQL_INTERVAL_DAY_TO_SECOND:
- case SQL_INTERVAL_HOUR_TO_MINUTE:
- case SQL_INTERVAL_HOUR_TO_SECOND:
- case SQL_INTERVAL_MINUTE_TO_SECOND:
- value.emplace<SQL_INTERVAL_STRUCT>();
- bind_field(index, std::forward<SQL_INTERVAL_STRUCT>(std::any_cast<SQL_INTERVAL_STRUCT&>(value)));
- break;
- case SQL_CHAR:
- value.emplace<std::string>();
- bind_field(index, qtl::bind_string(std::any_cast<std::string&>(value)));
- break;
- case SQL_GUID:
- value.emplace<SQLGUID>();
- bind_field(index, std::forward<SQLGUID>(std::any_cast<SQLGUID&>(value)));
- break;
- case SQL_BINARY:
- value.emplace<blobbuf>();
- bind_field(index, std::forward<blobbuf>(std::any_cast<blobbuf&>(value)));
- break;
- default:
- throw odbc::error(*this, SQL_ERROR);
- }
- param_data& param = m_params[index];
- auto fetch_fun = param.m_after_fetch;
- param.m_after_fetch = [fetch_fun, &value](const param_data& p) {
- if (fetch_fun) fetch_fun(p);
- if (p.m_indicator == SQL_NULL_DATA)
- value.reset();
- };
- }
#endif // C++17
- SQLLEN affetced_rows()
- {
- SQLLEN count=0;
- verify_error(SQLRowCount(m_handle, &count));
- return count;
- }
-
- size_t find_field(const char* name) const
- {
- SQLSMALLINT count=0;
- verify_error(SQLNumResultCols(m_handle, &count));
- for(SQLSMALLINT i=0; i!=count; i++)
- {
- SQLCHAR field_name[256]={0};
- SQLSMALLINT name_length=0;
- SQLSMALLINT data_type;
- SQLULEN column_size;
- SQLSMALLINT digits;
- SQLSMALLINT nullable;
- verify_error(SQLDescribeColA(m_handle, i, field_name, sizeof(field_name), &name_length,
- &data_type, &column_size, &digits, &nullable));
- if(strncmp((char*)field_name, name, name_length)==0)
- return i;
- }
- return -1;
- }
-
- void reset()
- {
- verify_error(SQLFreeStmt(m_handle, SQL_RESET_PARAMS));
- }
-
- /*
- ODBC do not support this function, but you can use query to instead it:
- For MS SQL Server: SELECT @@IDENTITY;
- For MySQL: SELECT LAST_INSERT_ID();
- For SQLite: SELECT last_insert_rowid();
- */
- /*uint64_t insert_id()
- {
- assert(false);
- return 0;
- }*/
-
-protected:
- struct param_data
- {
- SQLPOINTER m_data;
- SQLLEN m_size;
- SQLLEN m_indicator;
- std::function<void(const param_data&)> m_after_fetch;
-
- param_data() : m_data(NULL), m_size(0), m_indicator(0) { }
- };
- SQLPOINTER m_blob_buffer;
- std::vector<param_data> m_params;
- bool m_binded_cols;
-};
-
-class statement : public base_statement
-{
-public:
- statement() = default;
- explicit statement(base_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, size_t text_length = SQL_NTS)
- {
- reset();
- verify_error(SQLPrepareA(m_handle, (SQLCHAR*)query_text, text_length));
- }
- void open(const std::string& query_text)
- {
- open(query_text.data(), query_text.size());
- }
-
-
- template<typename Types>
- void execute(const Types& params)
- {
- SQLSMALLINT count = 0;
- verify_error(SQLNumParams(m_handle, &count));
- if (count > 0)
- {
- m_params.resize(count);
- qtl::bind_params(*this, params);
- }
-
- SQLRETURN ret = SQLExecute(m_handle);
- verify_error(ret);
- if (ret == SQL_NEED_DATA)
- {
- SQLPOINTER token;
- size_t i = 0;
- ret = SQLParamData(m_handle, &token);
- verify_error(ret);
- while (ret == SQL_NEED_DATA)
+ SQLLEN affetced_rows()
{
- while (i != count)
+ SQLLEN count = 0;
+ verify_error(SQLRowCount(m_handle, &count));
+ return count;
+ }
+
+ size_t find_field(const char *name) const
+ {
+ SQLSMALLINT count = 0;
+ verify_error(SQLNumResultCols(m_handle, &count));
+ for (SQLSMALLINT i = 0; i != count; i++)
{
- if (&m_params[i] == token)
- {
- if (m_params[i].m_after_fetch)
- m_params[i].m_after_fetch(m_params[i]);
- break;
- }
- ++i;
+ SQLCHAR field_name[256] = {0};
+ SQLSMALLINT name_length = 0;
+ SQLSMALLINT data_type;
+ SQLULEN column_size;
+ SQLSMALLINT digits;
+ SQLSMALLINT nullable;
+ verify_error(SQLDescribeColA(m_handle, i, field_name, sizeof(field_name), &name_length,
+ &data_type, &column_size, &digits, &nullable));
+ if (strncmp((char *)field_name, name, name_length) == 0)
+ return i;
}
- ret = SQLParamData(m_handle, &token);
- verify_error(ret);
+ return -1;
}
- }
- }
- template<typename Types>
- bool fetch(Types&& values)
- {
- if (!m_binded_cols)
- {
- SQLSMALLINT count = 0;
- verify_error(SQLNumResultCols(m_handle, &count));
- if (count > 0)
+ void reset()
{
- m_params.resize(count);
- qtl::bind_record(*this, std::forward<Types>(values));
+ verify_error(SQLFreeStmt(m_handle, SQL_RESET_PARAMS));
}
- m_binded_cols = true;
- }
- return fetch();
- }
- bool fetch()
- {
- SQLRETURN ret = SQLFetch(m_handle);
- if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
- {
- for (const param_data& data : m_params)
+ /*
+ ODBC do not support this function, but you can use query to instead it:
+ For MS SQL Server: SELECT @@IDENTITY;
+ For MySQL: SELECT LAST_INSERT_ID();
+ For SQLite: SELECT last_insert_rowid();
+ */
+ /*uint64_t insert_id()
{
- if (data.m_after_fetch)
- data.m_after_fetch(data);
+ assert(false);
+ return 0;
+ }*/
+
+ protected:
+ struct param_data
+ {
+ SQLPOINTER m_data;
+ SQLLEN m_size;
+ SQLLEN m_indicator;
+ std::function<void(const param_data &)> m_after_fetch;
+
+ param_data() : m_data(NULL), m_size(0), m_indicator(0) {}
+ };
+ SQLPOINTER m_blob_buffer;
+ std::vector<param_data> m_params;
+ bool m_binded_cols;
+ };
+
+ class statement : public base_statement
+ {
+ public:
+ statement() = default;
+ explicit statement(base_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;
}
- return true;
- }
- verify_error(ret);
- return false;
- }
+ ~statement()
+ {
+ close();
+ }
- bool next_result()
- {
- SQLRETURN ret;
- SQLSMALLINT count = 0;
- m_binded_cols = false;
- do
- {
- ret = SQLMoreResults(m_handle);
- if (ret == SQL_ERROR || ret == SQL_INVALID_HANDLE)
+ void open(const char *query_text, size_t text_length = SQL_NTS)
+ {
+ reset();
+ verify_error(SQLPrepareA(m_handle, (SQLCHAR *)query_text, text_length));
+ }
+ void open(const std::string &query_text)
+ {
+ open(query_text.data(), query_text.size());
+ }
+
+ template <typename Types>
+ void execute(const Types ¶ms)
+ {
+ SQLSMALLINT count = 0;
+ verify_error(SQLNumParams(m_handle, &count));
+ if (count > 0)
+ {
+ m_params.resize(count);
+ qtl::bind_params(*this, params);
+ }
+
+ SQLRETURN ret = SQLExecute(m_handle);
verify_error(ret);
- verify_error(SQLNumResultCols(m_handle, &count));
- } while (count == 0);
- return ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO;
- }
-};
+ if (ret == SQL_NEED_DATA)
+ {
+ SQLPOINTER token;
+ size_t i = 0;
+ ret = SQLParamData(m_handle, &token);
+ verify_error(ret);
+ while (ret == SQL_NEED_DATA)
+ {
+ while (i != count)
+ {
+ if (&m_params[i] == token)
+ {
+ if (m_params[i].m_after_fetch)
+ m_params[i].m_after_fetch(m_params[i]);
+ break;
+ }
+ ++i;
+ }
+ ret = SQLParamData(m_handle, &token);
+ verify_error(ret);
+ }
+ }
+ }
-struct connection_parameter
-{
- std::string m_name;
- std::string m_prompt;
- std::string m_value;
- std::vector<std::string> m_value_list;
- bool m_optinal;
- bool m_assigned;
+ template <typename Types>
+ bool fetch(Types &&values)
+ {
+ if (!m_binded_cols)
+ {
+ SQLSMALLINT count = 0;
+ verify_error(SQLNumResultCols(m_handle, &count));
+ if (count > 0)
+ {
+ m_params.resize(count);
+ qtl::bind_record(*this, std::forward<Types>(values));
+ }
+ m_binded_cols = true;
+ }
+ return fetch();
+ }
- connection_parameter() : m_optinal(false), m_assigned(false) { }
- void reset()
- {
- m_name.clear();
- m_prompt.clear();
- m_value.clear();
- m_value_list.clear();
- m_optinal=false;
- m_assigned=false;
- }
-};
-typedef std::vector<connection_parameter> connection_parameters;
+ bool fetch()
+ {
+ SQLRETURN ret = SQLFetch(m_handle);
+ if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
+ {
+ for (const param_data &data : m_params)
+ {
+ if (data.m_after_fetch)
+ data.m_after_fetch(data);
+ }
+ return true;
+ }
+ verify_error(ret);
+ return false;
+ }
-class base_database : public object<SQL_HANDLE_DBC>
-{
-public:
- typedef odbc::error exception_type;
+ bool next_result()
+ {
+ SQLRETURN ret;
+ SQLSMALLINT count = 0;
+ m_binded_cols = false;
+ do
+ {
+ ret = SQLMoreResults(m_handle);
+ if (ret == SQL_ERROR || ret == SQL_INVALID_HANDLE)
+ verify_error(ret);
+ verify_error(SQLNumResultCols(m_handle, &count));
+ } while (count == 0);
+ return ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO;
+ }
+ };
- explicit base_database(environment& env) : object(env.handle()), m_opened(false)
- {
- }
- base_database(const base_database&) = delete;
- base_database(base_database&& src)
- : object(std::forward<base_database>(src)), m_connection(std::forward<std::string>(src.m_connection))
- {
- m_opened=src.m_opened;
- src.m_opened=false;
- }
- ~base_database()
- {
- close();
- }
- base_database& operator=(base_database&& src)
- {
- if(this!=&src)
+ struct connection_parameter
{
- object::operator =(std::forward<base_database>(src));
- m_opened=src.m_opened;
- src.m_opened=false;
- m_connection=std::forward<std::string>(src.m_connection);
- }
- return *this;
- }
+ std::string m_name;
+ std::string m_prompt;
+ std::string m_value;
+ std::vector<std::string> m_value_list;
+ bool m_optinal;
+ bool m_assigned;
- void close()
- {
- if(m_opened)
+ connection_parameter() : m_optinal(false), m_assigned(false) {}
+ void reset()
+ {
+ m_name.clear();
+ m_prompt.clear();
+ m_value.clear();
+ m_value_list.clear();
+ m_optinal = false;
+ m_assigned = false;
+ }
+ };
+ typedef std::vector<connection_parameter> connection_parameters;
+
+ class base_database : public object<SQL_HANDLE_DBC>
{
- verify_error(SQLDisconnect(m_handle));
- m_opened=false;
- }
- }
+ public:
+ typedef odbc::error exception_type;
- void set_attribute(SQLINTEGER attr, SQLPOINTER value)
- {
- verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_IS_POINTER));
- }
- void set_attribute(SQLINTEGER attr, SQLINTEGER value)
- {
- verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_IS_INTEGER));
- }
- void set_attribute(SQLINTEGER attr, SQLUINTEGER value)
- {
- verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_IS_UINTEGER));
- }
- void set_attribute(SQLINTEGER attr, SQLSMALLINT value)
- {
- verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_IS_SMALLINT));
- }
- void set_attribute(SQLINTEGER attr, SQLUSMALLINT value)
- {
- verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_IS_USMALLINT));
- }
- void set_attribute(SQLINTEGER attr, const char* value)
- {
- verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_NTS));
- }
- void set_attribute(SQLINTEGER attr, const std::string& value)
- {
- verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value.data(), value.size()));
- }
- void set_attribute(SQLINTEGER attr, const void* value, SQLINTEGER length)
- {
- verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_LEN_BINARY_ATTR(length)));
- }
- void get_attribute(SQLINTEGER attr, SQLPOINTER& value) const
- {
- verify_error(SQLGetConnectAttrA(m_handle, attr, &value, SQL_IS_POINTER, 0));
- }
- void get_attribute(SQLINTEGER attr, SQLINTEGER& value) const
- {
- value = 0;
- verify_error(SQLGetConnectAttrA(m_handle, attr, &value, SQL_IS_INTEGER, 0));
- }
- void get_attribute(SQLINTEGER attr, SQLUINTEGER& value) const
- {
- value = 0;
- verify_error(SQLGetConnectAttrA(m_handle, attr, &value, SQL_IS_UINTEGER, 0));
- }
- void get_attribute(SQLINTEGER attr, SQLSMALLINT& value) const
- {
- value = 0;
- verify_error(SQLGetConnectAttrA(m_handle, attr, &value, SQL_IS_SMALLINT, 0));
- }
- void get_attribute(SQLINTEGER attr, SQLUSMALLINT& value) const
- {
- value = 0;
- verify_error(SQLGetConnectAttrA(m_handle, attr, &value, SQL_IS_USMALLINT, 0));
- }
- void get_attribute(SQLINTEGER attr, void* buffer, SQLINTEGER length) const
- {
- verify_error(SQLGetConnectAttrA(m_handle, attr, buffer, SQL_LEN_BINARY_ATTR(length), 0));
- }
- void get_attribute(SQLINTEGER attr, char* buffer, size_t length) const
- {
- verify_error(SQLGetConnectAttrA(m_handle, attr, buffer, length, 0));
- }
- void get_attribute(SQLINTEGER attr, std::string& value) const
- {
- SQLINTEGER length = 0;
- verify_error(SQLGetConnectAttrA(m_handle, attr, NULL, 0, &length));
- value.resize(length);
- if(length>0)
- verify_error(SQLGetConnectAttrA(m_handle, attr, (SQLPOINTER)value.data(), length, 0));
- }
- void get_info(SQLSMALLINT info, std::string& value, SQLSMALLINT size=SQL_MAX_OPTION_STRING_LENGTH) const
- {
- value.resize(size);
- verify_error(SQLGetInfo(m_handle, info, (SQLPOINTER)value.data(), size, &size));
- value.resize(size);
- }
+ explicit base_database(environment &env) : object(env.handle()), m_opened(false)
+ {
+ }
+ base_database(const base_database &) = delete;
+ base_database(base_database &&src)
+ : object(std::forward<base_database>(src)), m_connection(std::forward<std::string>(src.m_connection))
+ {
+ m_opened = src.m_opened;
+ src.m_opened = false;
+ }
+ ~base_database()
+ {
+ close();
+ }
+ base_database &operator=(base_database &&src)
+ {
+ if (this != &src)
+ {
+ object::operator=(std::forward<base_database>(src));
+ m_opened = src.m_opened;
+ src.m_opened = false;
+ m_connection = std::forward<std::string>(src.m_connection);
+ }
+ return *this;
+ }
- std::string dbms_name() const
- {
- std::string name;
- get_info(SQL_DBMS_NAME, name);
- return name;
- }
- std::string server_name() const
- {
- std::string name;
- get_info(SQL_SERVER_NAME, name);
- return name;
- }
- std::string user_name() const
- {
- std::string name;
- get_info(SQL_USER_NAME, name);
- return name;
- }
- std::string db_name() const
- {
- std::string name;
- get_info(SQL_DATABASE_NAME, name);
- return name;
- }
- const std::string& connection_text() const
- {
- return m_connection;
- }
+ void close()
+ {
+ if (m_opened)
+ {
+ verify_error(SQLDisconnect(m_handle));
+ m_opened = false;
+ }
+ }
-protected:
- bool m_opened;
- std::string m_connection;
+ void set_attribute(SQLINTEGER attr, SQLPOINTER value)
+ {
+ verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_IS_POINTER));
+ }
+ void set_attribute(SQLINTEGER attr, SQLINTEGER value)
+ {
+ verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_IS_INTEGER));
+ }
+ void set_attribute(SQLINTEGER attr, SQLUINTEGER value)
+ {
+ verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_IS_UINTEGER));
+ }
+ void set_attribute(SQLINTEGER attr, SQLSMALLINT value)
+ {
+ verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_IS_SMALLINT));
+ }
+ void set_attribute(SQLINTEGER attr, SQLUSMALLINT value)
+ {
+ verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_IS_USMALLINT));
+ }
+ void set_attribute(SQLINTEGER attr, const char *value)
+ {
+ verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_NTS));
+ }
+ void set_attribute(SQLINTEGER attr, const std::string &value)
+ {
+ verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value.data(), value.size()));
+ }
+ void set_attribute(SQLINTEGER attr, const void *value, SQLINTEGER length)
+ {
+ verify_error(SQLSetConnectAttrA(m_handle, attr, (SQLPOINTER)value, SQL_LEN_BINARY_ATTR(length)));
+ }
+ void get_attribute(SQLINTEGER attr, SQLPOINTER &value) const
+ {
+ verify_error(SQLGetConnectAttrA(m_handle, attr, &value, SQL_IS_POINTER, 0));
+ }
+ void get_attribute(SQLINTEGER attr, SQLINTEGER &value) const
+ {
+ value = 0;
+ verify_error(SQLGetConnectAttrA(m_handle, attr, &value, SQL_IS_INTEGER, 0));
+ }
+ void get_attribute(SQLINTEGER attr, SQLUINTEGER &value) const
+ {
+ value = 0;
+ verify_error(SQLGetConnectAttrA(m_handle, attr, &value, SQL_IS_UINTEGER, 0));
+ }
+ void get_attribute(SQLINTEGER attr, SQLSMALLINT &value) const
+ {
+ value = 0;
+ verify_error(SQLGetConnectAttrA(m_handle, attr, &value, SQL_IS_SMALLINT, 0));
+ }
+ void get_attribute(SQLINTEGER attr, SQLUSMALLINT &value) const
+ {
+ value = 0;
+ verify_error(SQLGetConnectAttrA(m_handle, attr, &value, SQL_IS_USMALLINT, 0));
+ }
+ void get_attribute(SQLINTEGER attr, void *buffer, SQLINTEGER length) const
+ {
+ verify_error(SQLGetConnectAttrA(m_handle, attr, buffer, SQL_LEN_BINARY_ATTR(length), 0));
+ }
+ void get_attribute(SQLINTEGER attr, char *buffer, size_t length) const
+ {
+ verify_error(SQLGetConnectAttrA(m_handle, attr, buffer, length, 0));
+ }
+ void get_attribute(SQLINTEGER attr, std::string &value) const
+ {
+ SQLINTEGER length = 0;
+ verify_error(SQLGetConnectAttrA(m_handle, attr, NULL, 0, &length));
+ value.resize(length);
+ if (length > 0)
+ verify_error(SQLGetConnectAttrA(m_handle, attr, (SQLPOINTER)value.data(), length, 0));
+ }
+ void get_info(SQLSMALLINT info, std::string &value, SQLSMALLINT size = SQL_MAX_OPTION_STRING_LENGTH) const
+ {
+ value.resize(size);
+ verify_error(SQLGetInfo(m_handle, info, (SQLPOINTER)value.data(), size, &size));
+ value.resize(size);
+ }
- void parse_browse_string(const char* output_text, size_t text_length, connection_parameters& parameters);
- std::string create_connection_text(const connection_parameters& parameters);
-};
+ std::string dbms_name() const
+ {
+ std::string name;
+ get_info(SQL_DBMS_NAME, name);
+ return name;
+ }
+ std::string server_name() const
+ {
+ std::string name;
+ get_info(SQL_SERVER_NAME, name);
+ return name;
+ }
+ std::string user_name() const
+ {
+ std::string name;
+ get_info(SQL_USER_NAME, name);
+ return name;
+ }
+ std::string db_name() const
+ {
+ std::string name;
+ get_info(SQL_DATABASE_NAME, name);
+ return name;
+ }
+ const std::string &connection_text() const
+ {
+ return m_connection;
+ }
-class database : public base_database, public qtl::base_database<database, statement>
-{
-public:
- database() = default;
- explicit database(environment& env) : odbc::base_database(env)
- {
- }
- database(database&& src) : odbc::base_database(std::move(src))
- {
- }
+ protected:
+ bool m_opened;
+ std::string m_connection;
- void open(const char* server_name, size_t server_name_length,
- const char* user_name, size_t user_name_length, const char* password, size_t password_length)
- {
- if (m_opened) close();
- verify_error(SQLConnectA(m_handle, (SQLCHAR*)server_name, static_cast<SQLSMALLINT>(server_name_length),
- (SQLCHAR*)user_name, static_cast<SQLSMALLINT>(user_name_length), (SQLCHAR*)password, static_cast<SQLSMALLINT>(password_length)));
- m_opened = true;
- }
- void open(const char* server_name, const char* user_name, const char* password)
- {
- verify_error(SQLConnectA(m_handle, (SQLCHAR*)server_name, SQL_NTS, (SQLCHAR*)user_name, SQL_NTS, (SQLCHAR*)password, SQL_NTS));
- }
- void open(const std::string& server_name, const std::string& user_name, const std::string& password)
- {
- open(server_name.data(), server_name.size(), user_name.data(), user_name.size(), password.data(), password.size());
- }
- void open(const char* input_text, size_t text_length = SQL_NTS, SQLSMALLINT driver_completion = SQL_DRIVER_NOPROMPT, SQLHWND hwnd = NULL)
- {
- m_connection.resize(512);
- SQLSMALLINT out_len=0;
- if (m_opened) close();
- verify_error(SQLDriverConnectA(m_handle, hwnd, (SQLCHAR*)input_text, (SQLSMALLINT)text_length,
- (SQLCHAR*)m_connection.data(), (SQLSMALLINT)m_connection.size(), &out_len, driver_completion));
- m_connection.resize(out_len);
- m_opened = true;
- }
- void open(const std::string& input_text, SQLSMALLINT driver_completion = SQL_DRIVER_NOPROMPT, SQLHWND hwnd = NULL)
- {
- open(input_text.data(), input_text.size(), driver_completion, hwnd);
- }
- void open(SQLHWND hwnd, SQLSMALLINT driver_completion = SQL_DRIVER_COMPLETE)
- {
- open("", SQL_NTS, driver_completion, hwnd);
- }
- // InputPred like:
- // bool input_parameters(connection_parameters& parameters);
- template<typename InputPred>
- void open(const char* connection_text, size_t text_length, InputPred&& pred)
- {
- SQLSMALLINT length = 0;
- SQLRETURN ret = SQL_SUCCESS;
- std::string input_text;
- if (m_opened) close();
- if (text_length == SQL_NTS)
- input_text = connection_text;
- else
- input_text.assign(connection_text, text_length);
- m_connection.resize(1024);
- while ((ret = SQLBrowseConnectA(m_handle, (SQLCHAR*)input_text.data(), SQL_NTS,
- (SQLCHAR*)m_connection.data(), m_connection.size(), &length)) == SQL_NEED_DATA)
+ void parse_browse_string(const char *output_text, size_t text_length, connection_parameters ¶meters);
+ std::string create_connection_text(const connection_parameters ¶meters);
+ };
+
+ class database : public base_database, public qtl::base_database<database, statement>
{
- connection_parameters parameters;
- parse_browse_string(m_connection.data(), length, parameters);
- if (!pred(parameters))
- throw error(SQL_NEED_DATA, "User cancel operation.");
- input_text = create_connection_text(parameters);
- }
- if (ret == SQL_ERROR || ret == SQL_SUCCESS_WITH_INFO)
- verify_error(ret);
- m_opened = true;
- }
- template<typename InputPred>
- void open(const char* connection_text, InputPred&& pred)
- {
- open(connection_text, SQL_NTS, std::forward<InputPred>(pred));
- }
- template<typename InputPred>
- void open(const std::string& connection_text, InputPred&& pred)
- {
- open(connection_text.data(), connection_text.size(), std::forward<InputPred>(pred));
- }
+ public:
+ database() = default;
+ explicit database(environment &env) : odbc::base_database(env)
+ {
+ }
+ database(database &&src) : odbc::base_database(std::move(src))
+ {
+ }
- 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 open(const char *server_name, size_t server_name_length,
+ const char *user_name, size_t user_name_length, const char *password, size_t password_length)
+ {
+ if (m_opened)
+ close();
+ verify_error(SQLConnectA(m_handle, (SQLCHAR *)server_name, static_cast<SQLSMALLINT>(server_name_length),
+ (SQLCHAR *)user_name, static_cast<SQLSMALLINT>(user_name_length), (SQLCHAR *)password, static_cast<SQLSMALLINT>(password_length)));
+ m_opened = true;
+ }
+ void open(const char *server_name, const char *user_name, const char *password)
+ {
+ verify_error(SQLConnectA(m_handle, (SQLCHAR *)server_name, SQL_NTS, (SQLCHAR *)user_name, SQL_NTS, (SQLCHAR *)password, SQL_NTS));
+ }
+ void open(const std::string &server_name, const std::string &user_name, const std::string &password)
+ {
+ open(server_name.data(), server_name.size(), user_name.data(), user_name.size(), password.data(), password.size());
+ }
+ void open(const char *input_text, size_t text_length = SQL_NTS, SQLSMALLINT driver_completion = SQL_DRIVER_NOPROMPT, SQLHWND hwnd = NULL)
+ {
+ m_connection.resize(512);
+ SQLSMALLINT out_len = 0;
+ if (m_opened)
+ close();
+ verify_error(SQLDriverConnectA(m_handle, hwnd, (SQLCHAR *)input_text, (SQLSMALLINT)text_length,
+ (SQLCHAR *)m_connection.data(), (SQLSMALLINT)m_connection.size(), &out_len, driver_completion));
+ m_connection.resize(out_len);
+ m_opened = true;
+ }
+ void open(const std::string &input_text, SQLSMALLINT driver_completion = SQL_DRIVER_NOPROMPT, SQLHWND hwnd = NULL)
+ {
+ open(input_text.data(), input_text.size(), driver_completion, hwnd);
+ }
+ void open(SQLHWND hwnd, SQLSMALLINT driver_completion = SQL_DRIVER_COMPLETE)
+ {
+ open("", SQL_NTS, driver_completion, hwnd);
+ }
+ // InputPred like:
+ // bool input_parameters(connection_parameters& parameters);
+ template <typename InputPred>
+ void open(const char *connection_text, size_t text_length, InputPred &&pred)
+ {
+ SQLSMALLINT length = 0;
+ SQLRETURN ret = SQL_SUCCESS;
+ std::string input_text;
+ if (m_opened)
+ close();
+ if (text_length == SQL_NTS)
+ input_text = connection_text;
+ else
+ input_text.assign(connection_text, text_length);
+ m_connection.resize(1024);
+ while ((ret = SQLBrowseConnectA(m_handle, (SQLCHAR *)input_text.data(), SQL_NTS,
+ (SQLCHAR *)m_connection.data(), m_connection.size(), &length)) == SQL_NEED_DATA)
+ {
+ connection_parameters parameters;
+ parse_browse_string(m_connection.data(), length, parameters);
+ if (!pred(parameters))
+ throw error(SQL_NEED_DATA, "User cancel operation.");
+ input_text = create_connection_text(parameters);
+ }
+ if (ret == SQL_ERROR || ret == SQL_SUCCESS_WITH_INFO)
+ verify_error(ret);
+ m_opened = true;
+ }
+ template <typename InputPred>
+ void open(const char *connection_text, InputPred &&pred)
+ {
+ open(connection_text, SQL_NTS, std::forward<InputPred>(pred));
+ }
+ template <typename InputPred>
+ void open(const std::string &connection_text, InputPred &&pred)
+ {
+ open(connection_text.data(), connection_text.size(), std::forward<InputPred>(pred));
+ }
- void simple_execute(const char* query_text, size_t text_length = SQL_NTS)
- {
- statement command(*this);
- SQLRETURN ret = SQLExecDirectA(command.handle(), (SQLCHAR*)query_text, text_length);
- if (ret != SQL_SUCCESS && ret != SQL_NO_DATA)
- verify_error(ret);
- }
- void simple_execute(const std::string& query_text)
- {
- simple_execute(query_text.data(), query_text.size());
- }
+ 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 auto_commit(bool on)
- {
- set_attribute(SQL_ATTR_AUTOCOMMIT, on ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
- }
- void begin_transaction()
- {
- auto_commit(false);
- }
- void rollback()
- {
- verify_error(SQLEndTran(handler_type, m_handle, SQL_ROLLBACK));
- auto_commit(true);
- }
- void commit()
- {
- verify_error(SQLEndTran(handler_type, m_handle, SQL_COMMIT));
- auto_commit(true);
- }
+ void simple_execute(const char *query_text, size_t text_length = SQL_NTS)
+ {
+ statement command(*this);
+ SQLRETURN ret = SQLExecDirectA(command.handle(), (SQLCHAR *)query_text, text_length);
+ if (ret != SQL_SUCCESS && ret != SQL_NO_DATA)
+ verify_error(ret);
+ }
+ void simple_execute(const std::string &query_text)
+ {
+ simple_execute(query_text.data(), query_text.size());
+ }
- bool is_alive()
- {
- SQLINTEGER value;
- get_attribute(SQL_ATTR_CONNECTION_DEAD, value);
- return value == SQL_CD_FALSE;
- }
+ void auto_commit(bool on)
+ {
+ set_attribute(SQL_ATTR_AUTOCOMMIT, on ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
+ }
+ void begin_transaction()
+ {
+ auto_commit(false);
+ }
+ void rollback()
+ {
+ verify_error(SQLEndTran(handler_type, m_handle, SQL_ROLLBACK));
+ auto_commit(true);
+ }
+ void commit()
+ {
+ verify_error(SQLEndTran(handler_type, m_handle, SQL_COMMIT));
+ auto_commit(true);
+ }
+
+ bool is_alive()
+ {
+ SQLINTEGER value;
+ get_attribute(SQL_ATTR_CONNECTION_DEAD, value);
+ return value == SQL_CD_FALSE;
+ }
#ifdef QTL_ODBC_ENABLE_ASYNC_MODE
- //async_connection async_mode();
+ // async_connection async_mode();
-#endif //ODBC 3.80
+#endif // ODBC 3.80
+ };
-};
+ struct date : public SQL_DATE_STRUCT
+ {
+ date()
+ {
+ memset(this, 0, sizeof(SQL_DATE_STRUCT));
+ }
+ };
-struct date : public SQL_DATE_STRUCT
-{
- date()
- {
- memset(this, 0, sizeof(SQL_DATE_STRUCT));
- }
-};
+ struct time : public SQL_TIME_STRUCT
+ {
+ time()
+ {
+ memset(this, 0, sizeof(SQL_TIME_STRUCT));
+ }
+ };
-struct time : public SQL_TIME_STRUCT
-{
- time()
- {
- memset(this, 0, sizeof(SQL_TIME_STRUCT));
- }
-};
-
-struct timestamp : public SQL_TIMESTAMP_STRUCT
-{
- timestamp()
- {
- memset(this, 0, sizeof(SQL_TIMESTAMP_STRUCT));
- }
- timestamp(struct tm& tm)
- {
- 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;
- }
- timestamp(time_t value)
- {
- struct tm tm;
+ struct timestamp : public SQL_TIMESTAMP_STRUCT
+ {
+ timestamp()
+ {
+ memset(this, 0, sizeof(SQL_TIMESTAMP_STRUCT));
+ }
+ timestamp(struct tm &tm)
+ {
+ 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;
+ }
+ timestamp(time_t value)
+ {
+ struct tm tm;
#if defined(_MSC_VER)
- localtime_s(&tm, &value);
+ localtime_s(&tm, &value);
#elif defined(_POSIX_VERSION)
- localtime_r(&value, &tm);
+ localtime_r(&value, &tm);
#else
- tm=*localtime(&value);
+ tm = *localtime(&value);
#endif
- new(this)timestamp(tm);
- }
- timestamp(const timestamp& src)
- {
- memcpy(this, &src, sizeof(SQL_TIMESTAMP_STRUCT));
- }
- timestamp& operator=(const timestamp& src)
- {
- if(this!=&src)
- memcpy(this, &src, sizeof(SQL_TIMESTAMP_STRUCT));
- return *this;
- }
+ new (this) timestamp(tm);
+ }
+ timestamp(const timestamp &src)
+ {
+ memcpy(this, &src, sizeof(SQL_TIMESTAMP_STRUCT));
+ }
+ timestamp &operator=(const timestamp &src)
+ {
+ if (this != &src)
+ memcpy(this, &src, sizeof(SQL_TIMESTAMP_STRUCT));
+ return *this;
+ }
- static timestamp now()
- {
- time_t value;
- ::time(&value);
- return timestamp(value);
- }
+ static timestamp now()
+ {
+ time_t value;
+ ::time(&value);
+ return timestamp(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);
- }
- timeval get_timeval() const
- {
- timeval tv;
- struct tm tm;
- tv.tv_sec=as_tm(tm);
- tv.tv_usec=fraction/1000;
- }
-};
+ 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);
+ }
+ timeval get_timeval() const
+ {
+ timeval tv;
+ struct tm tm;
+ tv.tv_sec = as_tm(tm);
+ tv.tv_usec = fraction / 1000;
+ }
+ };
#ifdef QTL_ODBC_ENABLE_ASYNC_MODE
-class async_connection;
+ class async_connection;
-inline bool is_still_executing(SQLINTEGER code)
-{
- return code == SQL_STILL_EXECUTING;
-}
-
-class async_statement : public base_statement
-{
-public:
- explicit async_statement(async_connection& db);
- async_statement(async_statement&& src)
- : base_statement(std::move(src))
- {
- m_hCompleteEvent = src.m_hCompleteEvent;
- m_event=src.m_event;
- m_nQueryTimeout = src.m_nQueryTimeout;
- src.m_hCompleteEvent = nullptr;
- src.m_event = nullptr;
- }
- async_statement& operator=(async_statement&& src)
- {
- if (this != &src)
+ inline bool is_still_executing(SQLINTEGER code)
{
- base_statement::operator =(std::move(src));
- m_hCompleteEvent = src.m_hCompleteEvent;
- m_event = src.m_event;
- m_nQueryTimeout = src.m_nQueryTimeout;
- src.m_hCompleteEvent = nullptr;
- src.m_event = nullptr;
- }
- return *this;
- }
- ~async_statement()
- {
- close();
- }
-
- /*
- Handler defiens as:
- void handler(const qtl::odbc::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);
- reset();
- SQLRETURN ret = SQLPrepareA(m_handle, (SQLCHAR*)query_text, text_length);
- async_wait(ret, std::forward<Handler>(handler));
- }
-
- /*
- ExecuteHandler defiens as:
- void handler(const qtl::odbc::error& e, uint64_t affected);
- */
- template<typename Types, typename Handler>
- void execute(const Types& params, Handler&& handler)
- {
- SQLSMALLINT count = 0;
- SQLRETURN ret = SQLNumParams(m_handle, &count);
- if (!SQL_SUCCEEDED(ret))
- {
- handler(error(*this, ret), 0);
- return;
- }
- if (count > 0)
- {
- m_params.resize(count);
- qtl::bind_params(*this, params);
+ return code == SQL_STILL_EXECUTING;
}
- if (m_nQueryTimeout == 0)
- m_nQueryTimeout = query_timeout();
- ret = SQLExecute(m_handle);
- async_wait(ret, [this, count, handler](const error& e) mutable {
+ class async_statement : public base_statement
+ {
+ public:
+ explicit async_statement(async_connection &db);
+ async_statement(async_statement &&src)
+ : base_statement(std::move(src))
+ {
+ m_hCompleteEvent = src.m_hCompleteEvent;
+ m_event = src.m_event;
+ m_nQueryTimeout = src.m_nQueryTimeout;
+ src.m_hCompleteEvent = nullptr;
+ src.m_event = nullptr;
+ }
+ async_statement &operator=(async_statement &&src)
+ {
+ if (this != &src)
+ {
+ base_statement::operator=(std::move(src));
+ m_hCompleteEvent = src.m_hCompleteEvent;
+ m_event = src.m_event;
+ m_nQueryTimeout = src.m_nQueryTimeout;
+ src.m_hCompleteEvent = nullptr;
+ src.m_event = nullptr;
+ }
+ return *this;
+ }
+ ~async_statement()
+ {
+ close();
+ }
+
+ /*
+ Handler defiens as:
+ void handler(const qtl::odbc::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);
+ reset();
+ SQLRETURN ret = SQLPrepareA(m_handle, (SQLCHAR *)query_text, text_length);
+ async_wait(ret, std::forward<Handler>(handler));
+ }
+
+ /*
+ ExecuteHandler defiens as:
+ void handler(const qtl::odbc::error& e, uint64_t affected);
+ */
+ template <typename Types, typename Handler>
+ void execute(const Types ¶ms, Handler &&handler)
+ {
+ SQLSMALLINT count = 0;
+ SQLRETURN ret = SQLNumParams(m_handle, &count);
+ if (!SQL_SUCCEEDED(ret))
+ {
+ handler(error(*this, ret), 0);
+ return;
+ }
+ if (count > 0)
+ {
+ m_params.resize(count);
+ qtl::bind_params(*this, params);
+ }
+
+ if (m_nQueryTimeout == 0)
+ m_nQueryTimeout = query_timeout();
+ ret = SQLExecute(m_handle);
+ async_wait(ret, [this, count, handler](const error &e) mutable
+ {
SQLINTEGER ret = e.code();
if (ret == SQL_NEED_DATA)
async_param_data(0, count, std::forward<Handler>(handler));
else if(ret>=0)
handler(error(*this, ret), affetced_rows());
else
- handler(error(*this, ret), 0);
- });
- }
-
- template<typename Types, typename RowHandler, typename FinishHandler>
- void fetch(Types&& values, RowHandler&& row_handler, FinishHandler&& finish_handler)
- {
- if (!m_binded_cols)
- {
- SQLSMALLINT count = 0;
- SQLRETURN ret = SQLNumResultCols(m_handle, &count);
- if(!SQL_SUCCEEDED(ret))
- {
- finish_handler(error(*this, ret));
- return;
+ handler(error(*this, ret), 0); });
}
- if (count > 0)
+
+ template <typename Types, typename RowHandler, typename FinishHandler>
+ void fetch(Types &&values, RowHandler &&row_handler, FinishHandler &&finish_handler)
{
- m_params.resize(count);
- qtl::bind_record(*this, std::forward<Types>(values));
+ if (!m_binded_cols)
+ {
+ SQLSMALLINT count = 0;
+ SQLRETURN ret = SQLNumResultCols(m_handle, &count);
+ if (!SQL_SUCCEEDED(ret))
+ {
+ finish_handler(error(*this, ret));
+ return;
+ }
+ if (count > 0)
+ {
+ m_params.resize(count);
+ qtl::bind_record(*this, std::forward<Types>(values));
+ }
+ m_binded_cols = true;
+ }
+ return fetch(std::forward<RowHandler>(row_handler), std::forward<FinishHandler>(finish_handler));
}
- m_binded_cols = true;
- }
- 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)
- {
- SQLRETURN ret = SQLFetch(m_handle);
- async_wait(ret, [this, row_handler, finish_handler](const error& e) mutable {
+ template <typename RowHandler, typename FinishHandler>
+ void fetch(RowHandler &&row_handler, FinishHandler &&finish_handler)
+ {
+ SQLRETURN ret = SQLFetch(m_handle);
+ async_wait(ret, [this, row_handler, finish_handler](const error &e) mutable
+ {
SQLINTEGER ret = e.code();
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
{
@@ -1383,17 +1404,17 @@
finish_handler(error());
else
finish_handler(e);
+ } });
}
- });
- }
- template<typename Handler>
- void next_result(Handler handler)
- {
- SQLRETURN ret;
- m_binded_cols = false;
- ret = SQLMoreResults(m_handle);
- async_wait(ret, [this, handler](const error& e) mutable {
+ template <typename Handler>
+ void next_result(Handler handler)
+ {
+ SQLRETURN ret;
+ m_binded_cols = false;
+ ret = SQLMoreResults(m_handle);
+ async_wait(ret, [this, handler](const error &e) mutable
+ {
SQLINTEGER ret=e.code();
SQLSMALLINT count = 0;
if (ret == SQL_ERROR || ret == SQL_INVALID_HANDLE)
@@ -1412,83 +1433,83 @@
if (count > 0)
handler(error());
else
- next_result(handler);
- });
- }
+ next_result(handler); });
+ }
- HANDLE event_handle() const { return m_hCompleteEvent; }
+ HANDLE event_handle() const { return m_hCompleteEvent; }
- void close()
- {
- close_event();
- base_statement::close();
- }
+ void close()
+ {
+ close_event();
+ base_statement::close();
+ }
- template<typename CloseHandler>
- void close(CloseHandler&& handler)
- {
- if (m_handle)
- {
- close_event();
- SQLRETURN ret = SQLFreeHandle(handler_type, m_handle);
- if(SQL_SUCCEEDED(ret))
- m_handle = SQL_NULL_HANDLE;
- handler(error(*this, ret));
- }
- else
- {
- handler(error());
- }
- }
+ template <typename CloseHandler>
+ void close(CloseHandler &&handler)
+ {
+ if (m_handle)
+ {
+ close_event();
+ SQLRETURN ret = SQLFreeHandle(handler_type, m_handle);
+ if (SQL_SUCCEEDED(ret))
+ m_handle = SQL_NULL_HANDLE;
+ handler(error(*this, ret));
+ }
+ else
+ {
+ handler(error());
+ }
+ }
-private:
+ private:
+ void close_event()
+ {
+ if (m_hCompleteEvent)
+ {
+ if (m_event)
+ m_event->remove();
+ verify_error(SQLCancelHandle(handler_type, m_handle));
+ verify_error(SQLSetStmtAttr(m_handle, SQL_ATTR_ASYNC_STMT_EVENT, NULL, SQL_IS_POINTER));
+ verify_error(SQLSetStmtAttr(m_handle, SQL_ATTR_ASYNC_ENABLE, (SQLPOINTER)SQL_ASYNC_ENABLE_OFF, SQL_IS_INTEGER));
+ CloseHandle(m_hCompleteEvent);
+ m_hCompleteEvent = NULL;
+ }
+ }
- void close_event()
- {
- if (m_hCompleteEvent)
- {
- if (m_event)
- m_event->remove();
- verify_error(SQLCancelHandle(handler_type, m_handle));
- verify_error(SQLSetStmtAttr(m_handle, SQL_ATTR_ASYNC_STMT_EVENT, NULL, SQL_IS_POINTER));
- verify_error(SQLSetStmtAttr(m_handle, SQL_ATTR_ASYNC_ENABLE, (SQLPOINTER)SQL_ASYNC_ENABLE_OFF, SQL_IS_INTEGER));
- CloseHandle(m_hCompleteEvent);
- m_hCompleteEvent = NULL;
- }
- }
+ template <typename Handler>
+ void async_wait(SQLINTEGER ret, Handler &&handler) NOEXCEPT
+ {
+ if (is_still_executing(ret))
+ {
+ m_event->set_io_handler(0, m_nQueryTimeout,
+ [this, handler](int flags) mutable
+ {
+ RETCODE code;
+ SQLCompleteAsync(SQL_HANDLE_STMT, m_handle, &code);
+ if (SQL_SUCCEEDED(code))
+ {
+ handler(odbc::error());
+ }
+ else
+ {
+ SetEvent(m_hCompleteEvent);
+ handler(odbc::error(*this, code));
+ }
+ });
+ }
+ else
+ {
+ handler(error(*this, ret));
+ }
+ }
- template<typename Handler>
- void async_wait(SQLINTEGER ret, Handler&& handler) NOEXCEPT
- {
- if(is_still_executing(ret))
- {
- m_event->set_io_handler(0, m_nQueryTimeout,
- [this, handler](int flags) mutable {
- RETCODE code;
- SQLCompleteAsync(SQL_HANDLE_STMT, m_handle, &code);
- if (SQL_SUCCEEDED(code))
- {
- handler(odbc::error());
- }
- else
- {
- SetEvent(m_hCompleteEvent);
- handler(odbc::error(*this, code));
- }
- });
- }
- else
- {
- handler(error(*this, ret));
- }
- }
-
- template<typename Handler>
- void async_param_data(SQLSMALLINT index, SQLSMALLINT count, Handler&& handler) NOEXCEPT
- {
- SQLPOINTER token;
- SQLRETURN ret = SQLParamData(m_handle, &token);
- async_wait(ret, [this, index, count, token, handler](const error& e) mutable {
+ template <typename Handler>
+ void async_param_data(SQLSMALLINT index, SQLSMALLINT count, Handler &&handler) NOEXCEPT
+ {
+ SQLPOINTER token;
+ SQLRETURN ret = SQLParamData(m_handle, &token);
+ async_wait(ret, [this, index, count, token, handler](const error &e) mutable
+ {
SQLINTEGER ret = e.code();
if (ret == SQL_NEED_DATA)
{
@@ -1507,430 +1528,440 @@
else
{
handler(error(*this, ret), affetced_rows());
+ } });
}
- });
- }
- int query_timeout() const
- {
- SQLULEN timeout = 0;
- verify_error(SQLGetStmtAttr(m_handle, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)&timeout, NULL, NULL));
- return timeout;
- }
+ int query_timeout() const
+ {
+ SQLULEN timeout = 0;
+ verify_error(SQLGetStmtAttr(m_handle, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)&timeout, NULL, NULL));
+ return timeout;
+ }
-private:
- HANDLE m_hCompleteEvent;
- qtl::event* m_event;
- SQLULEN m_nQueryTimeout;
-};
+ private:
+ HANDLE m_hCompleteEvent;
+ qtl::event *m_event;
+ SQLULEN m_nQueryTimeout;
+ };
-class async_connection : public base_database, public qtl::async_connection<async_connection, async_statement>
-{
-public:
- async_connection(environment& env) : base_database(env)
- {
- set_attribute(SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE, SQL_ASYNC_DBC_ENABLE_ON);
- m_hCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (m_hCompleteEvent == NULL)
+ class async_connection : public base_database, public qtl::async_connection<async_connection, async_statement>
{
- throw std::system_error(std::error_code(GetLastError(), std::system_category()));
- }
- set_attribute(SQL_ATTR_ASYNC_DBC_EVENT, m_hCompleteEvent);
- }
- async_connection(async_connection&& src) :
- base_database(std::move(src)),
- qtl::async_connection<async_connection, async_statement>(std::move(src)),
- m_BindFunc(std::move(src.m_BindFunc))
- {
- m_hCompleteEvent = src.m_hCompleteEvent;
- src.m_hCompleteEvent = nullptr;
- }
- ~async_connection()
- {
- if (m_hCompleteEvent)
- {
- verify_error(SQLCancelHandle(handler_type, m_handle));
- set_attribute(SQL_ATTR_ASYNC_DBC_EVENT, (SQLPOINTER)NULL);
- }
- if (m_opened)
- {
- set_attribute(SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE, SQL_ASYNC_DBC_ENABLE_OFF);
- verify_error(SQLDisconnect(m_handle));
- m_opened = false;
- }
- if (m_hCompleteEvent)
- {
- CloseHandle(m_hCompleteEvent);
- }
- }
-
- /*
- OpenHandler defines as:
- void handler(const qtl::odbc::error& e) NOEXCEPT;
- */
- template<class EventLoop, typename OpenHandler>
- void open(EventLoop& ev, OpenHandler&& handler, const char* server_name, size_t server_name_length,
- const char* user_name, size_t user_name_length, const char* password, size_t password_length)
- {
- if (m_opened) close();
- SQLRETURN err = SQLConnectA(m_handle, (SQLCHAR*)server_name, static_cast<SQLSMALLINT>(server_name_length),
- (SQLCHAR*)user_name, static_cast<SQLSMALLINT>(user_name_length), (SQLCHAR*)password, static_cast<SQLSMALLINT>(password_length));
- async_wait_connect(err, ev, std::forward<OpenHandler>(handler));
- }
- template<class EventLoop, typename OpenHandler>
- void open(EventLoop& ev, OpenHandler&& handler, const char* server_name, const char* user_name, const char* password)
- {
- if (m_opened) close();
- SQLRETURN err = SQLConnectA(m_handle, (SQLCHAR*)server_name, SQL_NTS, (SQLCHAR*)user_name, SQL_NTS, (SQLCHAR*)password, SQL_NTS);
- async_wait_connect(err, ev, std::forward<OpenHandler>(handler));
- }
- template<class EventLoop, typename OpenHandler>
- void open(EventLoop& ev, OpenHandler&& handler, const std::string& server_name, const std::string& user_name, const std::string& password)
- {
- open(ev, std::forward<OpenHandler>(handler), server_name.data(), server_name.size(), user_name.data(), user_name.size(), password.data(), password.size());
- }
- template<class EventLoop, typename OpenHandler>
- void open(EventLoop& ev, OpenHandler&& handler, const char* input_text, size_t text_length = SQL_NTS, SQLSMALLINT driver_completion = SQL_DRIVER_NOPROMPT, SQLHWND hwnd = NULL)
- {
- m_connection.resize(512);
- SQLSMALLINT out_len=0;
- SQLRETURN err = SQLDriverConnectA(m_handle, hwnd, (SQLCHAR*)input_text, (SQLSMALLINT)text_length,
- (SQLCHAR*)m_connection.data(), (SQLSMALLINT)m_connection.size(), &out_len, driver_completion);
- m_connection.resize(out_len);
- async_wait_connect(err, ev, std::forward<OpenHandler>(handler));
- }
- template<class EventLoop, typename OpenHandler>
- void open(EventLoop& ev, OpenHandler&& handler, const std::string& input_text, SQLSMALLINT driver_completion = SQL_DRIVER_NOPROMPT, SQLHWND hwnd = NULL)
- {
- open(ev, std::forward<OpenHandler>(handler), input_text.data(), input_text.size(), driver_completion, hwnd);
- }
- template<class EventLoop, typename OpenHandler>
- void open(EventLoop& ev, OpenHandler&& handler, SQLHWND hwnd, SQLSMALLINT driver_completion = SQL_DRIVER_COMPLETE)
- {
- open(ev, std::forward<OpenHandler>(handler), "", SQL_NTS, driver_completion, hwnd);
- }
-
- /*
- CloseHandler defines as:
- void handler(const qtl::odbc::error& e) NOEXCEPT;
- */
- template<typename CloseHandler >
- void close(CloseHandler&& handler) NOEXCEPT
- {
- SQLRETURN ret = SQLDisconnect(m_handle);
- m_opened = false;
- async_wait(ret, [this, handler](const error& e) {
- if (!e) m_opened = false;
- handler(e);
- });
- }
-
- /*
- ExecuteHandler defines as:
- void handler(const qtl::odbc::error& e) NOEXCEPT;
- */
- template<typename ExecuteHandler>
- void simple_execute(ExecuteHandler&& handler, const char* query_text, size_t text_length = SQL_NTS) NOEXCEPT
- {
- statement command(*this);
- SQLRETURN ret = SQLExecDirectA(command.handle(), (SQLCHAR*)query_text, static_cast<SQLINTEGER>(text_length));
- async_wait(ret, std::forward<ExecuteHandler>(handler));
- }
- template<typename ExecuteHandler>
- void simple_execute(ExecuteHandler&& handler, const std::string& query_text)
- {
- simple_execute(std::forward<ExecuteHandler>(handler), query_text.data(), query_text.size());
- }
-
- 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 odbc::error& e) mutable {
- handler(e, stmt);
- }, query_text, text_length);
- }
-
- HANDLE event_handle() const { return m_hCompleteEvent; }
-
- qtl::event* rebind(HANDLE hEvent)
- {
- return m_BindFunc(hEvent);
- }
-
-private:
-
- template<typename Handler>
- void async_wait(SQLRETURN ret, Handler&& handler) NOEXCEPT
- {
- if (is_still_executing(ret))
- {
- m_event_handler->set_io_handler(0, connect_timeout(),
- [this, handler](int flags) mutable {
- RETCODE code;
- SQLCompleteAsync(SQL_HANDLE_DBC, m_handle, &code);
- if (SQL_SUCCEEDED(code))
+ public:
+ async_connection(environment &env) : base_database(env)
+ {
+ set_attribute(SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE, SQL_ASYNC_DBC_ENABLE_ON);
+ m_hCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (m_hCompleteEvent == NULL)
{
- handler(odbc::error());
+ throw std::system_error(std::error_code(GetLastError(), std::system_category()));
+ }
+ set_attribute(SQL_ATTR_ASYNC_DBC_EVENT, m_hCompleteEvent);
+ }
+ async_connection(async_connection &&src) : base_database(std::move(src)),
+ qtl::async_connection<async_connection, async_statement>(std::move(src)),
+ m_BindFunc(std::move(src.m_BindFunc))
+ {
+ m_hCompleteEvent = src.m_hCompleteEvent;
+ src.m_hCompleteEvent = nullptr;
+ }
+ ~async_connection()
+ {
+ if (m_hCompleteEvent)
+ {
+ verify_error(SQLCancelHandle(handler_type, m_handle));
+ set_attribute(SQL_ATTR_ASYNC_DBC_EVENT, (SQLPOINTER)NULL);
+ }
+ if (m_opened)
+ {
+ set_attribute(SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE, SQL_ASYNC_DBC_ENABLE_OFF);
+ verify_error(SQLDisconnect(m_handle));
+ m_opened = false;
+ }
+ if (m_hCompleteEvent)
+ {
+ CloseHandle(m_hCompleteEvent);
+ }
+ }
+
+ /*
+ OpenHandler defines as:
+ void handler(const qtl::odbc::error& e) NOEXCEPT;
+ */
+ template <class EventLoop, typename OpenHandler>
+ void open(EventLoop &ev, OpenHandler &&handler, const char *server_name, size_t server_name_length,
+ const char *user_name, size_t user_name_length, const char *password, size_t password_length)
+ {
+ if (m_opened)
+ close();
+ SQLRETURN err = SQLConnectA(m_handle, (SQLCHAR *)server_name, static_cast<SQLSMALLINT>(server_name_length),
+ (SQLCHAR *)user_name, static_cast<SQLSMALLINT>(user_name_length), (SQLCHAR *)password, static_cast<SQLSMALLINT>(password_length));
+ async_wait_connect(err, ev, std::forward<OpenHandler>(handler));
+ }
+ template <class EventLoop, typename OpenHandler>
+ void open(EventLoop &ev, OpenHandler &&handler, const char *server_name, const char *user_name, const char *password)
+ {
+ if (m_opened)
+ close();
+ SQLRETURN err = SQLConnectA(m_handle, (SQLCHAR *)server_name, SQL_NTS, (SQLCHAR *)user_name, SQL_NTS, (SQLCHAR *)password, SQL_NTS);
+ async_wait_connect(err, ev, std::forward<OpenHandler>(handler));
+ }
+ template <class EventLoop, typename OpenHandler>
+ void open(EventLoop &ev, OpenHandler &&handler, const std::string &server_name, const std::string &user_name, const std::string &password)
+ {
+ open(ev, std::forward<OpenHandler>(handler), server_name.data(), server_name.size(), user_name.data(), user_name.size(), password.data(), password.size());
+ }
+ template <class EventLoop, typename OpenHandler>
+ void open(EventLoop &ev, OpenHandler &&handler, const char *input_text, size_t text_length = SQL_NTS, SQLSMALLINT driver_completion = SQL_DRIVER_NOPROMPT, SQLHWND hwnd = NULL)
+ {
+ m_connection.resize(512);
+ SQLSMALLINT out_len = 0;
+ SQLRETURN err = SQLDriverConnectA(m_handle, hwnd, (SQLCHAR *)input_text, (SQLSMALLINT)text_length,
+ (SQLCHAR *)m_connection.data(), (SQLSMALLINT)m_connection.size(), &out_len, driver_completion);
+ m_connection.resize(out_len);
+ async_wait_connect(err, ev, std::forward<OpenHandler>(handler));
+ }
+ template <class EventLoop, typename OpenHandler>
+ void open(EventLoop &ev, OpenHandler &&handler, const std::string &input_text, SQLSMALLINT driver_completion = SQL_DRIVER_NOPROMPT, SQLHWND hwnd = NULL)
+ {
+ open(ev, std::forward<OpenHandler>(handler), input_text.data(), input_text.size(), driver_completion, hwnd);
+ }
+ template <class EventLoop, typename OpenHandler>
+ void open(EventLoop &ev, OpenHandler &&handler, SQLHWND hwnd, SQLSMALLINT driver_completion = SQL_DRIVER_COMPLETE)
+ {
+ open(ev, std::forward<OpenHandler>(handler), "", SQL_NTS, driver_completion, hwnd);
+ }
+
+ /*
+ CloseHandler defines as:
+ void handler(const qtl::odbc::error& e) NOEXCEPT;
+ */
+ template <typename CloseHandler>
+ void close(CloseHandler &&handler) NOEXCEPT
+ {
+ SQLRETURN ret = SQLDisconnect(m_handle);
+ m_opened = false;
+ async_wait(ret, [this, handler](const error &e)
+ {
+ if (!e) m_opened = false;
+ handler(e); });
+ }
+
+ /*
+ ExecuteHandler defines as:
+ void handler(const qtl::odbc::error& e) NOEXCEPT;
+ */
+ template <typename ExecuteHandler>
+ void simple_execute(ExecuteHandler &&handler, const char *query_text, size_t text_length = SQL_NTS) NOEXCEPT
+ {
+ statement command(*this);
+ SQLRETURN ret = SQLExecDirectA(command.handle(), (SQLCHAR *)query_text, static_cast<SQLINTEGER>(text_length));
+ async_wait(ret, std::forward<ExecuteHandler>(handler));
+ }
+ template <typename ExecuteHandler>
+ void simple_execute(ExecuteHandler &&handler, const std::string &query_text)
+ {
+ simple_execute(std::forward<ExecuteHandler>(handler), query_text.data(), query_text.size());
+ }
+
+ 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 odbc::error &e) mutable
+ { handler(e, stmt); }, query_text, text_length);
+ }
+
+ HANDLE event_handle() const { return m_hCompleteEvent; }
+
+ qtl::event *rebind(HANDLE hEvent)
+ {
+ return m_BindFunc(hEvent);
+ }
+
+ private:
+ template <typename Handler>
+ void async_wait(SQLRETURN ret, Handler &&handler) NOEXCEPT
+ {
+ if (is_still_executing(ret))
+ {
+ m_event_handler->set_io_handler(0, connect_timeout(),
+ [this, handler](int flags) mutable
+ {
+ RETCODE code;
+ SQLCompleteAsync(SQL_HANDLE_DBC, m_handle, &code);
+ if (SQL_SUCCEEDED(code))
+ {
+ handler(odbc::error());
+ }
+ else
+ {
+ SetEvent(m_hCompleteEvent);
+ handler(odbc::error(*this, code));
+ }
+ });
}
else
{
- SetEvent(m_hCompleteEvent);
- handler(odbc::error(*this, code));
+ handler(odbc::error(*this, ret));
}
- });
- }
- else
- {
- handler(odbc::error(*this, ret));
- }
- }
-
- template<typename EventLoop, typename Handler>
- void async_wait_connect(SQLRETURN err, EventLoop& ev, Handler&& handler)
- {
- bind(ev);
- m_BindFunc = [&ev](HANDLE hEvent) {
- return ev.add(hEvent);
- };
- if(is_still_executing(err))
- {
- async_wait(err, [this, handler](const error& e) mutable {
- if (!e) m_opened = true;
- handler(e);
- });
- }
- else
- {
- handler(odbc::error(*this, err));
- }
- }
-
- int connect_timeout() const
- {
- int timeout=0;
- verify_error(SQLGetConnectAttr(m_handle, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)&timeout, 0, NULL));
- return timeout;
- }
-
-private:
- HANDLE m_hCompleteEvent;
- std::function<qtl::event*(HANDLE)> m_BindFunc;
-};
-
-inline async_statement::async_statement(async_connection& db)
- : base_statement(static_cast<base_database&>(db))
-{
- verify_error(SQLSetStmtAttr(m_handle, SQL_ATTR_ASYNC_ENABLE, (SQLPOINTER)SQL_ASYNC_ENABLE_ON, SQL_IS_INTEGER));
- m_hCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (m_hCompleteEvent == NULL)
- {
- throw std::system_error(std::error_code(GetLastError(), std::system_category()));
- }
- verify_error(SQLSetStmtAttr(m_handle, SQL_ATTR_ASYNC_STMT_EVENT, m_hCompleteEvent, SQL_IS_POINTER));
- m_event = db.rebind(this->m_hCompleteEvent);
- m_nQueryTimeout = query_timeout();
-}
-
-#endif //ODBC 3.80
-
-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;
-}
-
-template<SQLSMALLINT Type>
-inline error::error(const object<Type>& h, SQLINTEGER code)
-{
- m_errno=code;
- if(code==SQL_ERROR || code==SQL_SUCCESS_WITH_INFO)
- {
- SQLSMALLINT i=0;
- SQLINTEGER err=SQL_SUCCESS;
- SQLCHAR message[SQL_MAX_MESSAGE_LENGTH];
- SQLCHAR state[SQL_SQLSTATE_SIZE+1];
- std::ostringstream oss;
- SQLRETURN ret = SQLGetDiagRecA(object<Type>::handler_type, h.handle(), ++i, state, &err,
- message, SQL_MAX_MESSAGE_LENGTH, NULL);
- while(ret==SQL_SUCCESS)
- {
- oss<<"["<<state<<"] ("<<err<<") "<<message<<std::endl;
- ret = SQLGetDiagRecA(object<Type>::handler_type, h.handle(), ++i, state, &err,
- message, SQL_MAX_MESSAGE_LENGTH, NULL);
- }
- m_errmsg=oss.str();
- }
- else if(code==SQL_INVALID_HANDLE)
- {
- m_errmsg="Invalid handle.";
- }
-}
-
-inline void base_database::parse_browse_string(const char* output_text, size_t text_length, connection_parameters& parameters)
-{
- enum { part_name, part_prompt, part_list, part_value };
- const char* sp=output_text;
- const char* token=sp;
- connection_parameter parameter;
- int part_type=part_name;
- while(sp!=output_text+text_length)
- {
- switch(*sp)
- {
- case ';':
- parameters.emplace_back(parameter);
- parameter.reset();
- part_type=part_name;
- token=sp+1;
- break;
- case '=':
- if(part_type==part_prompt)
- parameter.m_prompt.assign(token, sp-token);
- part_type=part_value;
- token=sp+1;
- break;
- case ':':
- if(part_type==part_name)
- parameter.m_name.assign(token, sp-token);
- part_type=part_prompt;
- token=sp+1;
- break;
- case '{':
- part_type=part_list;
- parameter.m_value_list.clear();
- token=sp+1;
- break;;
- case '}':
- case ',':
- if(part_type==part_list)
- parameter.m_value_list.emplace_back(token, sp-token);
- token=sp+1;
- break;
- case '*':
- if(part_type==part_name && token==sp)
- {
- parameter.m_optinal=true;
- token=sp+1;
}
- break;
- case '?':
- token=sp+1;
- break;
+
+ template <typename EventLoop, typename Handler>
+ void async_wait_connect(SQLRETURN err, EventLoop &ev, Handler &&handler)
+ {
+ bind(ev);
+ m_BindFunc = [&ev](HANDLE hEvent)
+ {
+ return ev.add(hEvent);
+ };
+ if (is_still_executing(err))
+ {
+ async_wait(err, [this, handler](const error &e) mutable
+ {
+ if (!e) m_opened = true;
+ handler(e); });
+ }
+ else
+ {
+ handler(odbc::error(*this, err));
+ }
+ }
+
+ int connect_timeout() const
+ {
+ int timeout = 0;
+ verify_error(SQLGetConnectAttr(m_handle, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)&timeout, 0, NULL));
+ return timeout;
+ }
+
+ private:
+ HANDLE m_hCompleteEvent;
+ std::function<qtl::event *(HANDLE)> m_BindFunc;
+ };
+
+ inline async_statement::async_statement(async_connection &db)
+ : base_statement(static_cast<base_database &>(db))
+ {
+ verify_error(SQLSetStmtAttr(m_handle, SQL_ATTR_ASYNC_ENABLE, (SQLPOINTER)SQL_ASYNC_ENABLE_ON, SQL_IS_INTEGER));
+ m_hCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (m_hCompleteEvent == NULL)
+ {
+ throw std::system_error(std::error_code(GetLastError(), std::system_category()));
+ }
+ verify_error(SQLSetStmtAttr(m_handle, SQL_ATTR_ASYNC_STMT_EVENT, m_hCompleteEvent, SQL_IS_POINTER));
+ m_event = db.rebind(this->m_hCompleteEvent);
+ m_nQueryTimeout = query_timeout();
}
- ++sp;
- }
- if(!parameter.m_name.empty())
- parameters.emplace_back(parameter);
-}
-inline std::string base_database::create_connection_text(const connection_parameters& parameters)
-{
- std::ostringstream oss;
- for(auto& parameter : parameters)
- {
- if(parameter.m_assigned)
- oss<<parameter.m_name<<'='<<parameter.m_value<<';';
- }
- return oss.str();
-}
+#endif // ODBC 3.80
-inline base_statement::base_statement(base_database& db)
- : object(db.handle()), m_blob_buffer(NULL), m_binded_cols(false)
-{
-}
+ typedef qtl::transaction<database> transaction;
-} //odbc
+ 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 ¶ms)
+ {
+ stmt.reset();
+ stmt.execute(params);
+ return stmt;
+ }
+
+ template <SQLSMALLINT Type>
+ inline error::error(const object<Type> &h, SQLINTEGER code)
+ {
+ m_errno = code;
+ if (code == SQL_ERROR || code == SQL_SUCCESS_WITH_INFO)
+ {
+ SQLSMALLINT i = 0;
+ SQLINTEGER err = SQL_SUCCESS;
+ SQLCHAR message[SQL_MAX_MESSAGE_LENGTH];
+ SQLCHAR state[SQL_SQLSTATE_SIZE + 1];
+ std::ostringstream oss;
+ SQLRETURN ret = SQLGetDiagRecA(object<Type>::handler_type, h.handle(), ++i, state, &err,
+ message, SQL_MAX_MESSAGE_LENGTH, NULL);
+ while (ret == SQL_SUCCESS)
+ {
+ oss << "[" << state << "] (" << err << ") " << message << std::endl;
+ ret = SQLGetDiagRecA(object<Type>::handler_type, h.handle(), ++i, state, &err,
+ message, SQL_MAX_MESSAGE_LENGTH, NULL);
+ }
+ m_errmsg = oss.str();
+ }
+ else if (code == SQL_INVALID_HANDLE)
+ {
+ m_errmsg = "Invalid handle.";
+ }
+ }
+
+ inline void base_database::parse_browse_string(const char *output_text, size_t text_length, connection_parameters ¶meters)
+ {
+ enum
+ {
+ part_name,
+ part_prompt,
+ part_list,
+ part_value
+ };
+ const char *sp = output_text;
+ const char *token = sp;
+ connection_parameter parameter;
+ int part_type = part_name;
+ while (sp != output_text + text_length)
+ {
+ switch (*sp)
+ {
+ case ';':
+ parameters.emplace_back(parameter);
+ parameter.reset();
+ part_type = part_name;
+ token = sp + 1;
+ break;
+ case '=':
+ if (part_type == part_prompt)
+ parameter.m_prompt.assign(token, sp - token);
+ part_type = part_value;
+ token = sp + 1;
+ break;
+ case ':':
+ if (part_type == part_name)
+ parameter.m_name.assign(token, sp - token);
+ part_type = part_prompt;
+ token = sp + 1;
+ break;
+ case '{':
+ part_type = part_list;
+ parameter.m_value_list.clear();
+ token = sp + 1;
+ break;
+ ;
+ case '}':
+ case ',':
+ if (part_type == part_list)
+ parameter.m_value_list.emplace_back(token, sp - token);
+ token = sp + 1;
+ break;
+ case '*':
+ if (part_type == part_name && token == sp)
+ {
+ parameter.m_optinal = true;
+ token = sp + 1;
+ }
+ break;
+ case '?':
+ token = sp + 1;
+ break;
+ }
+ ++sp;
+ }
+ if (!parameter.m_name.empty())
+ parameters.emplace_back(parameter);
+ }
+
+ inline std::string base_database::create_connection_text(const connection_parameters ¶meters)
+ {
+ std::ostringstream oss;
+ for (auto ¶meter : parameters)
+ {
+ if (parameter.m_assigned)
+ oss << parameter.m_name << '=' << parameter.m_value << ';';
+ }
+ return oss.str();
+ }
+
+ inline base_statement::base_statement(base_database &db)
+ : object(db.handle()), m_blob_buffer(NULL), m_binded_cols(false)
+ {
+ }
+
+ } // odbc
#ifdef _WIN32
-namespace mssql
-{
-
-class database : public odbc::database
-{
-public:
- explicit database(odbc::environment& env) : odbc::database(env) { }
- database(database&& src) : odbc::database(std::move(src)) { }
-
- void open(const char* server, const char* db=NULL, const char* user=NULL, const char* password=NULL)
+ namespace mssql
{
- std::ostringstream oss;
- oss<<"DRIVER={SQL Server};SERVER="<<server<<";";
- if(user==NULL)
- oss<<"UID=;PWD=;Trusted_Connection=yes;";
- else
+
+ class database : public odbc::database
{
- oss<<"UID="<<user<<";PWD=";
- if(password) oss<<password;
- oss<<";Trusted_Connection=no;";
- }
- oss<<"DATABASE="<<db;
- odbc::database::open(oss.str());
- }
-};
+ public:
+ explicit database(odbc::environment &env) : odbc::database(env) {}
+ database(database &&src) : odbc::database(std::move(src)) {}
+
+ void open(const char *server, const char *db = NULL, const char *user = NULL, const char *password = NULL)
+ {
+ std::ostringstream oss;
+ oss << "DRIVER={SQL Server};SERVER=" << server << ";";
+ if (user == NULL)
+ oss << "UID=;PWD=;Trusted_Connection=yes;";
+ else
+ {
+ oss << "UID=" << user << ";PWD=";
+ if (password)
+ oss << password;
+ oss << ";Trusted_Connection=no;";
+ }
+ oss << "DATABASE=" << db;
+ odbc::database::open(oss.str());
+ }
+ };
#ifdef QTL_ODBC_ENABLE_ASYNC_MODE
-class async_connection : public odbc::async_connection
-{
-public:
- explicit async_connection(odbc::environment& env) : odbc::async_connection(env) { }
- async_connection(async_connection&& src) : odbc::async_connection(std::move(src)) { }
-
- template<typename EventLoop, typename OpenHandler>
- void open(EventLoop& ev, const OpenHandler& handler, const char* server, const char* db = NULL, const char* user = NULL, const char* password = NULL)
- {
- std::ostringstream oss;
- oss << "DRIVER={ODBC Driver 11 for SQL Server};SERVER=" << server << ";";
- if (user == NULL)
- oss << "UID=;PWD=;Trusted_Connection=yes;";
- else
+ class async_connection : public odbc::async_connection
{
- oss << "UID=" << user << ";PWD=";
- if (password) oss << password;
- oss << ";Trusted_Connection=no;";
- }
- oss << "DATABASE=" << db;
- odbc::async_connection::open(ev, handler, oss.str());
- }
+ public:
+ explicit async_connection(odbc::environment &env) : odbc::async_connection(env) {}
+ async_connection(async_connection &&src) : odbc::async_connection(std::move(src)) {}
-};
+ template <typename EventLoop, typename OpenHandler>
+ void open(EventLoop &ev, const OpenHandler &handler, const char *server, const char *db = NULL, const char *user = NULL, const char *password = NULL)
+ {
+ std::ostringstream oss;
+ oss << "DRIVER={ODBC Driver 11 for SQL Server};SERVER=" << server << ";";
+ if (user == NULL)
+ oss << "UID=;PWD=;Trusted_Connection=yes;";
+ else
+ {
+ oss << "UID=" << user << ";PWD=";
+ if (password)
+ oss << password;
+ oss << ";Trusted_Connection=no;";
+ }
+ oss << "DATABASE=" << db;
+ odbc::async_connection::open(ev, handler, oss.str());
+ }
+ };
#endif
-} //mssql
+ } // mssql
-namespace msaccess
-{
-
-class database : public odbc::database
-{
-public:
- explicit database(odbc::environment& env) : odbc::database(env) { }
- database(database&& src) : odbc::database(std::forward<database>(src)) { }
-
- void open(const char* filename, const char* user=NULL, const char* password=NULL)
+ namespace msaccess
{
- std::ostringstream oss;
- oss<<"DRIVER={Microsoft Access Driver};DBQ="<<filename;
- if(user) oss<<";UID:"<<user;
- if(password) oss<<";PWD="<<password;
- odbc::database::open(oss.str());
- }
-};
-} //msaccess
+ class database : public odbc::database
+ {
+ public:
+ explicit database(odbc::environment &env) : odbc::database(env) {}
+ database(database &&src) : odbc::database(std::forward<database>(src)) {}
+
+ void open(const char *filename, const char *user = NULL, const char *password = NULL)
+ {
+ std::ostringstream oss;
+ oss << "DRIVER={Microsoft Access Driver};DBQ=" << filename;
+ if (user)
+ oss << ";UID:" << user;
+ if (password)
+ oss << ";PWD=" << password;
+ odbc::database::open(oss.str());
+ }
+ };
+
+ } // msaccess
#endif //_WIN32
--
Gitblit v1.9.3