Click here to Skip to main content
15,896,269 members
Articles / Database Development / MySQL

Lean and extensible mySQL C++ wrapper

Rate me:
Please Sign up or sign in to vote.
3.76/5 (9 votes)
26 Feb 20071 min read 44.6K   2K   32  
An article on a lean (2 header files) C++ template class that provides mySQL query
/********************************************************************
 	created:  2/7/2007  
	filename: mysql_client_simple_conn.h
  	contact:  hongpinglin@hotmail.com
	
	purpose:	
*********************************************************************/
#ifndef _mysql_client_simple_conn_h_2_7_2007
#define _mysql_client_simple_conn_h_2_7_2007

#include <string>
#include <sstream>
#include <stdexcept> 

#include <boost/shared_ptr.hpp>
#include <mysql/mysql.h>

#include "mysql_client_simple_private.h"

namespace sbs_mysql_simple
{

	typedef boost::shared_ptr<MYSQL> ConnPtr;
	typedef boost::shared_ptr<MYSQL_RES> ResPtr;

	class CMysqlSet;

//
// The thin wrapper of MYSQL_ROW
//
	class CMysqlRow
	{
	public:

		friend class CMysqlSet;


		inline operator bool () const 
		{
			return m_ptr&&m_row;
		}


		string operator [] (unsigned int index)
		{
 			if (index >= m_nFields)
				throw std::logic_error ("The invalid field index ");
			return string(m_row[index]);
		}
 
 
		unsigned int NumberOfFields() const {return  m_nFields;}

	private:
		CMysqlRow():m_row(NULL),m_nFields(0){}

		CMysqlRow (ResPtr ptr, unsigned int nfields)
			:m_ptr(ptr),m_row(NULL),m_nFields(nfields)
		{
			if (m_ptr)
			{
				m_row=mysql_fetch_row(m_ptr.get());
			}
		}

 
	private:

		ResPtr m_ptr;
 		MYSQL_ROW m_row;
		size_t m_nFields;
	};

//
// The thin wrapper of MYSQL_RES
//

	class CMysqlSet
	{
	public:

		CMysqlSet():m_rowCount(0),m_nFields(0){}


		CMysqlSet(MYSQL_RES* res)
			:m_ptr(res,myprivate::CloseResultSet),m_rowCount(0),m_nFields(0)
		{
			if (m_ptr)
			{
				m_rowCount=mysql_num_rows(m_ptr.get());
				m_nFields=mysql_num_fields(m_ptr.get());
			}
		}

 
		
		inline operator bool () const {return m_ptr;}

		size_t NumberOfRecords() const {return m_rowCount;}

		unsigned int NumberOfFields() const {return  m_nFields;}

		CMysqlRow GetNextRow()
		{
			  return CMysqlRow(m_ptr,NumberOfFields());
		}

	private:
		
		ResPtr m_ptr;
		size_t m_rowCount;
		size_t m_nFields;
		
	};


	//
	// Declare and define the ProcessQueryPolicy
	//
	//

	//
	// The policy for the not data query such as "update", "insert" statement
	//
	//
	struct NoData
	{
		typedef bool ReturnType;
		static ReturnType ReturnInFail()  {return false;}
		static ReturnType DeepQuery(ConnPtr ptr) {return true;}
	};


	//
	// The policy for the query with entire dataset
	//
	struct WithData
	{
		typedef CMysqlSet ReturnType;

		static ReturnType ReturnInFail()  {return CMysqlSet();}
		
		static ReturnType DeepQuery(ConnPtr ptr) 
		{
			MYSQL_RES* res_set=mysql_store_result(ptr.get());
			if (!res_set) return CMysqlSet();
			return CMysqlSet(res_set);
		}
	};


	//
	// The policy to check one field of the first record
	// which is normally used in checking if the valid record exist
	//
	struct CheckOneRecord
	{
		typedef pair<bool, string> ReturnType;

		static ReturnType ReturnInFail()  {return ReturnType(false,"no record");}
		
		static ReturnType DeepQuery(ConnPtr ptr) 
		{
			MYSQL_RES* res_set=mysql_store_result(ptr.get());
			if (!res_set) return ReturnType(false,"no record");
			
			CMysqlSet rset(res_set);

			size_t size=rset.NumberOfRecords();

			if (size)
			{
				CMysqlRow row=rset.GetNextRow();

				if (row.NumberOfFields()>0)
				{
					string value=row[0];
					return ReturnType(true,value);
				}
			}

			return ReturnType(false,"no record");
		}
	};





	
 //
// The thin wrapper of MYSQL connection
//
	class CMysqlConn 
	{
	public:

		CMysqlConn(){}

		CMysqlConn (string const& hostName,  
					string const& dbName, 
					string const&username, 
					string const& password)
		{
			Connect(hostName,dbName,username,password);
		}

		bool Connect (string const& hostName,  
						string const& dbName,  
						string const&username, 
						string const& password)
		{
			bool ret=true;
			m_ptr.reset();
 			try
			{
				m_ptr=myprivate::
						GetConnection(hostName,dbName,username,password);
			}
			catch (runtime_error & e)
			{
				cerr<<e.what()<<endl;
				ret=false;
			}
			return ret;
		}


 		inline operator bool() const {return m_ptr;}


 		template <typename ProcessQuery>
			typename ProcessQuery::ReturnType Query (string const& sql)
		{
 			typedef typename ProcessQuery::ReturnType ReturnType;

			if (!m_ptr)
			{
 				return ProcessQuery::ReturnInFail();
			}
			
 			cerr<<"Query '"<<sql<<"' ";
 
			if (mysql_query(m_ptr.get(),sql.c_str())!=0)
			{
 					cerr<<"Fail "
					<<GetLastErrorCode()
					<<":"
					<<GetLastErrorString()
					<<" - for the query of '"
 					<<sql
					<<"'"
					<<endl;
  				return ProcessQuery::ReturnInFail();
			}
			else
			{
				cerr<<"Success."<<endl;
			}
 
 			return ProcessQuery::DeepQuery(m_ptr);
		}

 


		int GetLastErrorCode() const 
		{return myprivate::GetLastErrorCode(m_ptr);}
		
		string GetLastErrorString() const
		{return myprivate::GetLastErrorString(m_ptr);}

 		
	private:
 		ConnPtr m_ptr;
	};
};


#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect
United States United States
Richard Lin is senior software engineer of in Silicon Valley.

Richard Lin was born in Beijing and came to US in the fall of 1995. He began his first software career in bay area of California in 1997. He has worked for many interesting projects including manufacturing testing systems, wireless AP firmware and applications, email anti-virus system and personal firewalls. He loves playing go (WeiQi in Chinese) and soccer in his spare time. He has a beautiful wife and a cute daughter and enjoys his life in San Jose of California.

Comments and Discussions