Changeset - b9fc585e2628
[Not reviewed]
0 2 0
HanzZ - 14 years ago 2011-08-12 18:32:53
hanzz.k@gmail.com
print mysql errors
2 files changed with 5 insertions and 0 deletions:
0 comments (0 inline, 0 general)
include/transport/mysqlbackend.h
Show inline comments
 
@@ -66,77 +66,79 @@ class MySQLBackend : public StorageBackend
 
		/// Changes users online state variable in database.
 
		/// \param id id of user - UserInfo.id
 
		/// \param online online state
 
		void setUserOnline(long id, bool online);
 

	
 
		/// Removes user and all connected data from database.
 
		/// \param id id of user - UserInfo.id
 
		/// \return true if user has been found in database and removed
 
		bool removeUser(long id);
 

	
 
		/// Returns JIDs of all buddies in user's roster.
 
		/// \param id id of user - UserInfo.id
 
		/// \param roster string list used to store user's roster
 
		/// \return true if user has been found in database and roster has been fetched
 
		bool getBuddies(long id, std::list<BuddyInfo> &roster);
 

	
 
		long addBuddy(long userId, const BuddyInfo &buddyInfo);
 

	
 
		void updateBuddy(long userId, const BuddyInfo &buddyInfo);
 
		void removeBuddy(long id) {}
 

	
 
		void getUserSetting(long userId, const std::string &variable, int &type, std::string &value);
 
		void updateUserSetting(long userId, const std::string &variable, const std::string &value);
 

	
 
		void beginTransaction();
 
		void commitTransaction();
 

	
 
	private:
 
		bool exec(const std::string &query);
 

	
 
		class Statement {
 
			public:
 
				Statement(MYSQL *conn, const std::string &format, const std::string &statement);
 
				~Statement();
 

	
 
				bool execute();
 

	
 
				// Pushes new data used as input for the statement.
 
				template <typename T>
 
				Statement& operator << (const T& t);
 

	
 
				Statement& operator << (const std::string& str);
 

	
 
				// Pulls fetched data by previous execute(); call.
 
				template <typename T>
 
				Statement& operator >> (T& t);
 
			private:
 
				MYSQL_STMT *m_stmt;
 
				MYSQL *m_conn;
 
				std::vector<MYSQL_BIND> m_params;
 
				int m_resultOffset;
 
				int m_offset;
 
				int m_error;
 
				std::string m_string;
 
		};
 

	
 
		MYSQL m_conn;
 
		Config *m_config;
 
		std::string m_prefix;
 

	
 
		// statements
 
// 		MYSQL_STMT *m_setUser;
 
		Statement * m_setUser;
 
		MYSQL_STMT *m_getUser;
 
		MYSQL_STMT *m_getUserSetting;
 
		MYSQL_STMT *m_setUserSetting;
 
		MYSQL_STMT *m_updateUserSetting;
 
		MYSQL_STMT *m_removeUser;
 
		MYSQL_STMT *m_removeUserBuddies;
 
		MYSQL_STMT *m_removeUserSettings;
 
		MYSQL_STMT *m_removeUserBuddiesSettings;
 
		MYSQL_STMT *m_addBuddy;
 
		MYSQL_STMT *m_updateBuddy;
 
		MYSQL_STMT *m_updateBuddySetting;
 
		MYSQL_STMT *m_getBuddies;
 
		MYSQL_STMT *m_getBuddiesSettings;
 
};
 

	
 
}
src/mysqlbackend.cpp
Show inline comments
 
@@ -33,166 +33,169 @@ using namespace log4cxx;
 

	
 
// Prepare the SQL statement
 
#define PREP_STMT(sql, str) \
 
	sql = mysql_stmt_init(&m_conn);\
 
	if (mysql_stmt_prepare(sql, std::string(str).c_str(), std::string(str).size())) {\
 
		LOG4CXX_ERROR(logger, str << " " << mysql_error(&m_conn)); \
 
		return false; \
 
	}
 

	
 
// Finalize the prepared statement
 
#define FINALIZE_STMT(prep) \
 
	if(prep != NULL) { \
 
		mysql_stmt_close(prep); \
 
	}
 
	
 
#define BEGIN(STATEMENT, SIZE) 	MYSQL_BIND STATEMENT##_bind[SIZE]; \
 
							memset(STATEMENT##_bind, 0, sizeof(STATEMENT##_bind)); \
 
							int STATEMENT##_id = 1;\
 
							int STATEMENT##_id_get = 0;\
 
							(void)STATEMENT##_id_get;
 

	
 
#define BIND_INT(STATEMENT, VARIABLE) STATEMENT##_bind[STATEMENT##_id].buffer_type= MYSQL_TYPE_LONG;\
 
							STATEMENT##_bind[STATEMENT##_id].buffer= (char *)&VARIABLE;\
 
							STATEMENT##_bind[STATEMENT##_id].is_null= 0;\
 
							STATEMENT##_bind[STATEMENT##_id++].length= 0;
 
#define BIND_STR(STATEMENT, VARIABLE) STATEMENT##_bind[STATEMENT##_id].buffer_type= MYSQL_TYPE_STRING;\
 
							STATEMENT##_bind[STATEMENT##_id].buffer= VARIABLE.c_str();\
 
							STATEMENT##_bind[STATEMENT##_id].buffer_length= STRING_SIZE;\
 
							STATEMENT##_bind[STATEMENT##_id].is_null= 0;\
 
							STATEMENT##_bind[STATEMENT##_id++].length= VARIABLE.size();
 
#define RESET_GET_COUNTER(STATEMENT)	STATEMENT##_id_get = 0;
 
#define GET_INT(STATEMENT)	sqlite3_column_int(STATEMENT, STATEMENT##_id_get++)
 
#define GET_STR(STATEMENT)	(const char *) sqlite3_column_text(STATEMENT, STATEMENT##_id_get++)
 
#define EXECUTE_STATEMENT(STATEMENT, NAME) if (mysql_stmt_bind_param(STATEMENT, STATEMENT##_bind)) { \
 
		LOG4CXX_ERROR(logger, NAME << " " << mysql_error(&m_conn)); \
 
	} \
 
	if (mysql_stmt_execute(STATEMENT)) { \
 
		LOG4CXX_ERROR(logger, NAME << " " << mysql_error(&m_conn)); \
 
	}
 

	
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
static LoggerPtr logger = Logger::getLogger("MySQLBackend");
 

	
 
MySQLBackend::Statement::Statement(MYSQL *conn, const std::string &format, const std::string &statement) {
 
	m_resultOffset = -1;
 
	m_conn = conn;
 
	m_offset = 0;
 
	m_string = statement;
 
	m_stmt = mysql_stmt_init(conn);
 
	if (mysql_stmt_prepare(m_stmt, statement.c_str(), statement.size())) {
 
		LOG4CXX_ERROR(logger, statement << " " << mysql_error(conn));
 
		return;
 
	}
 

	
 
	for (int i = 0; i < format.length(); i++) {
 
		switch (format.at(i)) {
 
			case 's':
 
				m_params.resize(m_params.size() + 1);
 
				memset(&m_params.back(), 0, sizeof(MYSQL_BIND));
 

	
 
				m_params.back().buffer_type= MYSQL_TYPE_STRING;
 
				m_params.back().buffer= (char *) malloc(sizeof(char) * 4096);
 
				m_params.back().buffer_length= 4096;
 
				m_params.back().is_null= 0;
 
				m_params.back().length= (unsigned long *) malloc(sizeof(unsigned long));
 
				break;
 
			case 'i':
 
				m_params.resize(m_params.size() + 1);
 
				memset(&m_params.back(), 0, sizeof(MYSQL_BIND));
 

	
 
				m_params.back().buffer_type= MYSQL_TYPE_LONG;
 
				m_params.back().buffer= (unsigned long *) malloc(sizeof(unsigned long));
 
				m_params.back().is_null= 0;
 
				m_params.back().length= (unsigned long *) malloc(sizeof(unsigned long));
 
				break;
 
			case 'b':
 
				m_params.resize(m_params.size() + 1);
 
				memset(&m_params.back(), 0, sizeof(MYSQL_BIND));
 

	
 
				m_params.back().buffer_type= MYSQL_TYPE_TINY;
 
				m_params.back().buffer= (bool *) malloc(sizeof(bool));
 
				m_params.back().is_null= 0;
 
				m_params.back().length= (unsigned long *) malloc(sizeof(unsigned long));
 
				break;
 
// 			case 'b':
 
// 				m_params.push_back(NULL);
 
// 				break;
 
			case '|':
 
				m_resultOffset = i;
 
				break;
 
		}
 
	}
 

	
 
	if (m_resultOffset < 0)
 
		m_resultOffset = format.size();
 

	
 
	if (mysql_stmt_bind_param(m_stmt, &m_params.front())) {
 
		LOG4CXX_ERROR(logger, statement << " " << mysql_error(conn));
 
	}
 
}
 

	
 
MySQLBackend::Statement::~Statement() {
 
	for (int i = 0; i < m_params.size(); i++) {
 
		free(m_params[i].buffer);
 
		free(m_params[i].length);
 
	}
 
	FINALIZE_STMT(m_stmt);
 
}
 

	
 
bool MySQLBackend::Statement::execute() {
 
	// If statement has some input and doesn't have any output, we have
 
	// to clear the offset now, because operator>> will not be called.
 
	if (m_resultOffset != 0 && m_offset + 1 == m_params.size()) {
 
		m_offset = 0;
 
	}
 

	
 
	if (mysql_stmt_execute(m_stmt)) {
 
		LOG4CXX_ERROR(logger, m_string << " " << mysql_error(m_conn));
 
		return false;
 
	}
 
	return true;
 
}
 

	
 
template <typename T>
 
MySQLBackend::Statement& MySQLBackend::Statement::operator << (const T& t) {
 
	if (m_offset >= m_resultOffset)
 
		return *this;
 
	T *data = (T *) m_params[m_offset].buffer;
 
	*data = t;
 

	
 
	LOG4CXX_INFO(logger, "adding " << m_offset << ":" << t);
 
	m_offset++;
 
	return *this;
 
}
 

	
 
MySQLBackend::Statement& MySQLBackend::Statement::operator << (const std::string& str) {
 
	if (m_offset >= m_resultOffset)
 
		return *this;
 
	LOG4CXX_INFO(logger, "adding " << m_offset << ":" << str << "(" << str.size() << ")");
 
	strncpy((char*) m_params[m_offset].buffer, str.c_str(), 4096);
 
	*m_params[m_offset].length = str.size();
 
	m_offset++;
 
	return *this;
 
}
 

	
 
template <typename T>
 
MySQLBackend::Statement& MySQLBackend::Statement::operator >> (T& t) {
 
	if (m_offset < m_resultOffset)
 
		return *this;
 

	
 
	std::swap(t, *(T *) m_params[m_offset]);
 
	if (++m_offset == m_params.size())
 
		m_offset = 0;
 
	return *this;
 
}
 

	
 
MySQLBackend::MySQLBackend(Config *config) {
 
	m_config = config;
 
	mysql_init(&m_conn);
 
	m_prefix = CONFIG_STRING(m_config, "database.prefix");
 
}
 

	
 
MySQLBackend::~MySQLBackend(){
 
// 	FINALIZE_STMT(m_setUser);
 
	delete m_setUser;
 
	FINALIZE_STMT(m_getUser);
0 comments (0 inline, 0 general)