From f268aec98176049136bceb2741f3615841e5c516 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 23 Dec 2015 23:15:18 +0000 Subject: MySQL files prefixed with my- --- libmysqlpp/Jamfile.jam | 4 +- libmysqlpp/column.cpp | 118 ---------------- libmysqlpp/column.h | 42 ------ libmysqlpp/command.cpp | 174 ------------------------ libmysqlpp/command.h | 47 ------- libmysqlpp/connection.cpp | 269 ------------------------------------- libmysqlpp/connection.h | 47 ------- libmysqlpp/error.cpp | 29 ---- libmysqlpp/error.h | 24 ---- libmysqlpp/mock.cpp | 26 ---- libmysqlpp/mock.h | 22 --- libmysqlpp/modifycommand.cpp | 30 ----- libmysqlpp/modifycommand.h | 25 ---- libmysqlpp/my-column.cpp | 118 ++++++++++++++++ libmysqlpp/my-column.h | 42 ++++++ libmysqlpp/my-command.cpp | 174 ++++++++++++++++++++++++ libmysqlpp/my-command.h | 47 +++++++ libmysqlpp/my-connection.cpp | 269 +++++++++++++++++++++++++++++++++++++ libmysqlpp/my-connection.h | 47 +++++++ libmysqlpp/my-error.cpp | 29 ++++ libmysqlpp/my-error.h | 24 ++++ libmysqlpp/my-mock.cpp | 26 ++++ libmysqlpp/my-mock.h | 22 +++ libmysqlpp/my-modifycommand.cpp | 30 +++++ libmysqlpp/my-modifycommand.h | 25 ++++ libmysqlpp/my-selectcommand.cpp | 99 ++++++++++++++ libmysqlpp/my-selectcommand.h | 26 ++++ libmysqlpp/selectcommand.cpp | 99 -------------- libmysqlpp/selectcommand.h | 26 ---- libmysqlpp/unittests/testmysql.cpp | 2 +- 30 files changed, 981 insertions(+), 981 deletions(-) delete mode 100644 libmysqlpp/column.cpp delete mode 100644 libmysqlpp/column.h delete mode 100644 libmysqlpp/command.cpp delete mode 100644 libmysqlpp/command.h delete mode 100644 libmysqlpp/connection.cpp delete mode 100644 libmysqlpp/connection.h delete mode 100644 libmysqlpp/error.cpp delete mode 100644 libmysqlpp/error.h delete mode 100644 libmysqlpp/mock.cpp delete mode 100644 libmysqlpp/mock.h delete mode 100644 libmysqlpp/modifycommand.cpp delete mode 100644 libmysqlpp/modifycommand.h create mode 100644 libmysqlpp/my-column.cpp create mode 100644 libmysqlpp/my-column.h create mode 100644 libmysqlpp/my-command.cpp create mode 100644 libmysqlpp/my-command.h create mode 100644 libmysqlpp/my-connection.cpp create mode 100644 libmysqlpp/my-connection.h create mode 100644 libmysqlpp/my-error.cpp create mode 100644 libmysqlpp/my-error.h create mode 100644 libmysqlpp/my-mock.cpp create mode 100644 libmysqlpp/my-mock.h create mode 100644 libmysqlpp/my-modifycommand.cpp create mode 100644 libmysqlpp/my-modifycommand.h create mode 100644 libmysqlpp/my-selectcommand.cpp create mode 100644 libmysqlpp/my-selectcommand.h delete mode 100644 libmysqlpp/selectcommand.cpp delete mode 100644 libmysqlpp/selectcommand.h diff --git a/libmysqlpp/Jamfile.jam b/libmysqlpp/Jamfile.jam index b0085a8..5bb9c2e 100644 --- a/libmysqlpp/Jamfile.jam +++ b/libmysqlpp/Jamfile.jam @@ -7,7 +7,7 @@ lib boost_date_time ; lib boost_system ; lib dbpp-mysql : - [ glob *.cpp ] : + [ glob my-*.cpp ] : ..//glibmm mysqlclient dbppcore @@ -24,5 +24,5 @@ lib dbpp-mysql : build-project unittests ; -package.install install : . : : dbpp-mysql : [ glob *.h ] ; +package.install install : . : : dbpp-mysql : [ glob my-*.h ] ; diff --git a/libmysqlpp/column.cpp b/libmysqlpp/column.cpp deleted file mode 100644 index 7ff365a..0000000 --- a/libmysqlpp/column.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "column.h" -#include "selectcommand.h" -#include "error.h" -#include -#include - -MySQL::ColumnBase::ColumnBase(const char * name, unsigned int i) : - DB::Column(name, i) -{ -} - -bool -MySQL::ColumnBase::isNull() const -{ - return is_null; -} - -void -MySQL::ColumnBase::rebind(DB::Command *, unsigned int) const -{ - throw Error("Not supported"); -} - -MySQL::StringColumn::StringColumn(const char * name, unsigned int field, MYSQL_BIND * b, unsigned int len) : - ColumnBase(name, field), - value(new char[len]) -{ - b->is_null = &is_null; - b->buffer_type = MYSQL_TYPE_STRING; - b->is_unsigned = 0; - b->buffer = value; - b->buffer_length = len; - b->length = &length; -} -MySQL::StringColumn::~StringColumn() -{ - delete[] value; -} -void -MySQL::StringColumn::apply(DB::HandleField & h) const -{ - if (is_null) { - h.null(); - } - else { - h.string(value, length); - } -} -MySQL::NullColumn::NullColumn(const char * name, unsigned int field, MYSQL_BIND * b) : - ColumnBase(name, field) -{ - b->is_null = &is_null; - b->buffer_type = MYSQL_TYPE_NULL; - b->buffer = NULL; - b->buffer_length = 0; -} -void -MySQL::NullColumn::apply(DB::HandleField & h) const -{ - h.null(); -} - -namespace MySQL { - template Column::Column(const char * name, unsigned int field, MYSQL_BIND * b) : - ColumnBase(name, field) - { - b->is_null = &is_null; - b->buffer_type = MT; - b->is_unsigned = 0; - b->buffer = &value; - b->buffer_length = sizeof(T); - } - - template <> void Column::apply(DB::HandleField & h) const - { - if (is_null) { - h.null(); - } - else { - h.integer(value); - } - } - template <> void Column::apply(DB::HandleField & h) const - { - if (is_null) { - h.null(); - } - else { - h.floatingpoint(value); - } - } - template <> void Column::apply(DB::HandleField & h) const - { - if (is_null) { - h.null(); - } - else { - h.timestamp(boost::posix_time::ptime( - boost::gregorian::date(value.year, value.month, value.day), - boost::posix_time::time_duration(value.hour, value.minute, value.second) + boost::posix_time::microseconds(value.second_part))); - } - } - template <> void Column::apply(DB::HandleField & h) const - { - if (is_null) { - h.null(); - } - else { - h.interval( - boost::posix_time::time_duration(value.hour, value.minute, value.second) + boost::posix_time::microseconds(value.second_part)); - } - } - - template class Column; - template class Column; - template class Column; - template class Column; -} diff --git a/libmysqlpp/column.h b/libmysqlpp/column.h deleted file mode 100644 index 38f4f39..0000000 --- a/libmysqlpp/column.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef MY_COLUMN_H -#define MY_COLUMN_H - -#include -#include - -namespace MySQL { - class SelectCommand; - class ColumnBase : public DB::Column { - public: - ColumnBase(const char * name, unsigned int field); - - bool isNull() const; - void rebind(DB::Command *, unsigned int) const; - protected: - my_bool is_null; - long unsigned int length; - friend class SelectCommand; - }; - class StringColumn : public ColumnBase { - public: - StringColumn(const char * name, unsigned int field, MYSQL_BIND * b, unsigned int len); - ~StringColumn(); - void apply(DB::HandleField &) const; - char * value; - long unsigned int length; - }; - class NullColumn : public ColumnBase { - public: - NullColumn(const char * name, unsigned int field, MYSQL_BIND * b); - void apply(DB::HandleField &) const; - }; - template class Column : public ColumnBase { - public: - Column(const char * name, unsigned int field, MYSQL_BIND * b); - void apply(DB::HandleField & h) const; - T value; - }; -} - -#endif - diff --git a/libmysqlpp/command.cpp b/libmysqlpp/command.cpp deleted file mode 100644 index 51db90f..0000000 --- a/libmysqlpp/command.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "command.h" -#include "connection.h" -#include -#include - -MySQL::Command::Command(const Connection * conn, const std::string & sql) : - DB::Command(sql), - c(conn), - stmt(mysql_stmt_init(&conn->conn)), - paramsNeedBinding(false) -{ - if (!stmt) { - throw Error(mysql_error(&conn->conn)); - } - if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length())) { - throw Error(mysql_stmt_error(stmt)); - } - binds.resize(mysql_stmt_param_count(stmt)); - if (binds.size()) { - paramsNeedBinding = true; - for (Binds::iterator i = binds.begin(); i != binds.end(); ++i) { - memset(&*i, 0, sizeof(MYSQL_BIND)); - i->buffer_type = MYSQL_TYPE_NULL; - } - } -} - -MySQL::Command::~Command() -{ - for (Binds::const_iterator i = binds.begin(); i != binds.end(); ++i) { - free(i->buffer); - } - mysql_stmt_close(stmt); -} - -void * -MySQL::Command::realloc(void * buffer, size_t size) -{ - void * newBuffer = ::realloc(buffer, size); - if (buffer != newBuffer) { - paramsNeedBinding = true; - } - return newBuffer; -} - -void -MySQL::Command::bindParamI(unsigned int n, int v) -{ - binds[n].buffer_type = MYSQL_TYPE_LONG; - binds[n].buffer = realloc(binds[n].buffer, sizeof(int)); - *static_cast(binds[n].buffer) = v; - binds[n].is_unsigned = 0; -} -void -MySQL::Command::bindParamI(unsigned int n, long int v) -{ - binds[n].buffer_type = MYSQL_TYPE_LONGLONG; - binds[n].buffer = realloc(binds[n].buffer, sizeof(long long int)); - *static_cast(binds[n].buffer) = v; - binds[n].is_unsigned = 0; -} -void -MySQL::Command::bindParamI(unsigned int n, long long int v) -{ - binds[n].buffer_type = MYSQL_TYPE_LONGLONG; - binds[n].buffer = realloc(binds[n].buffer, sizeof(long long int)); - *static_cast(binds[n].buffer) = v; - binds[n].is_unsigned = 0; -} -void -MySQL::Command::bindParamI(unsigned int n, unsigned int v) -{ - binds[n].buffer_type = MYSQL_TYPE_LONG; - binds[n].buffer = realloc(binds[n].buffer, sizeof(int)); - *static_cast(binds[n].buffer) = v; - binds[n].is_unsigned = 1; -} -void -MySQL::Command::bindParamI(unsigned int n, long unsigned int v) -{ - binds[n].buffer_type = MYSQL_TYPE_LONGLONG; - binds[n].buffer = realloc(binds[n].buffer, sizeof(long long int)); - *static_cast(binds[n].buffer) = v; - binds[n].is_unsigned = 1; -} -void -MySQL::Command::bindParamI(unsigned int n, long long unsigned int v) -{ - binds[n].buffer_type = MYSQL_TYPE_LONGLONG; - binds[n].buffer = realloc(binds[n].buffer, sizeof(long long int)); - *static_cast(binds[n].buffer) = v; - binds[n].is_unsigned = 1; -} -void -MySQL::Command::bindParamB(unsigned int n, bool v) -{ - binds[n].buffer_type = MYSQL_TYPE_TINY; - binds[n].buffer = realloc(binds[n].buffer, sizeof(bool)); - *static_cast(binds[n].buffer) = (v ? 1 : 0); - binds[n].is_unsigned = 1; -} -void -MySQL::Command::bindParamF(unsigned int n, double v) -{ - binds[n].buffer_type = MYSQL_TYPE_DOUBLE; - binds[n].buffer = realloc(binds[n].buffer, sizeof(double)); - *static_cast(binds[n].buffer) = v; -} -void -MySQL::Command::bindParamF(unsigned int n, float v) -{ - binds[n].buffer_type = MYSQL_TYPE_FLOAT; - binds[n].buffer = realloc(binds[n].buffer, sizeof(float)); - *static_cast(binds[n].buffer) = v; -} -void -MySQL::Command::bindParamS(unsigned int n, const Glib::ustring & s) -{ - binds[n].buffer_type = MYSQL_TYPE_STRING; - binds[n].buffer = realloc(binds[n].buffer, s.bytes()); - s.copy(static_cast(binds[n].buffer), s.bytes()); - binds[n].buffer_length = s.bytes(); - binds[n].is_unsigned = 0; -} -void -MySQL::Command::bindParamT(unsigned int n, const boost::posix_time::ptime & v) -{ - binds[n].buffer_type = MYSQL_TYPE_DATETIME; - binds[n].buffer = realloc(binds[n].buffer, sizeof(MYSQL_TIME)); - MYSQL_TIME & ts = *static_cast(binds[n].buffer); - ts.year = v.date().year(); - ts.month = v.date().month(); - ts.day = v.date().day(); - ts.hour = v.time_of_day().hours(); - ts.minute = v.time_of_day().minutes(); - ts.second = v.time_of_day().seconds(); - ts.second_part = v.time_of_day().total_microseconds() % 1000000; - ts.neg = 0; -} -void -MySQL::Command::bindParamT(unsigned int n, const boost::posix_time::time_duration & v) -{ - binds[n].buffer_type = MYSQL_TYPE_TIME; - binds[n].buffer = realloc(binds[n].buffer, sizeof(MYSQL_TIME)); - MYSQL_TIME & ts = *static_cast(binds[n].buffer); - ts.year = 0; - ts.month = 0; - ts.day = 0; - ts.hour = v.hours(); - ts.minute = v.minutes(); - ts.second = v.seconds(); - ts.second_part = v.total_microseconds() % 1000000; - ts.neg = (v.is_negative() ? 1 : 0); -} -void -MySQL::Command::bindNull(unsigned int n) -{ - binds[n].buffer_type = MYSQL_TYPE_NULL; - binds[n].buffer = NULL; - free(binds[n].buffer); -} - -void -MySQL::Command::bindParams() -{ - if (paramsNeedBinding) { - if (mysql_stmt_bind_param(stmt, &binds.front())) { - throw Error(mysql_stmt_error(stmt)); - paramsNeedBinding = false; - } - } -} - - diff --git a/libmysqlpp/command.h b/libmysqlpp/command.h deleted file mode 100644 index 2de1b85..0000000 --- a/libmysqlpp/command.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef MY_COMMAND_H -#define MY_COMMAND_H - -#include -#include -#include - -namespace MySQL { - class Connection; - class Command : public virtual DB::Command { - public: - Command(const Connection *, const std::string & sql); - virtual ~Command() = 0; - - void bindParamI(unsigned int, int); - void bindParamI(unsigned int, long int); - void bindParamI(unsigned int, long long int); - void bindParamI(unsigned int, unsigned int); - void bindParamI(unsigned int, long unsigned int); - void bindParamI(unsigned int, long long unsigned int); - - void bindParamB(unsigned int, bool); - - void bindParamF(unsigned int, double); - void bindParamF(unsigned int, float); - - void bindParamS(unsigned int, const Glib::ustring&); - - void bindParamT(unsigned int, const boost::posix_time::time_duration &); - void bindParamT(unsigned int, const boost::posix_time::ptime &); - - void bindNull(unsigned int); - protected: - void bindParams(); - void * realloc(void * buffer, size_t size); - - const Connection * c; - MYSQL_STMT * stmt; - typedef std::vector Binds; - Binds binds; - bool paramsNeedBinding; - }; -} - -#endif - - diff --git a/libmysqlpp/connection.cpp b/libmysqlpp/connection.cpp deleted file mode 100644 index fe3f51f..0000000 --- a/libmysqlpp/connection.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "connection.h" -#include "error.h" -#include "selectcommand.h" -#include "modifycommand.h" -#include -#include -#include -#include - -NAMEDFACTORY("mysql", MySQL::Connection, DB::ConnectionFactory); - -class Opts { - public: - Opts() { port = 3306; } - typedef boost::optional OptString; - OptString server; - OptString user; - OptString password; - OptString database; - unsigned int port; - OptString unix_socket; - OptString options; -}; - -const char * -operator~(const Opts::OptString & os) -{ - if (os) { - return os->c_str(); - } - return NULL; -} - -namespace std { - template - std::istream & - operator>>(std::istream & s, boost::optional & o) - { - o = T(); - return (s >> *o); - } -} - -using namespace AdHoc; -NvpTarget(Opts) OptsTargetMap { - NvpValue(Opts, server), - NvpValue(Opts, user), - NvpValue(Opts, password), - NvpValue(Opts, database), - NvpValue(Opts, unix_socket), - NvpValue(Opts, port), - NvpValue(Opts, options), -}; - - -MySQL::Connection::Connection(const std::string & str) : - txDepth(0), - rolledback(false) -{ - std::stringstream i(str); - Opts o; - NvpParse::parse(i, OptsTargetMap, o); - mysql_init(&conn); - if (o.options) { - mysql_options(&conn, MYSQL_READ_DEFAULT_GROUP, ~o.options); - } - if (mysql_real_connect(&conn, ~o.server, ~o.user, ~o.password, ~o.database, - o.port, ~o.unix_socket, CLIENT_LOCAL_FILES | CLIENT_MULTI_STATEMENTS) == NULL) { - throw ConnectionError(); - } - if (mysql_set_character_set(&conn, "utf8")) { - throw ConnectionError(); - } -} - -MySQL::Connection::~Connection() -{ - mysql_close(&conn); -} - -void -MySQL::Connection::finish() const -{ - if (txDepth != 0) { - rollbackTx(); - throw Error("Transaction still open"); - } -} - -int -MySQL::Connection::beginTx() const -{ - if (txDepth == 0) { - if (mysql_autocommit(&conn, 0)) { - throw Error(mysql_error(&conn)); - } - rolledback = false; - } - return ++txDepth; -} - -int -MySQL::Connection::commitTx() const -{ - if (rolledback) { - return rollbackTx(); - } - if (--txDepth == 0) { - if (mysql_commit(&conn)) { - throw Error(mysql_error(&conn)); - } - } - return txDepth; -} - -int -MySQL::Connection::rollbackTx() const -{ - if (--txDepth == 0) { - if (mysql_rollback(&conn)) { - throw Error(mysql_error(&conn)); - } - } - else { - rolledback = true; - } - return txDepth; -} - -bool -MySQL::Connection::inTx() const -{ - return txDepth; -} - -DB::BulkDeleteStyle -MySQL::Connection::bulkDeleteStyle() const -{ - return DB::BulkDeleteUsingUsingAlias; -} - -DB::BulkUpdateStyle -MySQL::Connection::bulkUpdateStyle() const -{ - return DB::BulkUpdateUsingJoin; -} - -void -MySQL::Connection::ping() const -{ - if (mysql_ping(&conn)) { - throw Error(mysql_error(&conn)); - } -} - - -DB::SelectCommand * -MySQL::Connection::newSelectCommand(const std::string & sql) const -{ - return new SelectCommand(this, sql); -} - -DB::ModifyCommand * -MySQL::Connection::newModifyCommand(const std::string & sql) const -{ - return new ModifyCommand(this, sql); -} - -namespace MySQL { - class LoadContext : public AdHoc::System::RuntimeContext { - public: - LoadContext(MYSQL * c) : - loadBuf(NULL), - loadBufLen(0), - bufOff(0), - conn(c) - { - } - - static int local_infile_init(void ** ptr, const char *, void * ctx) { - *ptr = ctx; - return 0; - } - - static int local_infile_read(void * obj, char * buf, unsigned int bufSize) { - LoadContext * ctx = static_cast(obj); - if (ctx->loadBufLen - ctx->bufOff == 0) { - ctx->swapContext(); - if (ctx->loadBufLen - ctx->bufOff <= 0) { - // Nothing to do or error - return ctx->bufOff; - } - } - unsigned int copy = std::min(ctx->loadBufLen - ctx->bufOff, bufSize); - memcpy(buf, ctx->loadBuf + ctx->bufOff, copy); - ctx->bufOff += copy; - return copy; - } - - static void local_infile_end(void *) { - } - - static int local_infile_error(void *, char*, unsigned int) { - return 0; - } - - void callback() override - { - loadReturn = mysql_read_query_result(conn); - } - - const char * loadBuf; - unsigned int loadBufLen; - int bufOff; - MYSQL * conn; - int loadReturn; - }; -} - -void -MySQL::Connection::beginBulkUpload(const char * table, const char * extra) const -{ - static char buf[BUFSIZ]; - int len = snprintf(buf, BUFSIZ, "LOAD DATA LOCAL INFILE 'any' INTO TABLE %s %s", table, extra); - mysql_send_query(&conn, buf, len); - - ctx = boost::shared_ptr(new MySQL::LoadContext(&conn)); - - mysql_set_local_infile_handler(&conn, LoadContext::local_infile_init, LoadContext::local_infile_read, - LoadContext::local_infile_end, LoadContext::local_infile_error, ctx.get()); - - ctx->swapContext(); -} - -void -MySQL::Connection::endBulkUpload(const char * msg) const -{ - ctx->loadBuf = NULL; - ctx->loadBufLen = 0; - ctx->bufOff = msg ? -1 : 0; - // switch context with empty buffer fires finished - ctx->swapContext(); - // Check result - if (!msg) { - if (ctx->loadReturn) { - ctx.reset(); - throw Error(mysql_error(&conn)); - } - } - ctx.reset(); -} - -size_t -MySQL::Connection::bulkUploadData(const char * data, size_t len) const -{ - ctx->loadBuf = data; - ctx->loadBufLen = len; - ctx->bufOff = 0; - // switch context to load the buffered data - ctx->swapContext(); - return len; -} - -int64_t -MySQL::Connection::insertId() const -{ - return mysql_insert_id(&conn); -} - diff --git a/libmysqlpp/connection.h b/libmysqlpp/connection.h deleted file mode 100644 index 3ea6be8..0000000 --- a/libmysqlpp/connection.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef MY_CONNECTION_H -#define MY_CONNECTION_H - -#include -#include "error.h" -#include -#include - -namespace MySQL { - class LoadContext; - class Connection : public DB::Connection { - public: - Connection(const std::string & info); - ~Connection(); - - void finish() const override; - int beginTx() const override; - int commitTx() const override; - int rollbackTx() const override; - bool inTx() const override; - void ping() const override; - DB::BulkDeleteStyle bulkDeleteStyle() const override; - DB::BulkUpdateStyle bulkUpdateStyle() const override; - - DB::SelectCommand * newSelectCommand(const std::string & sql) const override; - DB::ModifyCommand * newModifyCommand(const std::string & sql) const override; - - void beginBulkUpload(const char *, const char *) const override; - void endBulkUpload(const char *) const override; - size_t bulkUploadData(const char *, size_t) const override; - - int64_t insertId() const override; - - mutable MYSQL conn; - - private: - my_bool my_true; - - mutable unsigned int txDepth; - mutable bool rolledback; - - mutable boost::shared_ptr ctx; - }; -} - -#endif - diff --git a/libmysqlpp/error.cpp b/libmysqlpp/error.cpp deleted file mode 100644 index 2b9b418..0000000 --- a/libmysqlpp/error.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "error.h" -#include - -MySQL::Error::Error() : - msg(NULL) -{ -} - -MySQL::Error::Error(const MySQL::Error & e) : - msg(e.msg ? strdup(e.msg) : NULL) -{ -} - -MySQL::Error::Error(const char * e) : - msg(e ? strdup(e) : NULL) -{ -} - -MySQL::Error::~Error() throw() -{ - free(msg); -} - -const char * -MySQL::Error::what() const throw() -{ - return msg ? msg : "No message"; -} - diff --git a/libmysqlpp/error.h b/libmysqlpp/error.h deleted file mode 100644 index b4f93b2..0000000 --- a/libmysqlpp/error.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef MY_ERROR_H -#define MY_ERROR_H - -#include - -namespace MySQL { - class Error : public DB::Error { - public: - Error(); - Error(const Error &); - Error(const char *); - ~Error() throw(); - - const char * what() const throw(); - - private: - char * msg; - }; - class ConnectionError : public Error, public virtual DB::ConnectionError { - }; -} - -#endif - diff --git a/libmysqlpp/mock.cpp b/libmysqlpp/mock.cpp deleted file mode 100644 index 3c749de..0000000 --- a/libmysqlpp/mock.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "connection.h" -#include "mock.h" -#include - -namespace MySQL { - -Mock::Mock(const std::string & name, const std::vector & ss) : - MockServerDatabase("options=p2testmysql", name, "mysql") -{ - CreateNewDatabase(); - PlaySchemaScripts(ss); -} - -DB::Connection * -Mock::openConnection() const -{ - return new Connection(stringbf("options=p2testmysql;database=%s", testDbName)); -} - -Mock::~Mock() -{ - DropDatabase(); -} - -} - diff --git a/libmysqlpp/mock.h b/libmysqlpp/mock.h deleted file mode 100644 index ce4fdf2..0000000 --- a/libmysqlpp/mock.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef MOCKMYSQLDATASOURCE_H -#define MOCKMYSQLDATASOURCE_H - -#include -#include -#include - -namespace MySQL { - -class DLL_PUBLIC Mock : public DB::MockServerDatabase { - public: - Mock(const std::string & name, const std::vector & ss); - ~Mock(); - - private: - DB::Connection * openConnection() const override; -}; - -} - -#endif - diff --git a/libmysqlpp/modifycommand.cpp b/libmysqlpp/modifycommand.cpp deleted file mode 100644 index e6e86b7..0000000 --- a/libmysqlpp/modifycommand.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "modifycommand.h" -#include "error.h" -#include -#include "connection.h" - -MySQL::ModifyCommand::ModifyCommand(const Connection * conn, const std::string & sql) : - DB::Command(sql), - DB::ModifyCommand(sql), - MySQL::Command(conn, sql) -{ -} - -MySQL::ModifyCommand::~ModifyCommand() -{ -} - -unsigned int -MySQL::ModifyCommand::execute(bool anc) -{ - bindParams(); - if (mysql_stmt_execute(stmt)) { - throw Error(mysql_stmt_error(stmt)); - } - int rows = mysql_stmt_affected_rows(stmt); - if (rows == 0 && !anc) { - throw Error("No rows affected"); - } - return rows; -} - diff --git a/libmysqlpp/modifycommand.h b/libmysqlpp/modifycommand.h deleted file mode 100644 index abb3507..0000000 --- a/libmysqlpp/modifycommand.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef MY_MODIFYCOMMAND_H -#define MY_MODIFYCOMMAND_H - -#include -#include "command.h" - -namespace MySQL { - class Connection; - class ModifyCommand : public DB::ModifyCommand, public Command { - public: - ModifyCommand(const Connection *, const std::string & sql); - virtual ~ModifyCommand(); - - unsigned int execute(bool); - - private: - void prepare() const; - mutable bool prepared; - }; -} - -#endif - - - diff --git a/libmysqlpp/my-column.cpp b/libmysqlpp/my-column.cpp new file mode 100644 index 0000000..4e3038e --- /dev/null +++ b/libmysqlpp/my-column.cpp @@ -0,0 +1,118 @@ +#include "my-column.h" +#include "my-selectcommand.h" +#include "my-error.h" +#include +#include + +MySQL::ColumnBase::ColumnBase(const char * name, unsigned int i) : + DB::Column(name, i) +{ +} + +bool +MySQL::ColumnBase::isNull() const +{ + return is_null; +} + +void +MySQL::ColumnBase::rebind(DB::Command *, unsigned int) const +{ + throw Error("Not supported"); +} + +MySQL::StringColumn::StringColumn(const char * name, unsigned int field, MYSQL_BIND * b, unsigned int len) : + ColumnBase(name, field), + value(new char[len]) +{ + b->is_null = &is_null; + b->buffer_type = MYSQL_TYPE_STRING; + b->is_unsigned = 0; + b->buffer = value; + b->buffer_length = len; + b->length = &length; +} +MySQL::StringColumn::~StringColumn() +{ + delete[] value; +} +void +MySQL::StringColumn::apply(DB::HandleField & h) const +{ + if (is_null) { + h.null(); + } + else { + h.string(value, length); + } +} +MySQL::NullColumn::NullColumn(const char * name, unsigned int field, MYSQL_BIND * b) : + ColumnBase(name, field) +{ + b->is_null = &is_null; + b->buffer_type = MYSQL_TYPE_NULL; + b->buffer = NULL; + b->buffer_length = 0; +} +void +MySQL::NullColumn::apply(DB::HandleField & h) const +{ + h.null(); +} + +namespace MySQL { + template Column::Column(const char * name, unsigned int field, MYSQL_BIND * b) : + ColumnBase(name, field) + { + b->is_null = &is_null; + b->buffer_type = MT; + b->is_unsigned = 0; + b->buffer = &value; + b->buffer_length = sizeof(T); + } + + template <> void Column::apply(DB::HandleField & h) const + { + if (is_null) { + h.null(); + } + else { + h.integer(value); + } + } + template <> void Column::apply(DB::HandleField & h) const + { + if (is_null) { + h.null(); + } + else { + h.floatingpoint(value); + } + } + template <> void Column::apply(DB::HandleField & h) const + { + if (is_null) { + h.null(); + } + else { + h.timestamp(boost::posix_time::ptime( + boost::gregorian::date(value.year, value.month, value.day), + boost::posix_time::time_duration(value.hour, value.minute, value.second) + boost::posix_time::microseconds(value.second_part))); + } + } + template <> void Column::apply(DB::HandleField & h) const + { + if (is_null) { + h.null(); + } + else { + h.interval( + boost::posix_time::time_duration(value.hour, value.minute, value.second) + boost::posix_time::microseconds(value.second_part)); + } + } + + template class Column; + template class Column; + template class Column; + template class Column; +} diff --git a/libmysqlpp/my-column.h b/libmysqlpp/my-column.h new file mode 100644 index 0000000..38f4f39 --- /dev/null +++ b/libmysqlpp/my-column.h @@ -0,0 +1,42 @@ +#ifndef MY_COLUMN_H +#define MY_COLUMN_H + +#include +#include + +namespace MySQL { + class SelectCommand; + class ColumnBase : public DB::Column { + public: + ColumnBase(const char * name, unsigned int field); + + bool isNull() const; + void rebind(DB::Command *, unsigned int) const; + protected: + my_bool is_null; + long unsigned int length; + friend class SelectCommand; + }; + class StringColumn : public ColumnBase { + public: + StringColumn(const char * name, unsigned int field, MYSQL_BIND * b, unsigned int len); + ~StringColumn(); + void apply(DB::HandleField &) const; + char * value; + long unsigned int length; + }; + class NullColumn : public ColumnBase { + public: + NullColumn(const char * name, unsigned int field, MYSQL_BIND * b); + void apply(DB::HandleField &) const; + }; + template class Column : public ColumnBase { + public: + Column(const char * name, unsigned int field, MYSQL_BIND * b); + void apply(DB::HandleField & h) const; + T value; + }; +} + +#endif + diff --git a/libmysqlpp/my-command.cpp b/libmysqlpp/my-command.cpp new file mode 100644 index 0000000..bfa25e6 --- /dev/null +++ b/libmysqlpp/my-command.cpp @@ -0,0 +1,174 @@ +#include "my-command.h" +#include "my-connection.h" +#include +#include + +MySQL::Command::Command(const Connection * conn, const std::string & sql) : + DB::Command(sql), + c(conn), + stmt(mysql_stmt_init(&conn->conn)), + paramsNeedBinding(false) +{ + if (!stmt) { + throw Error(mysql_error(&conn->conn)); + } + if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length())) { + throw Error(mysql_stmt_error(stmt)); + } + binds.resize(mysql_stmt_param_count(stmt)); + if (binds.size()) { + paramsNeedBinding = true; + for (Binds::iterator i = binds.begin(); i != binds.end(); ++i) { + memset(&*i, 0, sizeof(MYSQL_BIND)); + i->buffer_type = MYSQL_TYPE_NULL; + } + } +} + +MySQL::Command::~Command() +{ + for (Binds::const_iterator i = binds.begin(); i != binds.end(); ++i) { + free(i->buffer); + } + mysql_stmt_close(stmt); +} + +void * +MySQL::Command::realloc(void * buffer, size_t size) +{ + void * newBuffer = ::realloc(buffer, size); + if (buffer != newBuffer) { + paramsNeedBinding = true; + } + return newBuffer; +} + +void +MySQL::Command::bindParamI(unsigned int n, int v) +{ + binds[n].buffer_type = MYSQL_TYPE_LONG; + binds[n].buffer = realloc(binds[n].buffer, sizeof(int)); + *static_cast(binds[n].buffer) = v; + binds[n].is_unsigned = 0; +} +void +MySQL::Command::bindParamI(unsigned int n, long int v) +{ + binds[n].buffer_type = MYSQL_TYPE_LONGLONG; + binds[n].buffer = realloc(binds[n].buffer, sizeof(long long int)); + *static_cast(binds[n].buffer) = v; + binds[n].is_unsigned = 0; +} +void +MySQL::Command::bindParamI(unsigned int n, long long int v) +{ + binds[n].buffer_type = MYSQL_TYPE_LONGLONG; + binds[n].buffer = realloc(binds[n].buffer, sizeof(long long int)); + *static_cast(binds[n].buffer) = v; + binds[n].is_unsigned = 0; +} +void +MySQL::Command::bindParamI(unsigned int n, unsigned int v) +{ + binds[n].buffer_type = MYSQL_TYPE_LONG; + binds[n].buffer = realloc(binds[n].buffer, sizeof(int)); + *static_cast(binds[n].buffer) = v; + binds[n].is_unsigned = 1; +} +void +MySQL::Command::bindParamI(unsigned int n, long unsigned int v) +{ + binds[n].buffer_type = MYSQL_TYPE_LONGLONG; + binds[n].buffer = realloc(binds[n].buffer, sizeof(long long int)); + *static_cast(binds[n].buffer) = v; + binds[n].is_unsigned = 1; +} +void +MySQL::Command::bindParamI(unsigned int n, long long unsigned int v) +{ + binds[n].buffer_type = MYSQL_TYPE_LONGLONG; + binds[n].buffer = realloc(binds[n].buffer, sizeof(long long int)); + *static_cast(binds[n].buffer) = v; + binds[n].is_unsigned = 1; +} +void +MySQL::Command::bindParamB(unsigned int n, bool v) +{ + binds[n].buffer_type = MYSQL_TYPE_TINY; + binds[n].buffer = realloc(binds[n].buffer, sizeof(bool)); + *static_cast(binds[n].buffer) = (v ? 1 : 0); + binds[n].is_unsigned = 1; +} +void +MySQL::Command::bindParamF(unsigned int n, double v) +{ + binds[n].buffer_type = MYSQL_TYPE_DOUBLE; + binds[n].buffer = realloc(binds[n].buffer, sizeof(double)); + *static_cast(binds[n].buffer) = v; +} +void +MySQL::Command::bindParamF(unsigned int n, float v) +{ + binds[n].buffer_type = MYSQL_TYPE_FLOAT; + binds[n].buffer = realloc(binds[n].buffer, sizeof(float)); + *static_cast(binds[n].buffer) = v; +} +void +MySQL::Command::bindParamS(unsigned int n, const Glib::ustring & s) +{ + binds[n].buffer_type = MYSQL_TYPE_STRING; + binds[n].buffer = realloc(binds[n].buffer, s.bytes()); + s.copy(static_cast(binds[n].buffer), s.bytes()); + binds[n].buffer_length = s.bytes(); + binds[n].is_unsigned = 0; +} +void +MySQL::Command::bindParamT(unsigned int n, const boost::posix_time::ptime & v) +{ + binds[n].buffer_type = MYSQL_TYPE_DATETIME; + binds[n].buffer = realloc(binds[n].buffer, sizeof(MYSQL_TIME)); + MYSQL_TIME & ts = *static_cast(binds[n].buffer); + ts.year = v.date().year(); + ts.month = v.date().month(); + ts.day = v.date().day(); + ts.hour = v.time_of_day().hours(); + ts.minute = v.time_of_day().minutes(); + ts.second = v.time_of_day().seconds(); + ts.second_part = v.time_of_day().total_microseconds() % 1000000; + ts.neg = 0; +} +void +MySQL::Command::bindParamT(unsigned int n, const boost::posix_time::time_duration & v) +{ + binds[n].buffer_type = MYSQL_TYPE_TIME; + binds[n].buffer = realloc(binds[n].buffer, sizeof(MYSQL_TIME)); + MYSQL_TIME & ts = *static_cast(binds[n].buffer); + ts.year = 0; + ts.month = 0; + ts.day = 0; + ts.hour = v.hours(); + ts.minute = v.minutes(); + ts.second = v.seconds(); + ts.second_part = v.total_microseconds() % 1000000; + ts.neg = (v.is_negative() ? 1 : 0); +} +void +MySQL::Command::bindNull(unsigned int n) +{ + binds[n].buffer_type = MYSQL_TYPE_NULL; + binds[n].buffer = NULL; + free(binds[n].buffer); +} + +void +MySQL::Command::bindParams() +{ + if (paramsNeedBinding) { + if (mysql_stmt_bind_param(stmt, &binds.front())) { + throw Error(mysql_stmt_error(stmt)); + paramsNeedBinding = false; + } + } +} + + diff --git a/libmysqlpp/my-command.h b/libmysqlpp/my-command.h new file mode 100644 index 0000000..2de1b85 --- /dev/null +++ b/libmysqlpp/my-command.h @@ -0,0 +1,47 @@ +#ifndef MY_COMMAND_H +#define MY_COMMAND_H + +#include +#include +#include + +namespace MySQL { + class Connection; + class Command : public virtual DB::Command { + public: + Command(const Connection *, const std::string & sql); + virtual ~Command() = 0; + + void bindParamI(unsigned int, int); + void bindParamI(unsigned int, long int); + void bindParamI(unsigned int, long long int); + void bindParamI(unsigned int, unsigned int); + void bindParamI(unsigned int, long unsigned int); + void bindParamI(unsigned int, long long unsigned int); + + void bindParamB(unsigned int, bool); + + void bindParamF(unsigned int, double); + void bindParamF(unsigned int, float); + + void bindParamS(unsigned int, const Glib::ustring&); + + void bindParamT(unsigned int, const boost::posix_time::time_duration &); + void bindParamT(unsigned int, const boost::posix_time::ptime &); + + void bindNull(unsigned int); + protected: + void bindParams(); + void * realloc(void * buffer, size_t size); + + const Connection * c; + MYSQL_STMT * stmt; + typedef std::vector Binds; + Binds binds; + bool paramsNeedBinding; + }; +} + +#endif + + diff --git a/libmysqlpp/my-connection.cpp b/libmysqlpp/my-connection.cpp new file mode 100644 index 0000000..3e1aed3 --- /dev/null +++ b/libmysqlpp/my-connection.cpp @@ -0,0 +1,269 @@ +#include "my-connection.h" +#include "my-error.h" +#include "my-selectcommand.h" +#include "my-modifycommand.h" +#include +#include +#include +#include + +NAMEDFACTORY("mysql", MySQL::Connection, DB::ConnectionFactory); + +class Opts { + public: + Opts() { port = 3306; } + typedef boost::optional OptString; + OptString server; + OptString user; + OptString password; + OptString database; + unsigned int port; + OptString unix_socket; + OptString options; +}; + +const char * +operator~(const Opts::OptString & os) +{ + if (os) { + return os->c_str(); + } + return NULL; +} + +namespace std { + template + std::istream & + operator>>(std::istream & s, boost::optional & o) + { + o = T(); + return (s >> *o); + } +} + +using namespace AdHoc; +NvpTarget(Opts) OptsTargetMap { + NvpValue(Opts, server), + NvpValue(Opts, user), + NvpValue(Opts, password), + NvpValue(Opts, database), + NvpValue(Opts, unix_socket), + NvpValue(Opts, port), + NvpValue(Opts, options), +}; + + +MySQL::Connection::Connection(const std::string & str) : + txDepth(0), + rolledback(false) +{ + std::stringstream i(str); + Opts o; + NvpParse::parse(i, OptsTargetMap, o); + mysql_init(&conn); + if (o.options) { + mysql_options(&conn, MYSQL_READ_DEFAULT_GROUP, ~o.options); + } + if (mysql_real_connect(&conn, ~o.server, ~o.user, ~o.password, ~o.database, + o.port, ~o.unix_socket, CLIENT_LOCAL_FILES | CLIENT_MULTI_STATEMENTS) == NULL) { + throw ConnectionError(); + } + if (mysql_set_character_set(&conn, "utf8")) { + throw ConnectionError(); + } +} + +MySQL::Connection::~Connection() +{ + mysql_close(&conn); +} + +void +MySQL::Connection::finish() const +{ + if (txDepth != 0) { + rollbackTx(); + throw Error("Transaction still open"); + } +} + +int +MySQL::Connection::beginTx() const +{ + if (txDepth == 0) { + if (mysql_autocommit(&conn, 0)) { + throw Error(mysql_error(&conn)); + } + rolledback = false; + } + return ++txDepth; +} + +int +MySQL::Connection::commitTx() const +{ + if (rolledback) { + return rollbackTx(); + } + if (--txDepth == 0) { + if (mysql_commit(&conn)) { + throw Error(mysql_error(&conn)); + } + } + return txDepth; +} + +int +MySQL::Connection::rollbackTx() const +{ + if (--txDepth == 0) { + if (mysql_rollback(&conn)) { + throw Error(mysql_error(&conn)); + } + } + else { + rolledback = true; + } + return txDepth; +} + +bool +MySQL::Connection::inTx() const +{ + return txDepth; +} + +DB::BulkDeleteStyle +MySQL::Connection::bulkDeleteStyle() const +{ + return DB::BulkDeleteUsingUsingAlias; +} + +DB::BulkUpdateStyle +MySQL::Connection::bulkUpdateStyle() const +{ + return DB::BulkUpdateUsingJoin; +} + +void +MySQL::Connection::ping() const +{ + if (mysql_ping(&conn)) { + throw Error(mysql_error(&conn)); + } +} + + +DB::SelectCommand * +MySQL::Connection::newSelectCommand(const std::string & sql) const +{ + return new SelectCommand(this, sql); +} + +DB::ModifyCommand * +MySQL::Connection::newModifyCommand(const std::string & sql) const +{ + return new ModifyCommand(this, sql); +} + +namespace MySQL { + class LoadContext : public AdHoc::System::RuntimeContext { + public: + LoadContext(MYSQL * c) : + loadBuf(NULL), + loadBufLen(0), + bufOff(0), + conn(c) + { + } + + static int local_infile_init(void ** ptr, const char *, void * ctx) { + *ptr = ctx; + return 0; + } + + static int local_infile_read(void * obj, char * buf, unsigned int bufSize) { + LoadContext * ctx = static_cast(obj); + if (ctx->loadBufLen - ctx->bufOff == 0) { + ctx->swapContext(); + if (ctx->loadBufLen - ctx->bufOff <= 0) { + // Nothing to do or error + return ctx->bufOff; + } + } + unsigned int copy = std::min(ctx->loadBufLen - ctx->bufOff, bufSize); + memcpy(buf, ctx->loadBuf + ctx->bufOff, copy); + ctx->bufOff += copy; + return copy; + } + + static void local_infile_end(void *) { + } + + static int local_infile_error(void *, char*, unsigned int) { + return 0; + } + + void callback() override + { + loadReturn = mysql_read_query_result(conn); + } + + const char * loadBuf; + unsigned int loadBufLen; + int bufOff; + MYSQL * conn; + int loadReturn; + }; +} + +void +MySQL::Connection::beginBulkUpload(const char * table, const char * extra) const +{ + static char buf[BUFSIZ]; + int len = snprintf(buf, BUFSIZ, "LOAD DATA LOCAL INFILE 'any' INTO TABLE %s %s", table, extra); + mysql_send_query(&conn, buf, len); + + ctx = boost::shared_ptr(new MySQL::LoadContext(&conn)); + + mysql_set_local_infile_handler(&conn, LoadContext::local_infile_init, LoadContext::local_infile_read, + LoadContext::local_infile_end, LoadContext::local_infile_error, ctx.get()); + + ctx->swapContext(); +} + +void +MySQL::Connection::endBulkUpload(const char * msg) const +{ + ctx->loadBuf = NULL; + ctx->loadBufLen = 0; + ctx->bufOff = msg ? -1 : 0; + // switch context with empty buffer fires finished + ctx->swapContext(); + // Check result + if (!msg) { + if (ctx->loadReturn) { + ctx.reset(); + throw Error(mysql_error(&conn)); + } + } + ctx.reset(); +} + +size_t +MySQL::Connection::bulkUploadData(const char * data, size_t len) const +{ + ctx->loadBuf = data; + ctx->loadBufLen = len; + ctx->bufOff = 0; + // switch context to load the buffered data + ctx->swapContext(); + return len; +} + +int64_t +MySQL::Connection::insertId() const +{ + return mysql_insert_id(&conn); +} + diff --git a/libmysqlpp/my-connection.h b/libmysqlpp/my-connection.h new file mode 100644 index 0000000..1f7ec5a --- /dev/null +++ b/libmysqlpp/my-connection.h @@ -0,0 +1,47 @@ +#ifndef MY_CONNECTION_H +#define MY_CONNECTION_H + +#include +#include "my-error.h" +#include +#include + +namespace MySQL { + class LoadContext; + class Connection : public DB::Connection { + public: + Connection(const std::string & info); + ~Connection(); + + void finish() const override; + int beginTx() const override; + int commitTx() const override; + int rollbackTx() const override; + bool inTx() const override; + void ping() const override; + DB::BulkDeleteStyle bulkDeleteStyle() const override; + DB::BulkUpdateStyle bulkUpdateStyle() const override; + + DB::SelectCommand * newSelectCommand(const std::string & sql) const override; + DB::ModifyCommand * newModifyCommand(const std::string & sql) const override; + + void beginBulkUpload(const char *, const char *) const override; + void endBulkUpload(const char *) const override; + size_t bulkUploadData(const char *, size_t) const override; + + int64_t insertId() const override; + + mutable MYSQL conn; + + private: + my_bool my_true; + + mutable unsigned int txDepth; + mutable bool rolledback; + + mutable boost::shared_ptr ctx; + }; +} + +#endif + diff --git a/libmysqlpp/my-error.cpp b/libmysqlpp/my-error.cpp new file mode 100644 index 0000000..c35a3a1 --- /dev/null +++ b/libmysqlpp/my-error.cpp @@ -0,0 +1,29 @@ +#include "my-error.h" +#include + +MySQL::Error::Error() : + msg(NULL) +{ +} + +MySQL::Error::Error(const MySQL::Error & e) : + msg(e.msg ? strdup(e.msg) : NULL) +{ +} + +MySQL::Error::Error(const char * e) : + msg(e ? strdup(e) : NULL) +{ +} + +MySQL::Error::~Error() throw() +{ + free(msg); +} + +const char * +MySQL::Error::what() const throw() +{ + return msg ? msg : "No message"; +} + diff --git a/libmysqlpp/my-error.h b/libmysqlpp/my-error.h new file mode 100644 index 0000000..b4f93b2 --- /dev/null +++ b/libmysqlpp/my-error.h @@ -0,0 +1,24 @@ +#ifndef MY_ERROR_H +#define MY_ERROR_H + +#include + +namespace MySQL { + class Error : public DB::Error { + public: + Error(); + Error(const Error &); + Error(const char *); + ~Error() throw(); + + const char * what() const throw(); + + private: + char * msg; + }; + class ConnectionError : public Error, public virtual DB::ConnectionError { + }; +} + +#endif + diff --git a/libmysqlpp/my-mock.cpp b/libmysqlpp/my-mock.cpp new file mode 100644 index 0000000..bf02e11 --- /dev/null +++ b/libmysqlpp/my-mock.cpp @@ -0,0 +1,26 @@ +#include "my-connection.h" +#include "my-mock.h" +#include + +namespace MySQL { + +Mock::Mock(const std::string & name, const std::vector & ss) : + MockServerDatabase("options=p2testmysql", name, "mysql") +{ + CreateNewDatabase(); + PlaySchemaScripts(ss); +} + +DB::Connection * +Mock::openConnection() const +{ + return new Connection(stringbf("options=p2testmysql;database=%s", testDbName)); +} + +Mock::~Mock() +{ + DropDatabase(); +} + +} + diff --git a/libmysqlpp/my-mock.h b/libmysqlpp/my-mock.h new file mode 100644 index 0000000..ce4fdf2 --- /dev/null +++ b/libmysqlpp/my-mock.h @@ -0,0 +1,22 @@ +#ifndef MOCKMYSQLDATASOURCE_H +#define MOCKMYSQLDATASOURCE_H + +#include +#include +#include + +namespace MySQL { + +class DLL_PUBLIC Mock : public DB::MockServerDatabase { + public: + Mock(const std::string & name, const std::vector & ss); + ~Mock(); + + private: + DB::Connection * openConnection() const override; +}; + +} + +#endif + diff --git a/libmysqlpp/my-modifycommand.cpp b/libmysqlpp/my-modifycommand.cpp new file mode 100644 index 0000000..c66c628 --- /dev/null +++ b/libmysqlpp/my-modifycommand.cpp @@ -0,0 +1,30 @@ +#include "my-modifycommand.h" +#include "my-error.h" +#include +#include "connection.h" + +MySQL::ModifyCommand::ModifyCommand(const Connection * conn, const std::string & sql) : + DB::Command(sql), + DB::ModifyCommand(sql), + MySQL::Command(conn, sql) +{ +} + +MySQL::ModifyCommand::~ModifyCommand() +{ +} + +unsigned int +MySQL::ModifyCommand::execute(bool anc) +{ + bindParams(); + if (mysql_stmt_execute(stmt)) { + throw Error(mysql_stmt_error(stmt)); + } + int rows = mysql_stmt_affected_rows(stmt); + if (rows == 0 && !anc) { + throw Error("No rows affected"); + } + return rows; +} + diff --git a/libmysqlpp/my-modifycommand.h b/libmysqlpp/my-modifycommand.h new file mode 100644 index 0000000..cf570bb --- /dev/null +++ b/libmysqlpp/my-modifycommand.h @@ -0,0 +1,25 @@ +#ifndef MY_MODIFYCOMMAND_H +#define MY_MODIFYCOMMAND_H + +#include +#include "my-command.h" + +namespace MySQL { + class Connection; + class ModifyCommand : public DB::ModifyCommand, public Command { + public: + ModifyCommand(const Connection *, const std::string & sql); + virtual ~ModifyCommand(); + + unsigned int execute(bool); + + private: + void prepare() const; + mutable bool prepared; + }; +} + +#endif + + + diff --git a/libmysqlpp/my-selectcommand.cpp b/libmysqlpp/my-selectcommand.cpp new file mode 100644 index 0000000..257f33f --- /dev/null +++ b/libmysqlpp/my-selectcommand.cpp @@ -0,0 +1,99 @@ +#include "my-selectcommand.h" +#include "my-connection.h" +#include "my-column.h" +#include "my-error.h" +#include + +MySQL::SelectCommand::SelectCommand(const Connection * conn, const std::string & sql) : + DB::Command(sql), + DB::SelectCommand(sql), + MySQL::Command(conn, sql), + prepared(false), + executed(false) +{ +} + +void +MySQL::SelectCommand::execute() +{ + if (!prepared) { + bindParams(); + fields.resize(mysql_stmt_field_count(stmt)); + for (Binds::iterator i = fields.begin(); i != fields.end(); ++i) { + memset(&*i, 0, sizeof(MYSQL_BIND)); + } + MYSQL_RES * prepare_meta_result = mysql_stmt_result_metadata(stmt); + MYSQL_FIELD * fieldDefs = mysql_fetch_fields(prepare_meta_result); + for (unsigned int i = 0; i < fields.size(); i += 1) { + switch (fieldDefs[i].type) { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_YEAR: + insertColumn(boost::shared_ptr(new Column(fieldDefs[i].name, i, &fields[i]))); + break; + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + insertColumn(boost::shared_ptr(new Column(fieldDefs[i].name, i, &fields[i]))); + break; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_DATETIME: + insertColumn(boost::shared_ptr(new Column(fieldDefs[i].name, i, &fields[i]))); + break; + case MYSQL_TYPE_TIME: + insertColumn(boost::shared_ptr(new Column(fieldDefs[i].name, i, &fields[i]))); + break; + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + insertColumn(boost::shared_ptr(new StringColumn(fieldDefs[i].name, i, &fields[i], fieldDefs[i].length))); + break; + case MYSQL_TYPE_NULL: + insertColumn(boost::shared_ptr(new NullColumn(fieldDefs[i].name, i, &fields[i]))); + break; + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_SET: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_GEOMETRY: + default: + mysql_free_result(prepare_meta_result); + throw Error("Unexpected type"); + } + } + mysql_free_result(prepare_meta_result); + if (mysql_stmt_bind_result(stmt, &fields.front())) { + throw Error(mysql_stmt_error(stmt)); + } + prepared = true; + } + if (!executed) { + if (mysql_stmt_execute(stmt)) { + throw Error(mysql_stmt_error(stmt)); + } + if (mysql_stmt_store_result(stmt)) { + throw Error(mysql_stmt_error(stmt)); + } + executed = true; + } +} + +bool +MySQL::SelectCommand::fetch() +{ + execute(); + switch (mysql_stmt_fetch(stmt)) { + case 0: + return true; + case MYSQL_NO_DATA: + executed = false; + return false; + default: + throw Error(mysql_stmt_error(stmt)); + } +} + diff --git a/libmysqlpp/my-selectcommand.h b/libmysqlpp/my-selectcommand.h new file mode 100644 index 0000000..dc4937a --- /dev/null +++ b/libmysqlpp/my-selectcommand.h @@ -0,0 +1,26 @@ +#ifndef MY_SELECTCOMMAND_H +#define MY_SELECTCOMMAND_H + +#include +#include "my-command.h" + +namespace MySQL { + class Connection; + class ColumnBase; + class SelectCommand : public DB::SelectCommand, public Command { + public: + SelectCommand(const Connection *, const std::string & sql); + + bool fetch(); + void execute(); + + private: + bool prepared; + bool executed; + Binds fields; + }; +} + +#endif + + diff --git a/libmysqlpp/selectcommand.cpp b/libmysqlpp/selectcommand.cpp deleted file mode 100644 index b24e8d7..0000000 --- a/libmysqlpp/selectcommand.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "selectcommand.h" -#include "connection.h" -#include "column.h" -#include "error.h" -#include - -MySQL::SelectCommand::SelectCommand(const Connection * conn, const std::string & sql) : - DB::Command(sql), - DB::SelectCommand(sql), - MySQL::Command(conn, sql), - prepared(false), - executed(false) -{ -} - -void -MySQL::SelectCommand::execute() -{ - if (!prepared) { - bindParams(); - fields.resize(mysql_stmt_field_count(stmt)); - for (Binds::iterator i = fields.begin(); i != fields.end(); ++i) { - memset(&*i, 0, sizeof(MYSQL_BIND)); - } - MYSQL_RES * prepare_meta_result = mysql_stmt_result_metadata(stmt); - MYSQL_FIELD * fieldDefs = mysql_fetch_fields(prepare_meta_result); - for (unsigned int i = 0; i < fields.size(); i += 1) { - switch (fieldDefs[i].type) { - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_LONGLONG: - case MYSQL_TYPE_YEAR: - insertColumn(boost::shared_ptr(new Column(fieldDefs[i].name, i, &fields[i]))); - break; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - insertColumn(boost::shared_ptr(new Column(fieldDefs[i].name, i, &fields[i]))); - break; - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_DATETIME: - insertColumn(boost::shared_ptr(new Column(fieldDefs[i].name, i, &fields[i]))); - break; - case MYSQL_TYPE_TIME: - insertColumn(boost::shared_ptr(new Column(fieldDefs[i].name, i, &fields[i]))); - break; - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - insertColumn(boost::shared_ptr(new StringColumn(fieldDefs[i].name, i, &fields[i], fieldDefs[i].length))); - break; - case MYSQL_TYPE_NULL: - insertColumn(boost::shared_ptr(new NullColumn(fieldDefs[i].name, i, &fields[i]))); - break; - case MYSQL_TYPE_BIT: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_GEOMETRY: - default: - mysql_free_result(prepare_meta_result); - throw Error("Unexpected type"); - } - } - mysql_free_result(prepare_meta_result); - if (mysql_stmt_bind_result(stmt, &fields.front())) { - throw Error(mysql_stmt_error(stmt)); - } - prepared = true; - } - if (!executed) { - if (mysql_stmt_execute(stmt)) { - throw Error(mysql_stmt_error(stmt)); - } - if (mysql_stmt_store_result(stmt)) { - throw Error(mysql_stmt_error(stmt)); - } - executed = true; - } -} - -bool -MySQL::SelectCommand::fetch() -{ - execute(); - switch (mysql_stmt_fetch(stmt)) { - case 0: - return true; - case MYSQL_NO_DATA: - executed = false; - return false; - default: - throw Error(mysql_stmt_error(stmt)); - } -} - diff --git a/libmysqlpp/selectcommand.h b/libmysqlpp/selectcommand.h deleted file mode 100644 index d145ce8..0000000 --- a/libmysqlpp/selectcommand.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef MY_SELECTCOMMAND_H -#define MY_SELECTCOMMAND_H - -#include -#include "command.h" - -namespace MySQL { - class Connection; - class ColumnBase; - class SelectCommand : public DB::SelectCommand, public Command { - public: - SelectCommand(const Connection *, const std::string & sql); - - bool fetch(); - void execute(); - - private: - bool prepared; - bool executed; - Binds fields; - }; -} - -#endif - - diff --git a/libmysqlpp/unittests/testmysql.cpp b/libmysqlpp/unittests/testmysql.cpp index 9b0eae2..827ae84 100644 --- a/libmysqlpp/unittests/testmysql.cpp +++ b/libmysqlpp/unittests/testmysql.cpp @@ -1,7 +1,7 @@ #define BOOST_TEST_MODULE TestMySQL #include -#include +#include #include #include #include -- cgit v1.2.3