Introduction
This article present a lean C++ wrapper of mySQL client. All of the functions are defined in two header files. Users can build the file with mySQL C API library and header files of boost::shared_ptr
which is used to manage the MYSQL connection and result set.
Using the code
The classes diagram of the mySQL client wrapper is shown as the following diagram.
The structure is pretty simple. The only special note is the member function CMysqlConn::Query
. The function has a template parameter 'ProcessQuery
' which is a 'policy
' class to cope with the concreted client requirements of using the API. Different clients have different purposes of querying a database. Some clients want to fetch the data that meets certain predications. Some clients want to insert and update records in which no return data is required. Other clients may just fetch the ID type of data that meets given 'where' clause. Inspired by the policy based solution addressed in Andrei Alexandrescu's "Modern C++ design", the 'Query
' member function uses the template solution to separate the usage policy from the general query algorithm.
I have defined three policy classes for the CMysqlConn::Query
. Here are the use cases.
- Query DB that needs returned data
CMysqlSet rset=conn.Query<WithData>("select * from mytable");
- Query DB that does not need returned data
bool ret =conn.Query<NoData>("insert into mytable values
(5000, 'testing message')");
- Query DB that only fetches one value
pair<bool, string> value=conn.Query<CheckOneRecord>
("select field from mytable where errorcode='2005'");
Users can define their own policy class by following this sample:
struct Nodata
{
typedef boolReturnType;
static ReturnType ReturnInFail() {return false;}
static ReturnType DeepQuery(ConnPtr ptr) {return true;}
};
Here is the sample code of using this wrapper:
int Test()
{
string query="select * from mytable";
CMysqlConn conn("myhost","mytable", "login","password");
if (conn)
{
CMysqlSet rset=conn.Query<WithData>(query);
if (rset)
{
cout<<"I got a result";
unsigned size=rset.NumberOfRecords();
for (unsigned int i=0;i<size; i++){
CMysqlRow row=rset.GetNextRow();
if (row)
{
for (unsigned int j=0; j<row.NumberOfFields();j++)
{
cout<<row[j];
}
cout<<endl;
}
}
}
cout<<"Last error is
"<<conn.GetLastfiled1()<<":"<<conn.GetLastErrorString()<<endl;
string updateQuery="insert into mytable values (5000, 'testing message')";
conn.Query<NoData>(updateQuery);
cout<<"query single data..."<<endl;
pair<bool, string> value=conn.Query<CheckOneRecord>
("select filed1s from mytable where filed1='2005'");
if (value.first)
{
cout<<"get value of "<<value.second<<endl;
}
}
return 0;
}