humorly / sql_wrapper Goto Github PK
View Code? Open in Web Editor NEW封装mysql官方的cppconn c++接口的更高级封装,使增删改查变得更加modern c++。(跨平台)
License: MIT License
封装mysql官方的cppconn c++接口的更高级封装,使增删改查变得更加modern c++。(跨平台)
License: MIT License
修改对应MySQL Connector库目录下的 ...\include\jdbc\mysql_connection.h 文件
修改该文件后的源码如下:
mysql_connection.h
/*
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2.0, as
* published by the Free Software Foundation.
*
* This program is also distributed with certain software (including
* but not limited to OpenSSL) that is licensed under separate terms,
* as designated in a particular file or component or in included license
* documentation. The authors of MySQL hereby grant you an
* additional permission to link the program and your derivative works
* with the separately licensed software that they have included with
* MySQL.
*
* Without limiting anything contained in the foregoing, this file,
* which is part of MySQL Connector/C++, is also subject to the
* Universal FOSS Exception, version 1.0, a copy of which can be found at
* http://oss.oracle.com/licenses/universal-foss-exception.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License, version 2.0, for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _MYSQL_CONNECTION_H_
#define _MYSQL_CONNECTION_H_
#include "cppconn/connection.h"
#include <memory>
namespace sql
{
namespace mysql
{
class MySQL_Savepoint : public sql::Savepoint
{
sql::SQLString name;
public:
MySQL_Savepoint(const sql::SQLString& savepoint);
virtual ~MySQL_Savepoint() {}
int getSavepointId();
sql::SQLString getSavepointName();
private:
/* Prevent use of these */
MySQL_Savepoint(const MySQL_Savepoint&);
void operator=(MySQL_Savepoint&);
};
class MySQL_DebugLogger;
struct MySQL_ConnectionData; /* PIMPL */
class MySQL_Statement;
namespace NativeAPI
{
class NativeConnectionWrapper;
}
class CPPCONN_PUBLIC_FUNC MySQL_Connection : public sql::Connection
{
MySQL_Statement* createServiceStmt();
public:
MySQL_Connection(Driver* _driver,
::sql::mysql::NativeAPI::NativeConnectionWrapper& _proxy,
const sql::SQLString& hostName,
const sql::SQLString& userName,
const sql::SQLString& password);
MySQL_Connection(Driver* _driver, ::sql::mysql::NativeAPI::NativeConnectionWrapper& _proxy,
std::map< sql::SQLString, sql::ConnectPropertyVal >& options);
virtual ~MySQL_Connection();
void clearWarnings();
void close();
void commit();
sql::Statement* createStatement();
sql::SQLString escapeString(const sql::SQLString&);
bool getAutoCommit();
sql::SQLString getCatalog();
Driver* getDriver();
sql::SQLString getSchema();
sql::SQLString getClientInfo();
void getClientOption(const sql::SQLString& optionName, void* optionValue);
sql::SQLString getClientOption(const sql::SQLString& optionName);
sql::DatabaseMetaData* getMetaData();
enum_transaction_isolation getTransactionIsolation();
const SQLWarning* getWarnings();
bool isClosed();
bool isReadOnly();
bool isValid();
bool reconnect();
sql::SQLString nativeSQL(const sql::SQLString& sql);
sql::PreparedStatement* prepareStatement(const sql::SQLString& sql);
sql::PreparedStatement* prepareStatement(const sql::SQLString& sql, int autoGeneratedKeys);
sql::PreparedStatement* prepareStatement(const sql::SQLString& sql, int columnIndexes[]);
sql::PreparedStatement* prepareStatement(const sql::SQLString& sql, int resultSetType, int resultSetConcurrency);
sql::PreparedStatement* prepareStatement(const sql::SQLString& sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability);
sql::PreparedStatement* prepareStatement(const sql::SQLString& sql, sql::SQLString columnNames[]);
void releaseSavepoint(Savepoint* savepoint);
void rollback();
void rollback(Savepoint* savepoint);
void setAutoCommit(bool autoCommit);
void setCatalog(const sql::SQLString& catalog);
void setSchema(const sql::SQLString& catalog);
sql::Connection* setClientOption(const sql::SQLString& optionName, const void* optionValue);
sql::Connection* setClientOption(const sql::SQLString& optionName, const sql::SQLString& optionValue);
void setHoldability(int holdability);
void setReadOnly(bool readOnly);
sql::Savepoint* setSavepoint();
sql::Savepoint* setSavepoint(const sql::SQLString& name);
void setTransactionIsolation(enum_transaction_isolation level);
virtual sql::SQLString getSessionVariable(const sql::SQLString& varname);
virtual void setSessionVariable(const sql::SQLString& varname, const sql::SQLString& value);
virtual void setSessionVariable(const sql::SQLString& varname, unsigned int value);
virtual sql::SQLString getLastStatementInfo();
private:
/* We do not really think this class has to be subclassed*/
void checkClosed();
void init(std::map< sql::SQLString, sql::ConnectPropertyVal >& properties);
Driver* driver;
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable: 4251)
#endif
std::shared_ptr< NativeAPI::NativeConnectionWrapper > proxy;
#ifdef _WIN32
#pragma warning(pop)
#endif
/* statement handle to execute queries initiated by driver. Perhaps it is
a good idea to move it to a separate helper class */
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable: 4251)
#endif
std::unique_ptr< ::sql::mysql::MySQL_Statement > service;
std::unique_ptr< ::sql::mysql::MySQL_ConnectionData > intern; /* pimpl */
#ifdef _WIN32
#pragma warning(pop)
#endif
/* Prevent use of these */
MySQL_Connection(const MySQL_Connection&);
void operator=(MySQL_Connection&);
};
} /* namespace mysql */
} /* namespace sql */
#endif // _MYSQL_CONNECTION_H_
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
测试代码:
sql_warpper sql_("tcp://127.0.0.1:3306", "root", "123456", "gamed");
bool ret_ = false;
ret_ = sql_.create("create table test (id_ double, name_ varchar(64), password_ varchar(64)); ");
ret_ = sql_.insert("insert into test values(5.12056683, \"humorly\", \"chen123\");");
ret_ = sql_.insert("insert into test values(5.12056684, \"humorly\", \"chen123\");");
ret_ = sql_.insert("insert into test values(5.12056685, \"humorly\", \"chen123\");");
ret_ = sql_.remove("delete from test where id_ = 5.12056684;");
ret_ = sql_.update("update game.test set id_ = 5.55555555 where id_ = 5.12056683;");
// 待搜索的字段信息
std::tuple<std::string, std::string, std::string> params_("id_", "name_", "password_");
std::vector<std::tuple<double, std::string, std::string>> user_content_;
ret_ = sql_.select("SELECT * FROM test", user_content_, params_);
std::cout << "content:" << std::endl;
for (auto & val : user_content_)
{
std::cout << "id_ = " << std::get<0>(val) << ", ";
std::cout << "name_ = " << std::get<1>(val) << ", ";
std::cout << "password_ = " << std::get<2>(val) << std::endl;
}
return 0;
封装过程:
使用mysql等数据库在查询时无法避免一个问题,在作select操作时,经常要调用mysql对象中的getInt、getString、getByte、getDouble...,并且要将mysql中的sql::ResultSet对象公开(或以接口提供),其中mysql提供的cppconn也没有很好的解决方案。这里做了一番思考,为何不把对象的查询字段做一个tuple封装,传递给查询接口对应的”字段名称“。再做一个tuple传递结果字段的对应类型,并将查询到的“字段值”存储到其中。该过程中对tuple进行展开让编译器去调用getInt、getString、getByte、getDouble...等,代码设计如下:
1:设计一个获取字段值的tuple,必须与select操作需要的字段值对应,用来将其中的“字段名称”传递给getInt等方法作为参数,例如设计搜索表user_content中的"id_", "name_", "password_"(其中id_值类型为int,其他为varchar(string)); 则有展开字段模板:
std::tuple<std::string, std::string, std::string> params_("id_", "name_", "password_");
2:设计一个接收结果的tuple,用来接收表中搜索到的字段类型结果:
std::tuple<int, std::string, std::string> user_content_;
3:将select语句、content_、parm_传递到展开接口separation中:
bool select(const std::string & command, std::vector<__dest_type> & dest, __set parm)
{
try {
pstmt_ = con_->prepareStatement(command.c_str());
res_ = pstmt_->executeQuery();
res_->afterLast();
while (res_->previous())
{
// 这里进行参数展开
// 将res传入其中,待稍后参数展开时get对应的字段值
separation<__dest_type, sql::ResultSet, __set, __type, params...>(dest, res_, parm);
}
delete res_;
delete pstmt_;
}
catch (sql::SQLException &e) {
std::string str_logger_("sql error by create select -> code is " +
std::to_string(e.getErrorCode()) + " & describe is " + std::string(e.what()));
wstd::log_writer::log_store(str_logger_, __FILE_LINE__);
return false;
}
return true;
}
4:展开过程解释:
std::vector<__dest_type> & separation(std::vector<__dest_type> & dest, __value_type * src, __set parm)
{
__dest_type tu_;
// 获取字段列表parm待展开的参数数目
constexpr int size_ = sizeof...(params);
// 对参数进行递归展开
get_class<0, size_>::template get<__dest_type, __value_type, __set, T, params...>(tu_, src, parm);
dest.push_back(tu_);
return dest;
}
5:逐字段赋值过程
template<integer_type N, integer_type M>
struct get_class
{
template <typename __dest, typename __src, typename __set, typename T, typename ... params>
inline static void get(__dest & dest, __src * src, __set parm)
{
constexpr integer_type index_ = N + 1;
// 对tuple中的第N个元素赋值
// 右侧通过偏特化dest中的模板参数调用对应的get value方法
std::get<N>(dest) = get_value_type<T, __src, const char *>::template get_value(src, std::get<N>(parm).c_str());
// 递归下一字段
get_class<index_, M>::template get<__dest, __src, __set, params...>(dest, src, parm);
}
};
// 递归到末元素时只赋值无需继续递归
// 末元素即为N = M,即偏特化M,M
template<integer_type M>
struct get_class<M, M>
{
template <typename __dest, typename __src, typename __set, typename T>
inline static void get(__dest & dest, __src * src, __set parm)
{
// 末元素赋值
std::get<M>(dest) = get_value_type<T, __src, const char *>::template get_value(src, std::get<M>(parm).c_str());
}
};
6:偏特化get value过程:
template<typename __value_type, typename __dest_type, typename __parm>
struct get_value_type
{
inline static auto get_value(__dest_type * val, __parm parm) {}
};
// bigint
template<typename __dest_type, typename __parm>
struct get_value_type<integer_type, __dest_type, __parm>
{
inline static auto get_value(__dest_type * val, __parm parm) -> decltype(val->getInt64(parm))
{
return val->getInt64(parm);
}
};
// varchar
template<typename __dest_type, typename __parm>
struct get_value_type<std::string, __dest_type, __parm>
{
inline static std::string get_value(__dest_type * val, __parm parm)
{
return val->getString(parm).c_str();
}
};
// 其他类型在这里照例补充偏特化
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.