#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma
comment(lib,"libmysql.lib")
namespace mysql{
struct true_type {};
struct false_type{};
struct pod_tag{};
struct numeric_category_tag :
pod_tag{};
struct datetime_category_tag :
pod_tag{};
struct string_category_tag
{};
namespace detail{
template
ID> struct mytype_trait;
template struct
c_type_trait;
//根据 "C API Prepared Statement Type Codes"制定此表
//MySQL类型 ==> C基本数据类型
#define INTRODUCT_(category_prefix, MYSQL_TYPE_ID, ctype)
\
template<> \
struct
mytype_trait{
\
typedef
category_prefix##_category_tag category; \
typedef ctype
primitive_type; \
}; \
INTRODUCT_( numeric, MYSQL_TYPE_TINY
,char )
INTRODUCT_( numeric, MYSQL_TYPE_SHORT
,short )
INTRODUCT_( numeric, MYSQL_TYPE_INT24
,int )
INTRODUCT_( numeric, MYSQL_TYPE_LONG
,int )
INTRODUCT_( numeric, MYSQL_TYPE_LONGLONG
,__int64 )
INTRODUCT_( numeric, MYSQL_TYPE_FLOAT
,float )
INTRODUCT_( numeric, MYSQL_TYPE_DOUBLE
,double )
INTRODUCT_( string, MYSQL_TYPE_VAR_STRING
,char* )
INTRODUCT_( string, MYSQL_TYPE_STRING
,char*
)
INTRODUCT_( datetime, MYSQL_TYPE_TIMESTAMP ,MYSQL_TIME
)
INTRODUCT_( datetime, MYSQL_TYPE_DATE ,MYSQL_TIME
)
INTRODUCT_( datetime, MYSQL_TYPE_TIME ,MYSQL_TIME
)
INTRODUCT_( datetime, MYSQL_TYPE_DATETIME
,MYSQL_TIME )
//C基本数据类型
==> MySQL类型
#define TRANSLATE_PRIMITIVE(ctype,
MYSQL_TYPE_ID) \
template<> \
struct
c_type_trait{ \
typedef false_type
is_wrapper; \
static const
enum_field_types ID = MYSQL_TYPE_ID; \
}; \
TRANSLATE_PRIMITIVE( char , MYSQL_TYPE_TINY )
TRANSLATE_PRIMITIVE( short ,
MYSQL_TYPE_SHORT )
TRANSLATE_PRIMITIVE( int , MYSQL_TYPE_LONG )
TRANSLATE_PRIMITIVE( long , MYSQL_TYPE_LONG )
TRANSLATE_PRIMITIVE( __int64 , MYSQL_TYPE_LONGLONG )
TRANSLATE_PRIMITIVE( float ,
MYSQL_TYPE_FLOAT )
TRANSLATE_PRIMITIVE( double ,
MYSQL_TYPE_DOUBLE )
}
//数据封装类的基类,处理有关null的逻辑
struct Base{
Base():is_null_(0){}
bool isnull(){
return is_null_ ? true : false ;
}
void setnull(bool lb){
is_null_ = lb; }
my_bool is_null_;
};
//定义一些封装类
#define DECLARE_WRAPPER( classname , MYSQL_TYPE ) \
struct classname : Base{ \
static const
enum_field_types ID = MYSQL_TYPE; \
typedef
detail::mytype_trait::primitive_type
primitive_type; \
primitive_type data_;
\
void operator=(const
primitive_type& rhs){ data_ = rhs; } \
}; \
DECLARE_WRAPPER(Tiny , MYSQL_TYPE_TINY
)
DECLARE_WRAPPER(Small , MYSQL_TYPE_SHORT
)
DECLARE_WRAPPER(Int ,
MYSQL_TYPE_LONG )
DECLARE_WRAPPER(Int64 , MYSQL_TYPE_LONGLONG
)
DECLARE_WRAPPER(Float , MYSQL_TYPE_FLOAT
)
DECLARE_WRAPPER(Double , MYSQL_TYPE_DOUBLE )
struct Datetime_Base{
void year
(int y){ data_.year =
y;}
void month (int y){
data_.month = y;}
void day
(int y){ data_.day = y;}
void hour
(int y){ data_.hour =
y;}
void minute(int y){
data_.minute = y;}
void second(int y){
data_.second = y;}
int year()
{ return data_.year; }
int month() { return
data_.month; }
int day()
{ return data_.day; }
int hour()
{ return data_.hour; }
int minute(){ return
data_.minute; }
int second(){ return
data_.second; }
MYSQL_TIME data_;
};
//日期时间
struct Datetime : Base, Datetime_Base{
static const
enum_field_types ID = MYSQL_TYPE_DATETIME;
};
//日期
struct Date : Base, Datetime_Base{
static const
enum_field_types ID = MYSQL_TYPE_DATE;
};
//时间
struct Time : Base, Datetime_Base{
static const
enum_field_types ID = MYSQL_TYPE_TIME;
};
//字符串
struct String : Base
{
static const
enum_field_types ID = MYSQL_TYPE_STRING;
char* data_;
unsigned long
max_length_; //指出data_的最大长度
String(char*
str,unsigned long len ):data_(str),max_length_(len){}
String():data_(0),max_length_(0){}
};
namespace detail{
//封装类 ==> MySQL类型
#define TRANSLATE_WRAPPER( classname ) \
template<> \
struct
c_type_trait{ \
typedef true_type
is_wrapper; \
static const
enum_field_types ID = classname::ID; \
}; \
TRANSLATE_WRAPPER(Tiny)
TRANSLATE_WRAPPER(Small)
TRANSLATE_WRAPPER(Int)
TRANSLATE_WRAPPER(Int64)
TRANSLATE_WRAPPER(Float)
TRANSLATE_WRAPPER(Double)
TRANSLATE_WRAPPER(String)
TRANSLATE_WRAPPER(Datetime)
TRANSLATE_WRAPPER(Date)
TRANSLATE_WRAPPER(Time)
///
struct holder_base
{
char* buffer_;
//存放数据的地址
my_bool
is_null_; //是否是NULL
unsigned long
buffer_length_;
//如果是字符串,应该是存放字符串的数组长度
unsigned long
length_; //数据的实际长度
my_bool
error_;
enum_field_types
field_type_; //字段的MYSQL数据类型
std::string
field_name_; //字段的名字
std::string
table_name; //字段所在的表的名字
virtual ~holder_base(){}
//子类需要调析构函数
};
template
struct numeric_holder : holder_base
{
numeric_holder():data_(0){}
T data_;
template
bool
get(U& u)
{
//基本数据类型int,
double...无法区分0值和NULL值,只能用0值敷衍过去了
if (is_null_) { return u=0,true; }
//取标量,向目标类型转
try
{
u =
boost::numeric_cast(data_);
return
false;
}
catch (boost::numeric::bad_numeric_cast
&e)
{
UNREFERENCED_PARAMETER(e);
throw
db_exception("numeric_cast can not process",0);
}
}
};
/
struct datetime_holder : holder_base
{
MYSQL_TIME data_;
bool
get(MYSQL_TIME& u){
if (is_null_){
memset(&u,0,sizeof(MYSQL_TIME));
return
true;
}
u = data_;
return false;
}
};
struct string_holder : holder_base
{
char* data_;
bool
get(char*& u){
if (is_null_){ return u[0]=0, true; }
else { return u = data_, false;
}
}
string_holder(int
n):data_(new char[n+1]) {} //为0结束符留一个位置
~string_holder(){ delete
[] data_; data_=0; }
};
/
//根据类型ID,计算holder类型。
//例如
holder_typeof::type
<===>
numeric_holder
template
struct holder_generator;
template
struct
holder_generator
{
typedef
numeric_holder
holder_type;
};
template
struct
holder_generator
{
typedef string_holder
holder_type;
};
template
struct
holder_generator
{
typedef datetime_holder
holder_type;
};
template
struct holder
{
typedef typename
mytype_trait::category
C;
typedef typename
mytype_trait::primitive_type
T;
typedef typename
holder_generator::holder_type
type;
};
} //~end namespace detail
namespace detail{
template
struct is_tuple{
static const bool value = false;
};
template
struct
is_tuple<:tuple>
>{
static const bool value = true;
};
template
struct
is_tuple<:tuple>
>{
static const bool value = true;
};
template
T2>
struct
is_tuple<:tuple>
>{
static const bool value = true;
};
template
T3>
struct
is_tuple<:tuple>
>{
static const bool value = true;
};
template
T4>
struct
is_tuple<:tuple>
>{
static const bool value = true;
};
template
T4,class T5>
struct
is_tuple<:tuple>
>{
static const bool value = true;
};
template
T4,class T5,class T6>
struct
is_tuple<:tuple>
>{
static const bool value = true;
};
template
T4,class T5,class T6,class T7>
struct
is_tuple<:tuple>
>{
static const bool value = true;
};
template
T4,
class T5,class T6,class
T7,class T8>
struct
is_tuple<:tuple>
>{
static const bool value = true;
};
template
T4,
class T5,class T6,class
T7,class T8,class T9>
struct
is_tuple<:tuple>
>{
static const bool value = true;
};
};
class C_CON;
class C_STMT;
class C_RS;
class C_SQL;
//数据库异常
class db_exception : public std::exception
{
public:
virtual const char*
what() const { return _what.c_str(); }
long errcode(){ return
_errcode;}
db_exception(const char*
w = "",long errcode=0) throw() : _what(w),_errcode(errcode) {}
db_exception(const
std::string& w,long errcode=0) throw() :
_what(w),_errcode(errcode) {}
private:
std::string _what;
long _errcode;
};
///
//一条SQL语句
class C_SQL{
public:
C_SQL(){}
~C_SQL(){
BOOST_FOREACH(Para* p,param_){
delete
p;
}
param_.clear();
bind_param_.clear();
}
C_SQL&
operator%(const char* txt){
txt_ += txt;
return *this;
}
template
C_SQL&
operator%(T& obj)
{
return bind_para(obj);
}
private:
template
C_SQL&
bind_para(T& obj, typename
boost::disable_if<
detail::is_tuple
>::type* p=0){
txt_+= "? ";
create_para(obj);
return *this;
}
template
C_SQL&
bind_para(T& obj, typename
boost::enable_if<
detail::is_tuple
>::type* p=0){
txt_+="values(" ;
return
bind_tuple_helper::value>::bind(
*this, obj );
}
template
struct bind_tuple_helper
{
static C_SQL& bind(
C_SQL& s, const Tuple& t ) {
//text
appends
s.txt_+="?" ;
//deal
with a variable
s.create_para(
boost::get<:tuples::length>::value
- size>(t) );
//text
appends
if (size
!= 1){
s.txt_+=',' ;
}
//another
var
return
bind_tuple_helper::bind(
s, t );
}
};
//terminator
template
struct
bind_tuple_helper {
static C_SQL& bind(
C_SQL& s, const Tuple& t ) {
s.txt_ +=
')';
return
s;
}
};
template
void
create_para(T& obj){
//tag dispatch
detail::mytype_trait<
detail::c_type_trait::ID
>::category v1;
detail::c_type_trait::is_wrapper
v2;
MYSQL_BIND bd={0};
Para* p = new Para;
bd.buffer = p->buffer_
= addressof(obj,v1,v2);
bd.buffer_length =
p->buffer_length_ = buffer_length(obj,v1,v2);
bd.buffer_type =
p->buffer_type_ =
(enum_field_types)detail::c_type_trait::ID;
bd.length =
&p->length_;
//如果是包裹类的参数,使用包裹类中的is_null的地址
bind_isnull(bd,obj,v2);
param_.push_back(p);
bind_param_.push_back(bd);
}
template
void
bind_isnull(MYSQL_BIND& bd,T&
obj,true_type){
bd.is_null = &(obj.is_null_);
//SQL参数支持空值。
}
template
void
bind_isnull(MYSQL_BIND& bd,T&
obj,false_type){
bd.is_null = 0; //SQL参数支持空值。
}
template
char*
addressof(T& t, pod_tag ,
false_type){
return
(char*)&t;
}
template
char*
addressof(T& t, pod_tag,
true_type ){
return
(char*)&(t.data_);
}
template
char*
addressof(T& t, string_category_tag, false_type){
BOOST_STATIC_ASSERT_MSG(0,"does not support
char*");
}
template
char*
addressof(T& t, string_category_tag, true_type){
return t.data_;
}
template
IsWrapper>
unsigned long
buffer_length(T& t, Tag ,IsWrapper){
return 0;
}
template
unsigned long
buffer_length(T& t, string_category_tag,true_type){
return t.max_length_ ;
}
template
unsigned long
buffer_length(T& t,
string_category_tag,false_type){
BOOST_STATIC_ASSERT_MSG(0,"does not support
char*");
}
//存放Para
struct Para
{
Para():length_(0),buffer_(0),buffer_length_(0),is_null_(0){}
enum_field_types
buffer_type_;
char* buffer_;
unsigned long buffer_length_;
unsigned long length_; //数据的实际长度,对于STRING类型的字段,需要这个值
my_bool is_null_;
};
void
calculate_length()
{
BOOST_FOREACH(Para* p,param_){
if (
p->buffer_type_ == MYSQL_TYPE_STRING ){
p->length_ =
(unsigned long)strlen(p->buffer_);
}
}
}
std::vector bind_param_;
//用于取MYSQL_BIND数组
std::vector param_; //存放参数的信息
std::string txt_;
//sql语句
friend class
C_STMT;
friend class
C_CON;
};
/
//连接对象
class C_CON{
public:
//可用于bool判断
operator void*(){ return
con_ptr.get(); };
//取原始句柄
MYSQL* handle(){
return (MYSQL*)con_ptr.get(); }
//初始化
C_CON(const char* host,
const char* user, const char* password, const char* db);
~C_CON(){}
//利用prepare方法准备sql语句。
void prepare(C_SQL*
sql);
//执行SQL语句。把C_SQL当做ID使用
void execute(C_SQL*
sql);
private:
//保存连接句柄
boost::shared_ptr
con_ptr;
//key=C_SQL指针,当做一条SQL的ID标识符 value保存的是
C_STMT智能指针
typedef
std::map
> MAP;
MAP
prepared_sql_;
//当前语句
boost::shared_ptr
current_stmt_ptr;
friend class C_RS;
};
/
class C_STMT
{
bool have_resultset_;
//是否应具有结果集.SELECT ,SHOW, EXLPAIN等语句有结果集。
//DELETE,UPDATE等语句无结果集
std::vector<:holder_base>
row_;
std::vector
bind_column_;
C_CON
&con_;
boost::shared_ptr
stmt_ptr_;
void execSQL();
MYSQL_STMT*
handle(){
return
(MYSQL_STMT*)(stmt_ptr_.get());
}
//取当前结果集的当前行中,列的序号id对应的数据
template
bool getField(size_t id,
U& u)
{
//字段是否存在?
if (id<0 ||
id>row_.size()){
throw
db_exception("column out of range",0);
}
detail::holder_base* col = row_.at(id);
//tag dispatch
detail::mytype_trait<:c_type_trait>::ID>::category
v1;
detail::c_type_trait::is_wrapper
v2;
return getField_dispatch(col , u, v1 ,
v2);
}
private:
template
void bind(MYSQL_FIELD*
field){
typename
detail::mytype_trait::category
v1;
bind_dispatch(field,v1);
}
template
void bind_dispatch(
MYSQL_FIELD *field, string_category_tag )
{
unsigned long n = field->length +
1; //需要+1,为字符串结束符预留的
detail::string_holder* col = new
detail::string_holder(n); //需要预先分配容纳字符串的内存
col->field_type_ =
field->type;
col->buffer_ = (char
*)(col->data_);
MYSQL_BIND bd={0};
bd.buffer_type =
field->type;
bd.buffer = (char *)(col->data_);
bd.buffer_length = n ;
bd.is_null = &col->is_null_;
bd.length =
&col->length_;
bd.error =
&col->error_;
row_.push_back(col);
bind_column_.push_back(bd);
}
template
void bind_dispatch(
MYSQL_FIELD* field, pod_tag )
{
typedef
detail::holder::type
holder_type;
holder_type* col = new holder_type;
col->field_type_ =
field->type;
col->buffer_ = (char
*)&(col->data_);
MYSQL_BIND bd={0};
bd.buffer_type =
field->type;
bd.buffer = (char
*)&(col->data_);
bd.is_null = &col->is_null_;
bd.length =
&col->length_;
bd.error =
&col->error_;
row_.push_back(col);
bind_column_.push_back(bd);
}
// numeric类型字段
//封装类
template
bool
getField_dispatch(detail::holder_base* holder, U& w
,numeric_category_tag v1, true_type)
{
return w.is_null_ = getField_dispatch(holder,
w.data_ , v1 , false_type());
}
//基本数据类型
template
bool
getField_dispatch(detail::holder_base* holder,U&
u,numeric_category_tag, false_type)
{
switch(holder->field_type_)
{
case MYSQL_TYPE_TINY: return
static_cast<:holder>
>::type*>(holder)->get(u);
case MYSQL_TYPE_SHORT: return
static_cast<:holder>
>::type*>(holder)->get(u);
case MYSQL_TYPE_INT24: return
static_cast<:holder>
>::type*>(holder)->get(u);
case MYSQL_TYPE_LONG: return
static_cast<:holder>
>::type*>(holder)->get(u);
case MYSQL_TYPE_LONGLONG:return
static_cast<:holder>::type*>(holder)->get(u);
case MYSQL_TYPE_FLOAT: return
static_cast<:holder>
>::type*>(holder)->get(u);
case MYSQL_TYPE_DOUBLE: return
static_cast<:holder>
>::type*>(holder)->get(u);
default:
throw
db_exception("field is not numeric.",0);
}
return false;
}
///
// string类型字段
//封装类
template
bool
getField_dispatch(detail::holder_base* holder,U& w,
string_category_tag v1, true_type)
{
return w.is_null_ = getField_dispatch(holder,
w.data_ , v1 , false_type());
}
//基本类型
template
bool
getField_dispatch(detail::holder_base* holder,U& u,
string_category_tag, false_type)
{
switch(holder->field_type_)
{
case MYSQL_TYPE_STRING:
case
MYSQL_TYPE_VAR_STRING:
return
static_cast<:string_holder>(holder)->get(u);
default:
throw
db_exception("field is not string.",0);
}
return false;
}
// daetime类型字段
//封装类
template
bool
getField_dispatch(detail::holder_base* holder,U& w,
datetime_category_tag v1, true_type)
{
return w.is_null_ = getField_dispatch(holder,
w.data_ , v1 , false_type());
}
template
bool
getField_dispatch(detail::holder_base* holder,U&
u,datetime_category_tag,false_type)
{
switch(holder->field_type_)
{
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
return
static_cast<:datetime_holder>(holder)->get(u);
default:
throw
db_exception("field is not datetime.",0);
}
return false;
}
C_STMT(
C_CON& con,C_SQL* sql);
public:
~C_STMT()
{
BOOST_FOREACH(detail::holder_base*
p,row_){
delete
p;
}
row_.clear();
bind_column_.clear();
}
private:
friend class C_RS;
friend class
C_CON;
};
/
C_STMT::C_STMT( C_CON& con,C_SQL*
sql):have_resultset_(false),con_(con)
{
MYSQL* con_h =
con.handle();
boost::shared_ptr
ptr(mysql_stmt_init( con.handle() ),mysql_stmt_close);
stmt_ptr_ = ptr;
MYSQL_STMT* stmt_h =
(MYSQL_STMT*)stmt_ptr_.get();
if
(!stmt_h){
throw db_exception("mysql mysql_stmt_init()
fail",0);
}
if (mysql_stmt_prepare(
stmt_h, sql->txt_.c_str(), (unsigned
long)sql->txt_.length()))
{
throw
db_exception(mysql_error(con_h),mysql_errno(con_h));
}
int param_count=
mysql_stmt_param_count(stmt_h);
if
(param_count!=sql->bind_param_.size())
{
throw db_exception("sqltext error. not enough
params",0);
}
if (param_count
>0)
{
if (mysql_stmt_bind_param(stmt_h,
&sql->bind_param_[0])){
throw
db_exception(mysql_error(con_h),mysql_errno(con_h));
}
}
//获取结果集的元信息
boost::shared_ptr
sp(mysql_stmt_result_metadata(stmt_h),mysql_free_result);
MYSQL_RES* rs =
(MYSQL_RES*)sp.get();
if (rs)
{
int cnt= mysql_num_fields(rs);
row_.clear();
row_.reserve(cnt);
bind_column_.clear();
bind_column_.reserve(cnt);
MYSQL_FIELD *field;
while((field = mysql_fetch_field(rs)))
{
switch
(field->type)
{
case
MYSQL_TYPE_TINY: {
bind
> (field); break;
}
case
MYSQL_TYPE_SHORT: {
bind
> (field);
break; }
case
MYSQL_TYPE_INT24: {
bind
> (field);
break; }
case
MYSQL_TYPE_LONG: {
bind
> (field); break;
}
case
MYSQL_TYPE_LONGLONG: {
bind
> (field); break;
}
case
MYSQL_TYPE_FLOAT: {
bind
> (field);
break; }
case
MYSQL_TYPE_DOUBLE: {
bind
> (field);
break; }
case
MYSQL_TYPE_VAR_STRING: {
bind
(field); break; }
case
MYSQL_TYPE_STRING : {
bind
> (field);
break; }
case
MYSQL_TYPE_TIMESTAMP : {
bind
> (field); break; }
case
MYSQL_TYPE_DATE: {
bind
> (field); break;
}
case
MYSQL_TYPE_TIME: {
bind
> (field); break;
}
case
MYSQL_TYPE_DATETIME: {
bind
> (field); break;
}
default:
throw db_exception("cannot
deal with this field type",0);
break;
}
}
if (cnt!=row_.size()){ throw
db_exception("column count error",0); }
have_resultset_ = true;
}
else{
//没有结果集的语句
have_resultset_ = false;
}
}
//
void C_STMT::execSQL()
{
MYSQL_STMT* stmt_h =
(MYSQL_STMT*)stmt_ptr_.get();
MYSQL* con_h =
con_.handle();
if (!stmt_h){
throw db_exception("stmt is null",0);
}
if (mysql_stmt_execute(
stmt_h )){
throw db_exception( mysql_error(con_h),
mysql_errno(con_h) );
}
if
(have_resultset_)
{
if (mysql_stmt_bind_result(stmt_h,
&bind_column_[0])){
throw
db_exception(mysql_error(con_h),mysql_errno(con_h));
}
if (mysql_stmt_store_result(stmt_h))
{
throw
db_exception(mysql_error(con_h),mysql_errno(con_h));
}
}
}
namespace detail{
struct rsmanip{
rsmanip(){}
typedef
C_RS& (*PF)(C_RS&,int);
PF pf_;
int arg_;
rsmanip(PF pf, int
arg):pf_(pf),arg_(arg){}
};
}
/
class C_RS
{
public:
C_RS(C_CON&
conn):stmt_ptr_(conn.current_stmt_ptr){}
~C_RS(){ close();
}
bool next()
{
MYSQL_STMT* stmt_h =
stmt_ptr_->handle();
if (!stmt_h) return false;
else {
col_=0;
return
!mysql_stmt_fetch(stmt_h);
}
}
void close(){
mysql_stmt_free_result(stmt_ptr_->handle());
}
template
bool at(int column,
T& obj){ return
stmt_ptr_->getField(column,obj); }
template
C_RS&
operator>>(T&
t){
return extrat(t);
}
template
C_RS&
extrat(U& u ){
at(col_++,u);
return *this;
}
C_RS&
extrat(detail::rsmanip& u){
return
u.pf_(*this,u.arg_);
}
C_RS&
ignore(int n=1){
col_+=n;
return *this;
}
private:
boost::shared_ptr
stmt_ptr_;
int col_;
};
C_RS& set_ignore(C_RS& rs,int
n){ return rs.ignore(n); }
detail::rsmanip ignore(int n=1){
return
detail::rsmanip(set_ignore,n);
}
//
void C_CON::prepare(C_SQL* sql)
{
//已经解析过,不能重复解析
if
(prepared_sql_.find(sql) != prepared_sql_.end()) return;
boost::shared_ptr sp( new
C_STMT(*this, sql) );
prepared_sql_[sql]=sp;
}
/
C_CON::C_CON(const char* host, const char* user, const char*
password, const char*
db):con_ptr(mysql_init(NULL),mysql_close)
{
MYSQL* conn_h =
handle();
if (!conn_h) throw
db_exception("mysql_init fail. no memery.",0);
if
(!mysql_real_connect(conn_h, host , user , password , db , 0, NULL,
0))
{
throw
db_exception(mysql_error(conn_h),mysql_errno(conn_h));
}
}
/
void C_CON::execute(C_SQL* sql)
{
MAP::iterator ite =
prepared_sql_.find(sql);
if
(ite==prepared_sql_.end()){ throw db_exception("sql not register.
please call setSQL first",0); }
sql->calculate_length(); //计算字符串类型参数的长度
current_stmt_ptr =
ite->second;
current_stmt_ptr->execSQL();
}
template
T3,class T4,class T5,class T6,class T7,class T8,class
T9>
boost::tuple
values(T0& t0,T1&
t1,T2& t2,T3&
t3,T4& t4,T5&
t5,T6& t6,T7&
t7,T8& t8,T9& t9){
using namespace
boost;
return
boost::make_tuple(ref(t0),ref(t1),ref(t2),ref(t3),ref(t4),ref(t5),ref(t6),ref(t7),ref(t8),ref(t9));
}
template
T3,class T4,class T5,class T6,class T7,class
T8>
boost::tuple
values(T0& t0,T1&
t1,T2& t2,T3&
t3,T4& t4,T5&
t5,T6& t6,T7&
t7,T8& t8){
using namespace
boost;
return
boost::make_tuple(ref(t0),ref(t1),ref(t2),ref(t3),ref(t4),ref(t5),ref(t6),ref(t7),ref(t8));
}
template
T3,class T4,class T5,class T6,class T7>
boost::tuple
values(T0& t0,T1&
t1,T2& t2,T3&
t3,T4& t4,T5&
t5,T6& t6,T7& t7){
using namespace
boost;
return
boost::make_tuple(ref(t0),ref(t1),ref(t2),ref(t3),ref(t4),ref(t5),ref(t6),ref(t7),ref(t8),ref(t9));
}
template
T3,class T4,class T5,class T6>
boost::tuple
values(T0& t0,T1&
t1,T2& t2,T3&
t3,T4& t4,T5&
t5,T6& t6){
using namespace
boost;
return
boost::make_tuple(ref(t0),ref(t1),ref(t2),ref(t3),ref(t4),ref(t5),ref(t6));
}
template
T3,class T4,class T5>
boost::tuple
values(T0& t0,T1&
t1,T2& t2,T3&
t3,T4& t4,T5& t5){
using namespace
boost;
return
boost::make_tuple(ref(t0),ref(t1),ref(t2),ref(t3),ref(t4),ref(t5));
}
template
T3,class T4>
boost::tuple
values(T0& t0,T1&
t1,T2& t2,T3&
t3,T4& t4){
using namespace
boost;
return
boost::make_tuple(ref(t0),ref(t1),ref(t2),ref(t3),ref(t4));
}
template
T3>
boost::tuple
values(T0& t0,T1&
t1,T2& t2,T3& t3){
using namespace
boost;
return
boost::make_tuple(ref(t0),ref(t1),ref(t2),ref(t3));
}
template
T2>
boost::tuple
values(T0& t0,T1&
t1,T2& t2){
using namespace
boost;
return
boost::make_tuple(ref(t0),ref(t1),ref(t2));
}
template
T1>
boost::tuple
values(T0& t0,T1& t1){
using namespace
boost;
return
boost::make_tuple(ref(t0),ref(t1));
}
template
boost::tuple
values(T0& t0){
using namespace
boost;
return
boost::make_tuple(ref(t0));
}
}; //~end namespace mysql
void main()
{
using namespace
mysql;
try
{
Tiny kk;
Small jj;
//可以绑定封装类型,支持NULL字段语义
C_SQL sql_insert;
sql_insert % "insert into aaa
(tiny_col,short_col) " % values(kk,jj) ;
char aa=0;
short bb=0; //可以绑定原生类型,无法表达NULL字段值
C_SQL sql_select;
sql_select %"select tiny_col,short_col from aaa
where tiny_col=" % aa
%"and short_col=" % bb ;
//连接到数据库
C_CON
con("localhost","root","123","testdb");
//关联SQL语句和连接(预处理SQL语句,因为MySQL的预处理是会话级别的)
con.prepare(&sql_insert);
con.prepare(&sql_select);
//插入操作
kk = 13;
jj = 14;
con.execute(&sql_insert);
//查询操作
aa=13;
bb=14;
con.execute(&sql_select);
C_RS rs(con);
long ll;
Tiny tt; //取结果集,支持数值自动转换
if( rs.next() )
{
rs
>> ignore(1)
>> tt ;
}
}
catch(db_exception& db){
return ;
}
return ;
}