From a7db8380689ba15ce04b8a9a2a719528016f8f41 Mon Sep 17 00:00:00 2001 From: Denes Matetelki Date: Tue, 8 Nov 2011 10:39:47 +0100 Subject: [PATCH] MysqlClient class. TToStr, StrToT templates. CMakeLists update to run the tests. --- CMakeLists.txt | 2 +- build/CMakeLists.txt | 1 - include/ArgParse.hpp | 4 +- include/Common.hpp | 19 ++++++ include/MysqlClient.hpp | 76 +++++++++++++++++++++++ include/Subject.cpp | 3 + src/ArgParse.cpp | 6 +- src/MysqlClient.cpp | 130 ++++++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 10 +++- 9 files changed, 241 insertions(+), 10 deletions(-) create mode 100644 include/MysqlClient.hpp create mode 100644 src/MysqlClient.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 817b343..8daaeff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 2.6) project (CPP_UTILS_LIB) add_subdirectory (build) -add_subdirectory (test) +add_subdirectory (test EXCLUDE_FROM_ALL) find_package(Doxygen) if(DOXYGEN_FOUND) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 5be6579..560b23c 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -4,7 +4,6 @@ project (CPP_UTILS_LIB) set (CXX_FLAGS "-Wall -Wextra -pedantic -Weffc++ -Wshadow " "-ggdb -fprofile-arcs -ftest-coverage") add_definitions( ${CXX_FLAGS} ) -# add_definitions( -DNO_TRACE ) include_directories (../include) aux_source_directory(../src CPP_UTILS_LIB_SOURCES) diff --git a/include/ArgParse.hpp b/include/ArgParse.hpp index cfb310a..93b2a65 100644 --- a/include/ArgParse.hpp +++ b/include/ArgParse.hpp @@ -66,8 +66,8 @@ public: * Shall be cought be the client code! * @throw std::logic_error If the addArgument was bad. */ - void parseArgs(const int argc, - const char* argv[]); + void parseArgs(int argc, + char* argv[]); void parseArgs(const std::list argList); diff --git a/include/Common.hpp b/include/Common.hpp index d9a9217..acb04f8 100644 --- a/include/Common.hpp +++ b/include/Common.hpp @@ -13,6 +13,7 @@ #include // runtime_error #include // ostringstream + const long NANO = 1000000000L; // 10^9 @@ -94,4 +95,22 @@ inline std::string getTime( void ) return ret; } + +template +inline std::string TToStr(const T t) +{ + std::ostringstream oss; + oss << t; + return oss.str(); +} + + +template +inline void StrToT( T &t, const std::string s ) +{ + std::stringstream ss(s); + ss >> t; +} + + #endif // COMMON_HPP diff --git a/include/MysqlClient.hpp b/include/MysqlClient.hpp new file mode 100644 index 0000000..f76c551 --- /dev/null +++ b/include/MysqlClient.hpp @@ -0,0 +1,76 @@ +#ifndef MYSQL_CLIENT_HPP +#define MYSQL_CLIENT_HPP + +#include + +#include +#include + +class MysqlClient +{ + +public: + + /** + * For more details about the params, + * check the documentation of mysql_real_connect + * + * @note Call init_client_errs() / finish_client_errs() before / after. + * + * @param host May be either a host name or an IP address. + * If host is NULL or the string "localhost", + * a connection to the local host is assumed. + * @param user If user is NULL or the empty string "", + * the current user is assumed. + * @param passwd If passwd is NULL, only entries in the user table + * for the user that have a blank (empty) password field + * are checked for a match. + * @param db If db is not NULL, the connection sets the default + * database to this value. + * @param port If port is not 0, the value is used as the port number + * for the TCP/IP connection. Note that the host parameter determines + * the type of the connection. + * @param unix_socket If unix_socket is not NULL, the string specifies + * the socket or named pipe that should be used. Note that the host parameter + * determines the type of the connection. + * @param clientflag Usually 0, but can be set to a combination + * of flags to enable certain features. + */ + MysqlClient ( const char *host = NULL, + const char *user = NULL, + const char *passwd = NULL, + const char *db = NULL, + unsigned int port = 0, + const char *unix_socket = NULL, + unsigned long clientflag = 0 ); + + ~MysqlClient(); + + bool connect(); + + bool querty(const std::string queryLine, + std::list &result); + +private: + + MysqlClient(const MysqlClient&); + MysqlClient& operator=(const MysqlClient&); + + /// @todo optimize this + void queryResultToStringList(MYSQL_RES *res_set, + std::list &result); + + const char *m_host; + const char *m_user; + const char *m_passwd; + const char *m_db; + unsigned int m_port; + const char *m_unix_socket; + unsigned long m_clientflag; + + bool m_connected; + MYSQL *m_connection; +}; + + +#endif // MYSQL_CLIENT_HPP diff --git a/include/Subject.cpp b/include/Subject.cpp index 59057e7..9a79a36 100644 --- a/include/Subject.cpp +++ b/include/Subject.cpp @@ -11,11 +11,14 @@ public: virtual ~Subject(); + /// @todo listen only to aspect? virtual void attach( Observer* ); virtual void detach( Observer* ); virtual void notify(); private: + + /// @todo list can be a priority queue std::list< Observer* > m_observers; }; diff --git a/src/ArgParse.cpp b/src/ArgParse.cpp index 309418a..0c586f1 100644 --- a/src/ArgParse.cpp +++ b/src/ArgParse.cpp @@ -23,7 +23,7 @@ ArgParse::ArgParse(const std::string description, , m_params() { if (addHelp) - addArgument("-h,--help", "Prints this help message"); + addArgument("-h, --help", "Prints this help message"); } @@ -68,8 +68,8 @@ void ArgParse::addArgument(const std::string arg, } -void ArgParse::parseArgs(const int argc, - const char* argv[]) +void ArgParse::parseArgs(int argc, + char* argv[]) { std::list argList; for (int i = 0; i < argc; ++i ) diff --git a/src/MysqlClient.cpp b/src/MysqlClient.cpp new file mode 100644 index 0000000..ddcf291 --- /dev/null +++ b/src/MysqlClient.cpp @@ -0,0 +1,130 @@ +#include "MysqlClient.hpp" + +#include + +#include "Logger.hpp" +#include "Common.hpp" + + +MysqlClient::MysqlClient( const char *host, + const char *user, + const char *passwd, + const char *db, + unsigned int port, + const char *unix_socket, + unsigned long clientflag ) + : m_host(host) + , m_user(user) + , m_passwd(passwd) + , m_db(db) + , m_port(port) + , m_unix_socket(unix_socket) + , m_clientflag(clientflag) + , m_connected(false) + , m_connection(0) +{ + TRACE; +} + + +MysqlClient::~MysqlClient() +{ + TRACE; + mysql_close(m_connection); +} + + +bool +MysqlClient::connect() +{ + TRACE; + m_connection = mysql_init(NULL); + + if ( m_connection == NULL ) { + LOG ( Logger::ERR, std::string("MySQL Initialization Failed!").c_str()); + return false; + } + + m_connection = mysql_real_connect( m_connection, + m_host, + m_user, + m_passwd, + m_db, + m_port, + m_unix_socket, + m_clientflag ); + + if ( m_connection == NULL ) { + LOG ( Logger::ERR, std::string("MySQL Connection Failed! "). + append(mysql_error(m_connection)).c_str()); + return false; + } + + LOG ( Logger::DEBUG, + std::string("MySQL client connected to ").append(m_host ? m_host : "NULL") + .append(", on port: ").append(TToStr(m_port)) + .append(", as user: ").append(m_user ? m_user : "NULL") + .append(", with passwd: ").append(m_passwd ? m_passwd : "NULL") + .append(", to DB: ").append(m_db ? m_db : "NULL") + .append(", with unix_socket: ").append(m_unix_socket ? m_unix_socket : "NULL") + .append(", and flags: ").append(TToStr(m_clientflag)) + .c_str() ); + + m_connected = true; + return true; +} + + +bool +MysqlClient::querty(const std::string queryLine, + std::list &result) +{ + TRACE; + + if ( !m_connected && !connect() ) + return false; + + if ( mysql_query(m_connection,queryLine.c_str()) != 0 ) { + LOG ( Logger::ERR, std::string("MySQL query failed! "). + append(mysql_error(m_connection)).c_str()); + return false; + } + + MYSQL_RES *res_set; + res_set = mysql_store_result(m_connection); + + if ( res_set == NULL ) { + LOG ( Logger::ERR, std::string("MySQL store result failed! "). + append(mysql_error(m_connection)).c_str()); + return false; + } + + queryResultToStringList( res_set, result); + + mysql_free_result( res_set ); + return true; +} + +void +MysqlClient::queryResultToStringList(MYSQL_RES *res_set, + std::list &result) +{ + unsigned int numrows = mysql_num_rows(res_set); + LOG( Logger::DEBUG, std::string("MySQL query returned number of rows: "). + append(TToStr(numrows)).c_str()); + + unsigned int num_fields = mysql_num_fields(res_set); + MYSQL_ROW row; + + while ((row = mysql_fetch_row(res_set)) != NULL) { + std::string rowString; + for( unsigned int i = 0; i < num_fields; ++i ) { + rowString.append(row[i] ? row[i] : "NULL"); + rowString.append(","); + } + if (num_fields > 0) + rowString.erase(rowString.end()-1); + + result.push_back(rowString); + } +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 541227c..32f41e6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,7 +2,6 @@ set (CXX_FLAGS "-Wall -Wextra -pedantic -Weffc++ -Wshadow " "-ggdb -fprofile-arcs -ftest-coverage --std=c++0x " ) add_definitions( ${CXX_FLAGS} ) -# add_definitions( -DNO_TRACE ) find_package(CxxTest) @@ -12,7 +11,7 @@ if(CXXTEST_FOUND) include_directories(${CXXTEST_INCLUDE_DIR} ../include) enable_testing() - CXXTEST_ADD_TEST(test + CXXTEST_ADD_TEST(testCppUtils generated_main.cpp Fixture.hpp @@ -30,5 +29,10 @@ if(CXXTEST_FOUND) # test_Common.hpp # test_TimerThreadMultimap.hpp ) - target_link_libraries(test CppUtils gcov) + target_link_libraries(testCppUtils CppUtils gcov) endif() + +add_custom_target( test + COMMAND ./run_test.sh ./testCppUtils + DEPENDS testCppUtils +) \ No newline at end of file