C 访问MySql 接口封装_学习笔记:MySQL C API封装练习

#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 ;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值