BG
This commit is contained in:
@@ -58,7 +58,7 @@ add_subdirectory(src/yutil)
|
||||
add_subdirectory(src/yqt)
|
||||
add_subdirectory(src/ynet)
|
||||
add_subdirectory(src/yqlua)
|
||||
add_subdirectory(src/ymysql)
|
||||
add_subdirectory(src/ysql)
|
||||
######################## 三方库 ########################
|
||||
add_subdirectory(3rdparty/zlib)
|
||||
add_subdirectory(3rdparty/lua)
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
~buffer();
|
||||
void set(const char* data, size_t length);
|
||||
void set(const ylib::buffer& data);
|
||||
void append(const std::string& data);
|
||||
void append(const char* data, size_t length);
|
||||
void append(const ylib::buffer& data);
|
||||
void append(std::initializer_list<uchar> char_list);
|
||||
|
||||
@@ -2,19 +2,26 @@
|
||||
#include "http_define.h"
|
||||
#if USE_NET_HTTP_UTIL
|
||||
#include <map>
|
||||
namespace ylib::network::http
|
||||
namespace ylib
|
||||
{
|
||||
class cookie
|
||||
namespace network
|
||||
{
|
||||
public:
|
||||
cookie();
|
||||
~cookie();
|
||||
void merge(const cookie& ck);
|
||||
void merge(const std::string& ck);
|
||||
std::string to_string();
|
||||
void clear();
|
||||
private:
|
||||
std::map<std::string, std::string> m_param;
|
||||
};
|
||||
namespace http
|
||||
{
|
||||
class cookie
|
||||
{
|
||||
public:
|
||||
cookie();
|
||||
~cookie();
|
||||
void merge(const cookie& ck);
|
||||
void merge(const std::string& ck);
|
||||
std::string to_string();
|
||||
void clear();
|
||||
private:
|
||||
std::map<std::string, std::string> m_param;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
127
include/ysql/mssql.h
Normal file
127
include/ysql/mssql.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#pragma once
|
||||
#ifdef _WIN32
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#ifndef _WIN32
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#include "ybase/define.h"
|
||||
#include "ybase/error.h"
|
||||
#include "yutil/json.h"
|
||||
#include "yutil/pool.hpp"
|
||||
|
||||
namespace ylib::mssql
|
||||
{
|
||||
class pool;
|
||||
class result;
|
||||
class conn;
|
||||
class prepare_statement;
|
||||
struct mssql_conn_info
|
||||
{
|
||||
mssql_conn_info(){
|
||||
}
|
||||
std::string odbcname;
|
||||
std::string username;
|
||||
std::string password;
|
||||
};
|
||||
class result :public ylib::error_base
|
||||
{
|
||||
public:
|
||||
result();
|
||||
~result();
|
||||
// 列数量
|
||||
uint32 field_count();
|
||||
// 行数量
|
||||
size_t row_count();
|
||||
// 取文本值
|
||||
std::string get(uint32 field);
|
||||
// 下一行
|
||||
bool next();
|
||||
int32 get_int32(uint32 index);
|
||||
int32 get_int32(const std::string& name);
|
||||
|
||||
uint32 get_uint32(uint32 index);
|
||||
uint32 get_uint32(const std::string& name);
|
||||
|
||||
int64 get_int64(uint32 index);
|
||||
int64 get_int64(const std::string& name);
|
||||
|
||||
uint64 get_uint64(uint32 index);
|
||||
uint64 get_uint64(const std::string& name);
|
||||
|
||||
std::string get_string(uint32 index);
|
||||
std::string get_string(const std::string& name);
|
||||
|
||||
bool get_boolean(uint32 index);
|
||||
bool get_boolean(const std::string& name);
|
||||
|
||||
double get_double(uint32 index);
|
||||
double get_double(const std::string& name);
|
||||
|
||||
friend class ylib::mssql::prepare_statement;
|
||||
private:
|
||||
void* m_handle = nullptr;
|
||||
uint32 m_field_count = 0;
|
||||
uint32 m_row_count = 0;
|
||||
|
||||
std::map<std::string, short> m_field_name_index;
|
||||
};
|
||||
|
||||
class prepare_statement:public ylib::error_base{
|
||||
public:
|
||||
prepare_statement();
|
||||
~prepare_statement();
|
||||
void set_boolean(uint32 index,bool value);
|
||||
void set_datetime(uint32 index,const std::string& value);
|
||||
void set_double(uint32 index,double value);
|
||||
void set_int32(uint32 index,int32 value);
|
||||
void set_uint32(uint32 index,uint32 value);
|
||||
void set_int64(uint32 index,int64 value);
|
||||
void set_uint64(uint32 index,uint64 value);
|
||||
void set_null(uint32 index);
|
||||
void set_string(uint32 index,const std::string& value);
|
||||
void clear();
|
||||
uint64 update();
|
||||
ylib::mssql::result* query();
|
||||
|
||||
friend class ylib::mssql::conn;
|
||||
private:
|
||||
ylib::mssql::result* m_result = nullptr;
|
||||
void* m_handle = nullptr;
|
||||
};
|
||||
class conn :public ylib::example<ylib::mssql::mssql_conn_info>,public ylib::error_base
|
||||
{
|
||||
public:
|
||||
conn();
|
||||
~conn();
|
||||
virtual EXAMPLE_START_RESULT start(const ylib::mssql::mssql_conn_info&info) override;
|
||||
virtual void close() override;
|
||||
|
||||
|
||||
virtual void recover() override;
|
||||
virtual void task_out() override;
|
||||
|
||||
|
||||
void clear();
|
||||
ylib::mssql::prepare_statement* setsql(const std::string& sql);
|
||||
void begin();
|
||||
void commit();
|
||||
void rollback();
|
||||
friend class ylib::mssql::pool;
|
||||
private:
|
||||
void *m_handle = nullptr;
|
||||
ylib::mssql::mssql_conn_info m_info;
|
||||
class prepare_statement* m_ppst = nullptr;
|
||||
int m_sw = 0;
|
||||
};
|
||||
|
||||
|
||||
class pool: public ylib::pool<ylib::mssql::conn, ylib::mssql::mssql_conn_info>
|
||||
{
|
||||
public:
|
||||
pool();
|
||||
~pool();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -6,7 +6,7 @@ namespace ylib {
|
||||
public:
|
||||
counter(const T& default_value = 0){m_value = default_value;}
|
||||
~counter() {}
|
||||
size_t make(){
|
||||
T make(){
|
||||
std::unique_lock<std::mutex> guard(m_mutex);
|
||||
return ++m_value;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
namespace ylib
|
||||
{
|
||||
namespace debug
|
||||
{
|
||||
// 检测异常产生DUMP文件
|
||||
void detect_exception();
|
||||
#ifdef _WIN32
|
||||
// 打印VS控制台
|
||||
void vs_console_println(const std::string& value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
32
include/yutil/interval.hpp
Normal file
32
include/yutil/interval.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include <mutex>
|
||||
#include "yutil/time.h"
|
||||
namespace ylib {
|
||||
class interval {
|
||||
public:
|
||||
interval(timestamp msec):m_interval_msec(msec),m_pre_msec(0){
|
||||
m_pre_msec = time::now_msec();
|
||||
}
|
||||
~interval() {}
|
||||
/// <summary>
|
||||
/// 是否超市
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool isTimeout() {
|
||||
auto now_msec = time::now_msec();
|
||||
if (m_pre_msec + m_interval_msec < now_msec)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
void timeout() {
|
||||
m_pre_msec = time::now_msec() - m_interval_msec - 1;
|
||||
}
|
||||
void update() {
|
||||
m_pre_msec = time::now_msec();
|
||||
}
|
||||
|
||||
private:
|
||||
timestamp m_interval_msec = 0;
|
||||
timestamp m_pre_msec = 0;
|
||||
};
|
||||
}
|
||||
@@ -29,6 +29,8 @@ namespace ylib {
|
||||
m_pop_size--;
|
||||
m_queue.push(example);
|
||||
}
|
||||
public:
|
||||
void* env = nullptr;
|
||||
protected:
|
||||
ylib::queue<void*> m_queue;
|
||||
std::mutex m_mutex;
|
||||
@@ -150,6 +152,8 @@ namespace ylib {
|
||||
{
|
||||
bool init_success = false;
|
||||
example = new EXAMPLE;
|
||||
//example->pool((void*)this);
|
||||
((EXAMPLE*)example)->pool(this);
|
||||
for (uint32 i = 0; i < 3; i++)
|
||||
{
|
||||
auto SR = ((EXAMPLE*)example)->start(m_info);
|
||||
@@ -172,7 +176,7 @@ namespace ylib {
|
||||
if (init_success)
|
||||
{
|
||||
m_pop_size++;
|
||||
((EXAMPLE*)example)->pool(this);
|
||||
|
||||
((EXAMPLE*)example)->task_out();
|
||||
return ((EXAMPLE*)example);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,11 @@ void ylib::buffer::set(const ylib::buffer& data)
|
||||
set((const char*)data.data(), data.length());
|
||||
}
|
||||
|
||||
void ylib::buffer::append(const std::string& data)
|
||||
{
|
||||
append(data.c_str(),data.length());
|
||||
}
|
||||
|
||||
void ylib::buffer::append(const char* data, size_t length)
|
||||
{
|
||||
m_data.append((const uchar*)data,length);
|
||||
|
||||
471
src/ysql/src/mssql.cpp
Normal file
471
src/ysql/src/mssql.cpp
Normal file
@@ -0,0 +1,471 @@
|
||||
#include "ysql/mssql.h"
|
||||
#ifdef _WIN32
|
||||
#include "yutil/time.h"
|
||||
#include <windows.h>
|
||||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
#include "yutil/strutils.h"
|
||||
#define CHECK_SQL_CONNECTION if(m_handle == nullptr){throw ylib::exception("current connection is invalid");}
|
||||
#define CHECK_SQL_PPST if(m_handle == nullptr){throw ylib::exception("current preparedstatement is invalid");}
|
||||
#define CHECK_SQL_RESULT if(m_handle == nullptr){throw ylib::exception("current resultset is invalid");}
|
||||
|
||||
#define THROW_RET(RESULT,MSG) \
|
||||
if (RESULT != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) \
|
||||
throw ylib::exception(MSG)
|
||||
|
||||
|
||||
#define THROW_RET_BIND(RESULT) THROW_RET(RESULT,"SQLBindParameter Failed,code: " + std::to_string(RESULT))
|
||||
#define THROW_RET_GET(RESULT) THROW_RET(RESULT,"SQLGetData Failed,code: " + std::to_string(RESULT))
|
||||
|
||||
|
||||
|
||||
ylib::mssql::conn::conn()
|
||||
{
|
||||
m_handle = nullptr;
|
||||
m_ppst = nullptr;
|
||||
}
|
||||
|
||||
ylib::mssql::conn::~conn()
|
||||
{
|
||||
close();
|
||||
}
|
||||
EXAMPLE_START_RESULT ylib::mssql::conn::start(const mssql_conn_info &info)
|
||||
{
|
||||
if (info.odbcname.empty())
|
||||
{
|
||||
m_lastErrorDesc = "odbcname is empty";
|
||||
return SR_FAILED;
|
||||
}
|
||||
m_info = info;
|
||||
|
||||
|
||||
SQLHDBC hDbc = nullptr;
|
||||
SQLAllocHandle(SQL_HANDLE_DBC, m_pool->env, &hDbc);
|
||||
SQLCHAR connStr[1024];
|
||||
sprintf((char*)connStr, "DSN=%s;UID=%s;PWD=%s;", m_info.odbcname.c_str(), m_info.username.c_str(), m_info.password.c_str());
|
||||
SQLRETURN ret = SQLDriverConnect(hDbc, NULL, connStr, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
|
||||
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
|
||||
// 连接失败
|
||||
SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
|
||||
return SR_FAILED;
|
||||
}
|
||||
m_handle = hDbc;
|
||||
return SR_SUCCESS;
|
||||
}
|
||||
|
||||
void ylib::mssql::conn::close()
|
||||
{
|
||||
if (m_handle == nullptr)
|
||||
return;
|
||||
SQLDisconnect(m_handle);
|
||||
SQLFreeHandle(SQL_HANDLE_DBC, m_handle);
|
||||
}
|
||||
|
||||
void ylib::mssql::conn::recover()
|
||||
{
|
||||
if (m_sw == 1)
|
||||
{
|
||||
rollback();
|
||||
}
|
||||
SQLSetConnectAttr(m_pool->env, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
|
||||
clear();
|
||||
|
||||
}
|
||||
|
||||
void ylib::mssql::conn::task_out()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ylib::mssql::conn::clear()
|
||||
{
|
||||
if(this->m_ppst != nullptr)
|
||||
delete this->m_ppst;
|
||||
|
||||
this->m_ppst = nullptr;
|
||||
}
|
||||
|
||||
ylib::mssql::prepare_statement* ylib::mssql::conn::setsql(const std::string &sql)
|
||||
{
|
||||
CHECK_SQL_CONNECTION;
|
||||
clear();
|
||||
m_ppst = new prepare_statement;
|
||||
SQLAllocHandle(SQL_HANDLE_STMT, m_handle, &m_ppst->m_handle);
|
||||
SQLPrepare(m_ppst->m_handle, (SQLCHAR*)sql.c_str(), SQL_NTS);
|
||||
return m_ppst;
|
||||
}
|
||||
void ylib::mssql::conn::begin()
|
||||
{
|
||||
CHECK_SQL_CONNECTION;
|
||||
auto ret = SQLSetConnectAttr(m_handle, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0);
|
||||
THROW_RET(ret,"SQLSetConnectAttr failed,code: "+std::to_string(ret));
|
||||
m_sw = 1;
|
||||
}
|
||||
|
||||
void ylib::mssql::conn::commit()
|
||||
{
|
||||
auto ret = SQLTransact(m_pool->env, m_handle, SQL_COMMIT);
|
||||
THROW_RET(ret, "SQLSetConnectAttr failed,code: " + std::to_string(ret));
|
||||
m_sw = 0;
|
||||
}
|
||||
|
||||
void ylib::mssql::conn::rollback()
|
||||
{
|
||||
auto ret = SQLTransact(m_pool->env, m_handle, SQL_ROLLBACK);
|
||||
THROW_RET(ret, "SQLTransact failed,code: " + std::to_string(ret));
|
||||
}
|
||||
ylib::mssql::prepare_statement::prepare_statement()
|
||||
{
|
||||
m_result = nullptr;
|
||||
m_handle = nullptr;
|
||||
}
|
||||
|
||||
ylib::mssql::prepare_statement::~prepare_statement()
|
||||
{
|
||||
clear();
|
||||
if(m_handle != nullptr)
|
||||
{
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, m_handle);
|
||||
m_handle = nullptr;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
#define PRINT_DEBUG_SET std::cout<<__FUNCTION__<<"["<<index<<"]: "<<value<<std::endl
|
||||
#define PRINT_DEBUG_SET_std::string std::cout<<__FUNCTION__<<"["<<index<<"]: "<<value.c_str()<<std::endl
|
||||
#else
|
||||
#define PRINT_DEBUG_SET
|
||||
#define PRINT_DEBUG_SET_NSTRING
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void ylib::mssql::prepare_statement::set_boolean(uint32 index, bool value)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
PRINT_DEBUG_SET;
|
||||
|
||||
SQLLEN lenOrInd = 0;
|
||||
auto ret = SQLBindParameter(m_handle, index, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, 0, 0, &value, 0, &lenOrInd);
|
||||
THROW_RET_BIND(ret);
|
||||
}
|
||||
|
||||
void ylib::mssql::prepare_statement::set_datetime(uint32 index, const std::string &value)
|
||||
{
|
||||
auto sec = time::to_ts(value);
|
||||
ylib::time::datetime dt;
|
||||
time::format(sec, dt);
|
||||
|
||||
SQL_TIMESTAMP_STRUCT mssdt;
|
||||
mssdt.year = dt.year;
|
||||
mssdt.month = dt.month;
|
||||
mssdt.day = dt.day;
|
||||
mssdt.hour = dt.hour;
|
||||
mssdt.minute = dt.minute;
|
||||
mssdt.second = dt.second;
|
||||
mssdt.fraction = 0;
|
||||
SQLLEN lenOrInd = 0;
|
||||
auto ret = SQLBindParameter(m_handle, index, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TIMESTAMP, 0, 0, &mssdt, 0, &lenOrInd);
|
||||
THROW_RET_BIND(ret);
|
||||
}
|
||||
|
||||
void ylib::mssql::prepare_statement::set_double(uint32 index, double value)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
PRINT_DEBUG_SET;
|
||||
|
||||
SQLLEN lenOrInd = 0;
|
||||
auto ret = SQLBindParameter(m_handle, index, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &value, 0, &lenOrInd);
|
||||
THROW_RET_BIND(ret);
|
||||
}
|
||||
|
||||
void ylib::mssql::prepare_statement::set_int32(uint32 index, int32 value)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
PRINT_DEBUG_SET;
|
||||
SQLLEN lenOrInd = 0;
|
||||
|
||||
auto ret = SQLBindParameter(m_handle, index, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &value, 0, &lenOrInd);
|
||||
THROW_RET_BIND(ret);
|
||||
}
|
||||
|
||||
void ylib::mssql::prepare_statement::set_uint32(uint32 index, uint32 value)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
PRINT_DEBUG_SET;
|
||||
|
||||
|
||||
SQLLEN lenOrInd = 0;
|
||||
auto ret = SQLBindParameter(m_handle, index, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &value, 0, &lenOrInd);
|
||||
THROW_RET_BIND(ret);
|
||||
}
|
||||
|
||||
void ylib::mssql::prepare_statement::set_int64(uint32 index, int64 value)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
PRINT_DEBUG_SET;
|
||||
|
||||
SQLLEN lenOrInd = 0;
|
||||
|
||||
auto ret = SQLBindParameter(m_handle, index, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, &value, 0, &lenOrInd);
|
||||
THROW_RET_BIND(ret);
|
||||
}
|
||||
|
||||
void ylib::mssql::prepare_statement::set_uint64(uint32 index, uint64 value)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
PRINT_DEBUG_SET;
|
||||
|
||||
SQLLEN lenOrInd = 0;
|
||||
auto ret = SQLBindParameter(m_handle, index, SQL_PARAM_INPUT, SQL_C_UBIGINT, SQL_BIGINT, 0, 0, &value, 0, &lenOrInd);
|
||||
THROW_RET_BIND(ret);
|
||||
}
|
||||
|
||||
void ylib::mssql::prepare_statement::set_null(uint32 index)
|
||||
{
|
||||
//throw ylib::exception("Not supported temporarily");
|
||||
|
||||
SQLLEN lenOrInd = SQL_NULL_DATA;
|
||||
auto ret = SQLBindParameter(m_handle, index, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 0, NULL, 0, &lenOrInd);
|
||||
THROW_RET_BIND(ret);
|
||||
}
|
||||
|
||||
void ylib::mssql::prepare_statement::set_string(uint32 index, const std::string &value)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
PRINT_DEBUG_SET_NSTRING;
|
||||
|
||||
SQLLEN lenOrInd = SQL_NTS; // SQL_NTS denotes string is null-terminated
|
||||
|
||||
auto ret = SQLBindParameter(m_handle, index, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, value.length(), 0, (void*)value.c_str(), 0, &lenOrInd);
|
||||
|
||||
THROW_RET_BIND(ret);
|
||||
|
||||
}
|
||||
void ylib::mssql::prepare_statement::clear()
|
||||
{
|
||||
if(m_result != nullptr)
|
||||
{
|
||||
delete m_result;
|
||||
}
|
||||
m_result = nullptr;
|
||||
}
|
||||
|
||||
uint64 ylib::mssql::prepare_statement::update()
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
clear();
|
||||
auto ret = SQLExecute(m_handle);
|
||||
THROW_RET(ret,"SQLExecute failed,code: "+std::to_string(ret));
|
||||
SQLLEN numRowsAffected = 0;
|
||||
ret = SQLRowCount(m_handle, &numRowsAffected);
|
||||
THROW_RET(ret, "SQLRowCount failed,code: " + std::to_string(ret));
|
||||
return numRowsAffected;
|
||||
}
|
||||
|
||||
ylib::mssql::result *ylib::mssql::prepare_statement::query()
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
clear();
|
||||
auto ret = SQLExecute(m_handle);
|
||||
THROW_RET(ret, "SQLExecute failed,code: " + std::to_string(ret));
|
||||
|
||||
m_result = new ylib::mssql::result();
|
||||
m_result->m_handle = m_handle;
|
||||
|
||||
// 列数量
|
||||
{
|
||||
short num = 0;
|
||||
auto ret = SQLNumResultCols(m_handle, &num);
|
||||
THROW_RET(ret, "SQLNumResultCols failed,code: " + std::to_string(ret));
|
||||
m_result->m_field_count = num;
|
||||
}
|
||||
// 行数量
|
||||
{
|
||||
SQLLEN numRowsAffected = 0;
|
||||
auto ret = SQLRowCount(m_handle, &numRowsAffected);
|
||||
THROW_RET(ret, "SQLRowCount failed,code: " + std::to_string(ret));
|
||||
m_result->m_row_count = numRowsAffected;
|
||||
}
|
||||
// 列名称对应索引位置
|
||||
{
|
||||
SQLCHAR colName[128];
|
||||
SQLSMALLINT colNameLen;
|
||||
SQLSMALLINT dataType;
|
||||
SQLULEN columnSize;
|
||||
SQLSMALLINT decimalDigits;
|
||||
SQLSMALLINT nullable;
|
||||
SQLRETURN ret;
|
||||
SQLSMALLINT targetCol = 0; // 目标列的索引
|
||||
for (SQLSMALLINT i = 1; i <= m_result->m_field_count; i++) {
|
||||
ret = SQLDescribeCol(m_handle, i, colName, sizeof(colName), &colNameLen, &dataType, &columnSize, &decimalDigits, &nullable);
|
||||
if (SQL_SUCCEEDED(ret)) {
|
||||
m_result->m_field_name_index[reinterpret_cast<char*>(colName)] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_result;
|
||||
}
|
||||
|
||||
ylib::mssql::result::result()
|
||||
{
|
||||
m_handle = nullptr;
|
||||
}
|
||||
|
||||
ylib::mssql::result::~result()
|
||||
{
|
||||
if(m_handle != nullptr)
|
||||
{
|
||||
m_handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 ylib::mssql::result::field_count()
|
||||
{
|
||||
return m_field_count;
|
||||
}
|
||||
|
||||
size_t ylib::mssql::result::row_count()
|
||||
{
|
||||
return m_row_count;
|
||||
}
|
||||
|
||||
bool ylib::mssql::result::next()
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
return SQLFetch(m_handle) == SQL_SUCCESS;
|
||||
}
|
||||
|
||||
int32 ylib::mssql::result::get_int32(uint32 index)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
SQLINTEGER value;
|
||||
SQLLEN length_or_indicator;
|
||||
auto ret = SQLGetData(m_handle, 1, SQL_C_SLONG, &value, sizeof(value), &length_or_indicator);
|
||||
THROW_RET_GET(ret);
|
||||
return value;
|
||||
}
|
||||
|
||||
int32 ylib::mssql::result::get_int32(const std::string &name)
|
||||
{
|
||||
return get_int32(m_field_name_index[name]);
|
||||
}
|
||||
|
||||
uint32 ylib::mssql::result::get_uint32(uint32 index)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
SQLUINTEGER value;
|
||||
SQLLEN length_or_indicator;
|
||||
auto ret = SQLGetData(m_handle, 1, SQL_C_ULONG, &value, sizeof(value), &length_or_indicator);
|
||||
THROW_RET_GET(ret);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32 ylib::mssql::result::get_uint32(const std::string &name)
|
||||
{
|
||||
return get_uint32(m_field_name_index[name]);
|
||||
}
|
||||
|
||||
int64 ylib::mssql::result::get_int64(uint32 index)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
SQLBIGINT value;
|
||||
SQLLEN length_or_indicator;
|
||||
auto ret = SQLGetData(m_handle, 1, SQL_C_SBIGINT, &value, sizeof(value), &length_or_indicator);
|
||||
THROW_RET_GET(ret);
|
||||
return value;
|
||||
}
|
||||
|
||||
int64 ylib::mssql::result::get_int64(const std::string &name)
|
||||
{
|
||||
return get_int64(m_field_name_index[name]);
|
||||
}
|
||||
|
||||
uint64 ylib::mssql::result::get_uint64(uint32 index)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
SQLUBIGINT value;
|
||||
SQLLEN length_or_indicator;
|
||||
auto ret = SQLGetData(m_handle, 1, SQL_C_UBIGINT, &value, sizeof(value), &length_or_indicator);
|
||||
THROW_RET_GET(ret);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64 ylib::mssql::result::get_uint64(const std::string &name)
|
||||
{
|
||||
return get_uint64(m_field_name_index[name]);
|
||||
}
|
||||
std::string ylib::mssql::result::get_string(uint32 index)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
SQLCHAR buffer[1024]; // 初始缓冲区
|
||||
SQLLEN str_len_or_ind;
|
||||
// 第一次调用SQLGetData来获取所需缓冲区的大小
|
||||
SQLRETURN ret = SQLGetData(m_handle, 1, SQL_C_CHAR, buffer, sizeof(buffer), &str_len_or_ind);
|
||||
|
||||
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
|
||||
if (str_len_or_ind == SQL_NULL_DATA) {
|
||||
return "";
|
||||
}
|
||||
else if (str_len_or_ind > sizeof(buffer) - 1 || ret == SQL_SUCCESS_WITH_INFO) {
|
||||
// 缓冲区太小,需要更大的缓冲区
|
||||
std::string data;
|
||||
data.resize(str_len_or_ind); // 调整字符串大小以适应全部数据
|
||||
|
||||
// 重新调用SQLGetData获取完整数据
|
||||
SQLGetData(m_handle, 1, SQL_C_CHAR, &data[0], data.size() + 1, &str_len_or_ind);
|
||||
return data;
|
||||
}
|
||||
else {
|
||||
// 缓冲区足够,数据已经被完整读取
|
||||
std::string data((char*)buffer);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
throw ylib::exception("SQLGetData failed, code: "+std::to_string(ret));
|
||||
}
|
||||
std::string ylib::mssql::result::get_string(const std::string &name)
|
||||
{
|
||||
return get_string(m_field_name_index[name]);
|
||||
}
|
||||
|
||||
bool ylib::mssql::result::get_boolean(uint32 index)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
SQLCHAR value;
|
||||
SQLLEN length_or_indicator;
|
||||
auto ret = SQLGetData(m_handle, 1, SQL_C_BIT, &value, sizeof(value), &length_or_indicator);
|
||||
THROW_RET_GET(ret);
|
||||
return (bool)value;
|
||||
}
|
||||
|
||||
bool ylib::mssql::result::get_boolean(const std::string &name)
|
||||
{
|
||||
return get_boolean(m_field_name_index[name]);
|
||||
}
|
||||
|
||||
double ylib::mssql::result::get_double(uint32 index)
|
||||
{
|
||||
CHECK_SQL_PPST;
|
||||
SQLDOUBLE value;
|
||||
SQLLEN length_or_indicator;
|
||||
auto ret = SQLGetData(m_handle, 1, SQL_C_DOUBLE, &value, sizeof(value), &length_or_indicator);
|
||||
THROW_RET_GET(ret);
|
||||
return value;
|
||||
}
|
||||
|
||||
double ylib::mssql::result::get_double(const std::string &name)
|
||||
{
|
||||
return get_double(m_field_name_index[name]);
|
||||
}
|
||||
|
||||
ylib::mssql::pool::pool()
|
||||
{
|
||||
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
|
||||
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
|
||||
SQLSetEnvAttr(env, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_HENV, 0);
|
||||
}
|
||||
ylib::mssql::pool::~pool()
|
||||
{
|
||||
SQLFreeHandle(SQL_HANDLE_ENV, env);
|
||||
}
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "ymysql/mysql_plus.h"
|
||||
#include "ysql/mysql.h"
|
||||
#include "cppconn/driver.h"
|
||||
#include "cppconn/connection.h"
|
||||
#include "cppconn/statement.h"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -87,4 +87,9 @@ void ylib::debug::detect_exception()
|
||||
{
|
||||
SetUnhandledExceptionFilter(ExceptionFilter);
|
||||
}
|
||||
void ylib::debug::vs_console_println(const std::string& value)
|
||||
{
|
||||
std::string v2 = value + "\n";
|
||||
OutputDebugString(value.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user