add support for MySQL 8

This commit is contained in:
Günter Obiltschnig 2020-01-13 10:31:25 +01:00
parent 4920df18ce
commit c04a1f28d9
16 changed files with 64 additions and 52 deletions

View File

@ -17,12 +17,14 @@
#ifndef Data_MySQL_Binder_INCLUDED #ifndef Data_MySQL_Binder_INCLUDED
#define Data_MySQL_Binder_INCLUDED #define Data_MySQL_Binder_INCLUDED
#include "Poco/Data/MySQL/MySQL.h" #include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/AbstractBinder.h" #include "Poco/Data/AbstractBinder.h"
#include "Poco/Data/LOB.h" #include "Poco/Data/LOB.h"
#include "Poco/Data/MySQL/MySQLException.h" #include "Poco/Data/MySQL/MySQLException.h"
#include <mysql.h> #include <mysql.h>
namespace Poco { namespace Poco {
namespace Data { namespace Data {
namespace MySQL { namespace MySQL {
@ -105,7 +107,6 @@ public:
virtual void bind(std::size_t pos, const NullData& val, Direction dir); virtual void bind(std::size_t pos, const NullData& val, Direction dir);
/// Binds a null. /// Binds a null.
virtual void bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir = PD_IN); virtual void bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<Poco::Int8>& val, Direction dir = PD_IN); virtual void bind(std::size_t pos, const std::deque<Poco::Int8>& val, Direction dir = PD_IN);
@ -226,9 +227,6 @@ public:
MYSQL_BIND* getBindArray() const; MYSQL_BIND* getBindArray() const;
/// Return array /// Return array
//void updateDates();
/// Update linked times
private: private:
Binder(const Binder&); Binder(const Binder&);
/// Don't copy the binder /// Don't copy the binder
@ -244,7 +242,6 @@ private:
/// Common bind implementation /// Common bind implementation
private: private:
std::vector<MYSQL_BIND> _bindArray; std::vector<MYSQL_BIND> _bindArray;
std::vector<MYSQL_TIME*> _dates; std::vector<MYSQL_TIME*> _dates;
}; };

View File

@ -31,7 +31,6 @@ class MySQL_API Connector: public Poco::Data::Connector
/// Connector instantiates MySQL SessionImpl objects. /// Connector instantiates MySQL SessionImpl objects.
{ {
public: public:
static std::string KEY; static std::string KEY;
Connector(); Connector();

View File

@ -318,18 +318,17 @@ public:
/// Extracts a Dynamic::Var list. /// Extracts a Dynamic::Var list.
private: private:
bool realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, bool isUnsigned = false); bool realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, bool isUnsigned = false);
// Prevent VC8 warning "operator= could not be generated" // Prevent VC8 warning "operator= could not be generated"
Extractor& operator=(const Extractor&); Extractor& operator=(const Extractor&);
private: private:
StatementExecutor& _stmt; StatementExecutor& _stmt;
ResultMetadata& _metadata; ResultMetadata& _metadata;
}; };
} } } // namespace Poco::Data::MySQL } } } // namespace Poco::Data::MySQL

View File

@ -17,31 +17,27 @@
#ifndef Data_MySQL_MySQLException_INCLUDED #ifndef Data_MySQL_MySQLException_INCLUDED
#define Data_MySQL_MySQLException_INCLUDED #define Data_MySQL_MySQLException_INCLUDED
#include "Poco/Data/MySQL/MySQL.h" #include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/DataException.h" #include "Poco/Data/DataException.h"
#include <typeinfo> #include <typeinfo>
#include <string> #include <string>
#include <mysql.h>
#ifndef MYSQL
typedef struct st_mysql MYSQL;
#endif
#ifndef MYSQL_STMT
typedef struct st_mysql_stmt MYSQL_STMT;
#endif
namespace Poco { namespace Poco {
namespace Data { namespace Data {
namespace MySQL { namespace MySQL {
// End-user include this file and use in code ConnectionException/StatementException // End-user include this file and use in code ConnectionException/StatementException
// So it need not know // So it need not know
class MySQL_API MySQLException: public Poco::Data::DataException class MySQL_API MySQLException: public Poco::Data::DataException
/// Base class for all MySQL exceptions /// Base class for all MySQL exceptions
{ {
public: public:
MySQLException(const std::string& msg); MySQLException(const std::string& msg);
/// Creates MySQLException. /// Creates MySQLException.
@ -79,7 +75,6 @@ class ConnectionException : public MySQLException
/// ConnectionException /// ConnectionException
{ {
public: public:
ConnectionException(const std::string& msg); ConnectionException(const std::string& msg);
/// Creates ConnectionException from string. /// Creates ConnectionException from string.
@ -87,9 +82,7 @@ public:
/// Creates ConnectionException from string and handle. /// Creates ConnectionException from string and handle.
private: private:
static std::string compose(const std::string& text, MYSQL* h); static std::string compose(const std::string& text, MYSQL* h);
}; };
@ -97,7 +90,6 @@ class TransactionException : public ConnectionException
/// TrabsactionException /// TrabsactionException
{ {
public: public:
TransactionException(const std::string& msg); TransactionException(const std::string& msg);
/// Creates TransactionException from string. /// Creates TransactionException from string.
@ -110,7 +102,6 @@ class StatementException : public MySQLException
/// StatementException /// StatementException
{ {
public: public:
StatementException(const std::string& msg); StatementException(const std::string& msg);
/// Creates StatementException from string. /// Creates StatementException from string.
@ -118,7 +109,6 @@ public:
/// Creates StatementException from string and handle. /// Creates StatementException from string and handle.
private: private:
static std::string compose(const std::string& text, MYSQL_STMT* h, const std::string& stmt); static std::string compose(const std::string& text, MYSQL_STMT* h, const std::string& stmt);
}; };
@ -127,6 +117,7 @@ private:
// inlines // inlines
// //
inline MySQLException& MySQLException::operator=(const MySQLException& exc) inline MySQLException& MySQLException::operator=(const MySQLException& exc)
{ {
Poco::Data::DataException::operator=(exc); Poco::Data::DataException::operator=(exc);
@ -156,4 +147,5 @@ inline void MySQLException::rethrow() const
} } } // namespace Poco::Data::MySQL } } } // namespace Poco::Data::MySQL
#endif //Data_MySQL_MySQLException_INCLUDED #endif //Data_MySQL_MySQLException_INCLUDED

View File

@ -17,6 +17,7 @@
#ifndef Data_MySQL_MySQLStatementImpl_INCLUDED #ifndef Data_MySQL_MySQLStatementImpl_INCLUDED
#define Data_MySQL_MySQLStatementImpl_INCLUDED #define Data_MySQL_MySQLStatementImpl_INCLUDED
#include "Poco/Data/MySQL/MySQL.h" #include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/MySQL/SessionImpl.h" #include "Poco/Data/MySQL/SessionImpl.h"
#include "Poco/Data/MySQL/Binder.h" #include "Poco/Data/MySQL/Binder.h"
@ -44,7 +45,6 @@ public:
/// Destroys the MySQLStatementImpl. /// Destroys the MySQLStatementImpl.
protected: protected:
virtual std::size_t columnsReturned() const; virtual std::size_t columnsReturned() const;
/// Returns number of columns returned by query. /// Returns number of columns returned by query.
@ -93,7 +93,7 @@ private:
Binder::Ptr _pBinder; Binder::Ptr _pBinder;
Extractor::Ptr _pExtractor; Extractor::Ptr _pExtractor;
int _hasNext; int _hasNext;
}; };
} } } // namespace Poco::Data::MySQL } } } // namespace Poco::Data::MySQL

View File

@ -17,19 +17,29 @@
#ifndef Data_MySQL_ResultMetadata_INCLUDED #ifndef Data_MySQL_ResultMetadata_INCLUDED
#define Data_MySQL_ResultMetadata_INCLUDED #define Data_MySQL_ResultMetadata_INCLUDED
#include <mysql.h> #include <mysql.h>
#include <vector> #include <vector>
#include "Poco/Data/MetaColumn.h" #include "Poco/Data/MetaColumn.h"
#if LIBMYSQL_VERSION_ID >= 80000
typedef bool my_bool; // Workaround to make library work with MySQL client 8.0 as well as earlier versions
typedef char my_boolv; // Workaround for std::vector<bool>
#else
typedef my_bool my_boolv;
#endif
namespace Poco { namespace Poco {
namespace Data { namespace Data {
namespace MySQL { namespace MySQL {
class ResultMetadata class ResultMetadata
/// MySQL result metadata /// MySQL result metadata
{ {
public: public:
void reset(); void reset();
/// Resets the metadata. /// Resets the metadata.
@ -59,9 +69,11 @@ private:
std::vector<MYSQL_BIND> _row; std::vector<MYSQL_BIND> _row;
std::vector<char> _buffer; std::vector<char> _buffer;
std::vector<unsigned long> _lengths; std::vector<unsigned long> _lengths;
std::vector<my_bool> _isNull; std::vector<my_boolv> _isNull; // using char instead of bool to avoid std::vector<bool> disaster
}; };
}}}
} } } // namespace Poco::Data::MySQL
#endif //Data_MySQL_ResultMetadata_INCLUDED #endif //Data_MySQL_ResultMetadata_INCLUDED

View File

@ -17,18 +17,20 @@
#ifndef Data_MySQL_SessionHandle_INCLUDED #ifndef Data_MySQL_SessionHandle_INCLUDED
#define Data_MySQL_SessionHandle_INCLUDED #define Data_MySQL_SessionHandle_INCLUDED
#include <mysql.h> #include <mysql.h>
#include "Poco/Data/MySQL/MySQLException.h" #include "Poco/Data/MySQL/MySQLException.h"
namespace Poco { namespace Poco {
namespace Data { namespace Data {
namespace MySQL { namespace MySQL {
class SessionHandle class SessionHandle
/// MySQL session handle /// MySQL session handle
{ {
public: public:
explicit SessionHandle(MYSQL* mysql); explicit SessionHandle(MYSQL* mysql);
/// Creates session handle /// Creates session handle
@ -71,12 +73,10 @@ public:
operator MYSQL* (); operator MYSQL* ();
private: private:
SessionHandle(const SessionHandle&); SessionHandle(const SessionHandle&);
SessionHandle& operator=(const SessionHandle&); SessionHandle& operator=(const SessionHandle&);
private: private:
MYSQL* _pHandle; MYSQL* _pHandle;
}; };
@ -91,6 +91,7 @@ inline SessionHandle::operator MYSQL* ()
} }
}}} } } } // namespace Poco::Data::MySQL
#endif // Data_MySQL_SessionHandle_INCLUDED #endif // Data_MySQL_SessionHandle_INCLUDED

View File

@ -127,7 +127,6 @@ public:
/// Returns the name of the connector. /// Returns the name of the connector.
private: private:
template <typename T> template <typename T>
static inline T& getValue(MYSQL_BIND* pResult, T& val) static inline T& getValue(MYSQL_BIND* pResult, T& val)
{ {

View File

@ -17,13 +17,16 @@
#ifndef Data_MySQL_StatementHandle_INCLUDED #ifndef Data_MySQL_StatementHandle_INCLUDED
#define Data_MySQL_StatementHandle_INCLUDED #define Data_MySQL_StatementHandle_INCLUDED
#include <mysql.h> #include <mysql.h>
#include "Poco/Data/MySQL/MySQLException.h" #include "Poco/Data/MySQL/MySQLException.h"
namespace Poco { namespace Poco {
namespace Data { namespace Data {
namespace MySQL { namespace MySQL {
class StatementExecutor class StatementExecutor
/// MySQL statement executor. /// MySQL statement executor.
{ {
@ -68,7 +71,6 @@ public:
/// Cast operator to native handle type. /// Cast operator to native handle type.
private: private:
StatementExecutor(const StatementExecutor&); StatementExecutor(const StatementExecutor&);
StatementExecutor& operator=(const StatementExecutor&); StatementExecutor& operator=(const StatementExecutor&);
@ -91,7 +93,7 @@ inline StatementExecutor::operator MYSQL_STMT* ()
} }
}}} } } } // namespace Poco::Data::MySQL
#endif // Data_MySQL_StatementHandle_INCLUDED #endif // Data_MySQL_StatementHandle_INCLUDED

View File

@ -20,10 +20,7 @@
#include "Poco/Data/MySQL/MySQL.h" #include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/Session.h" #include "Poco/Data/Session.h"
#include <mysql.h>
struct st_mysql;
typedef struct st_mysql MYSQL;
namespace Poco { namespace Poco {
@ -35,7 +32,6 @@ class MySQL_API Utility
/// Various utility functions for MySQL. /// Various utility functions for MySQL.
{ {
public: public:
static std::string serverInfo(MYSQL* pHandle); static std::string serverInfo(MYSQL* pHandle);
/// Returns server info. /// Returns server info.

View File

@ -13,10 +13,10 @@
#include "Poco/Data/MySQL/Extractor.h" #include "Poco/Data/MySQL/Extractor.h"
#include "Poco/Data/Date.h" #include "Poco/Data/Date.h"
#include "Poco/Data/Time.h" #include "Poco/Data/Time.h"
namespace Poco { namespace Poco {
namespace Data { namespace Data {
namespace MySQL { namespace MySQL {
@ -240,10 +240,10 @@ bool Extractor::realExtractFixed(std::size_t pos, enum_field_types type, void* b
MYSQL_BIND bind = {0}; MYSQL_BIND bind = {0};
my_bool isNull = 0; my_bool isNull = 0;
bind.is_null = &isNull; bind.is_null = &isNull;
bind.buffer_type = type; bind.buffer_type = type;
bind.buffer = buffer; bind.buffer = buffer;
bind.is_unsigned = isUnsigned; bind.is_unsigned = isUnsigned;
if (!_stmt.fetchColumn(pos, &bind)) if (!_stmt.fetchColumn(pos, &bind))
return false; return false;
@ -637,5 +637,4 @@ bool Extractor::extract(std::size_t , std::list<Dynamic::Var>& )
} }
} } } // namespace Poco::Data::MySQL } } } // namespace Poco::Data::MySQL

View File

@ -14,6 +14,7 @@
#include "Poco/Data/MySQL/MySQLStatementImpl.h" #include "Poco/Data/MySQL/MySQLStatementImpl.h"
namespace Poco { namespace Poco {
namespace Data { namespace Data {
namespace MySQL { namespace MySQL {

View File

@ -16,13 +16,13 @@
#include "Poco/Data/MySQL/MySQLException.h" #include "Poco/Data/MySQL/MySQLException.h"
#include <cstring> #include <cstring>
namespace namespace
{ {
class ResultMetadataHandle class ResultMetadataHandle
/// Simple exception-safe wrapper /// Simple exception-safe wrapper
{ {
public: public:
explicit ResultMetadataHandle(MYSQL_STMT* stmt) explicit ResultMetadataHandle(MYSQL_STMT* stmt)
{ {
h = mysql_stmt_result_metadata(stmt); h = mysql_stmt_result_metadata(stmt);
@ -42,7 +42,6 @@ namespace
} }
private: private:
MYSQL_RES* h; MYSQL_RES* h;
}; };
@ -140,6 +139,7 @@ namespace Poco {
namespace Data { namespace Data {
namespace MySQL { namespace MySQL {
void ResultMetadata::reset() void ResultMetadata::reset()
{ {
_columns.resize(0); _columns.resize(0);
@ -149,6 +149,7 @@ void ResultMetadata::reset()
_isNull.resize(0); _isNull.resize(0);
} }
void ResultMetadata::init(MYSQL_STMT* stmt) void ResultMetadata::init(MYSQL_STMT* stmt)
{ {
ResultMetadataHandle h(stmt); ResultMetadataHandle h(stmt);
@ -199,41 +200,48 @@ void ResultMetadata::init(MYSQL_STMT* stmt)
_row[i].buffer_length = len; _row[i].buffer_length = len;
_row[i].buffer = (len > 0) ? (&_buffer[0] + offset) : 0; _row[i].buffer = (len > 0) ? (&_buffer[0] + offset) : 0;
_row[i].length = &_lengths[i]; _row[i].length = &_lengths[i];
_row[i].is_null = &_isNull[i]; _row[i].is_null = reinterpret_cast<my_bool*>(&_isNull[i]); // workaround to make it work with both MySQL 8 and earlier
_row[i].is_unsigned = (fields[i].flags & UNSIGNED_FLAG) > 0; _row[i].is_unsigned = (fields[i].flags & UNSIGNED_FLAG) > 0;
offset += _row[i].buffer_length; offset += _row[i].buffer_length;
} }
} }
std::size_t ResultMetadata::columnsReturned() const std::size_t ResultMetadata::columnsReturned() const
{ {
return static_cast<std::size_t>(_columns.size()); return static_cast<std::size_t>(_columns.size());
} }
const MetaColumn& ResultMetadata::metaColumn(std::size_t pos) const const MetaColumn& ResultMetadata::metaColumn(std::size_t pos) const
{ {
return _columns[pos]; return _columns[pos];
} }
MYSQL_BIND* ResultMetadata::row() MYSQL_BIND* ResultMetadata::row()
{ {
return &_row[0]; return &_row[0];
} }
std::size_t ResultMetadata::length(std::size_t pos) const std::size_t ResultMetadata::length(std::size_t pos) const
{ {
return _lengths[pos]; return _lengths[pos];
} }
const unsigned char* ResultMetadata::rawData(std::size_t pos) const const unsigned char* ResultMetadata::rawData(std::size_t pos) const
{ {
return reinterpret_cast<const unsigned char*>(_row[pos].buffer); return reinterpret_cast<const unsigned char*>(_row[pos].buffer);
} }
bool ResultMetadata::isNull(std::size_t pos) const bool ResultMetadata::isNull(std::size_t pos) const
{ {
return (_isNull[pos] != 0); return (_isNull[pos] != 0);
} }
}}} // namespace Poco::Data::MySQL
} } } // namespace Poco::Data::MySQL

View File

@ -20,6 +20,11 @@
#endif #endif
#if LIBMYSQL_VERSION_ID >= 80000
typedef bool my_bool; // Workaround to make library work with MySQL client 8.0 as well as earlier versions
#endif
#define POCO_MYSQL_VERSION_NUMBER ((NDB_VERSION_MAJOR<<16) | (NDB_VERSION_MINOR<<8) | (NDB_VERSION_BUILD&0xFF)) #define POCO_MYSQL_VERSION_NUMBER ((NDB_VERSION_MAJOR<<16) | (NDB_VERSION_MINOR<<8) | (NDB_VERSION_BUILD&0xFF))
@ -187,4 +192,4 @@ void SessionHandle::reset()
} }
}}} // Poco::Data::MySQL } } } // namespace Poco::Data::MySQL

View File

@ -129,12 +129,14 @@ void SessionImpl::open(const std::string& connect)
else if (!options["auto-reconnect"].empty()) else if (!options["auto-reconnect"].empty())
throw MySQLException("create session: specify correct auto-reconnect option (true or false) or skip it"); throw MySQLException("create session: specify correct auto-reconnect option (true or false) or skip it");
#ifdef MYSQL_SECURE_AUTH
if (options["secure-auth"] == "true") if (options["secure-auth"] == "true")
_handle.options(MYSQL_SECURE_AUTH, true); _handle.options(MYSQL_SECURE_AUTH, true);
else if (options["secure-auth"] == "false") else if (options["secure-auth"] == "false")
_handle.options(MYSQL_SECURE_AUTH, false); _handle.options(MYSQL_SECURE_AUTH, false);
else if (!options["secure-auth"].empty()) else if (!options["secure-auth"].empty())
throw MySQLException("create session: specify correct secure-auth option (true or false) or skip it"); throw MySQLException("create session: specify correct secure-auth option (true or false) or skip it");
#endif
if (!options["character-set"].empty()) if (!options["character-set"].empty())
_handle.options(MYSQL_SET_CHARSET_NAME, options["character-set"].c_str()); _handle.options(MYSQL_SET_CHARSET_NAME, options["character-set"].c_str());
@ -282,4 +284,4 @@ void SessionImpl::setConnectionTimeout(std::size_t timeout)
} }
}}} } } } // namespace Poco::Data::MySQL

View File

@ -146,4 +146,4 @@ int StatementExecutor::getAffectedRowCount() const
} }
}}} } } } // namespace Poco::Data::MySQL