remove curl

This commit is contained in:
Dario 2019-09-26 11:26:24 +02:00
parent 86a83e3e00
commit e7ca744da0
45 changed files with 5327 additions and 1 deletions

6
.gitmodules vendored
View File

@ -3,4 +3,8 @@
url = https://github.com/jibsen/tinf.git url = https://github.com/jibsen/tinf.git
[submodule "dependencies/iroha-ed25519"] [submodule "dependencies/iroha-ed25519"]
path = dependencies/iroha-ed25519 path = dependencies/iroha-ed25519
url = https://github.com/hyperledger/iroha-ed25519.git url = ssh://git@***REMOVED***/~/Forks/iroha-ed25519
[submodule "dependencies/mariadb-connector-c"]
path = dependencies/mariadb-connector-c
url = https://github.com/MariaDB/mariadb-connector-c.git

1
dependencies/mariadb-connector-c vendored Submodule

@ -0,0 +1 @@
Subproject commit 9ba8e32f6d0fe449114d8eb369cf29303257b460

View File

0
src/cpp/Crypto/KeyPair.h Normal file
View File

View File

View File

View File

@ -0,0 +1,59 @@
#include "LoginPage.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTMLForm.h"
#include "Poco/DeflatingStream.h"
#line 4 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\login.cpsp"
void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
response.setChunkedTransferEncoding(true);
response.setContentType("text/html");
bool _compressResponse(request.hasToken("Accept-Encoding", "gzip"));
if (_compressResponse) response.set("Content-Encoding", "gzip");
Poco::Net::HTMLForm form(request, request.stream());
std::ostream& _responseStream = response.send();
Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1);
std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream;
responseStream << "\n";
responseStream << "<!DOCTYPE html>\n";
responseStream << "<html>\n";
responseStream << "<head>\n";
responseStream << "<meta charset=\"UTF-8\">\n";
responseStream << "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n";
responseStream << "<title>Gradido Login Server: Login</title>\n";
responseStream << "<!--<link rel=\"stylesheet\" type=\"text/css\" href=\"css/styles.min.css\">-->\n";
responseStream << "<link rel=\"stylesheet\" type=\"text/css\" href=\"https://gradido2.dario-rekowski.de/css/styles.css\">\n";
responseStream << "</head>\n";
responseStream << "<body>\n";
responseStream << "<h1>Login</h1>\n";
responseStream << "<form method=\"POST\">\n";
responseStream << "\t<div class=\"grd_container\">\n";
responseStream << "\t\t<fieldset class=\"grd_container_small\">\n";
responseStream << "\t\t\t<legend>Login</legend>\n";
responseStream << "\t\t\t<p>Bitte gebe deine Zugangsdaten ein um dich einzuloggen.</p>\n";
responseStream << "\t\t\t<p class=\"grd_small\">\n";
responseStream << "\t\t\t\t<label for=\"login-email\">E-Mail</label>\n";
responseStream << "\t\t\t\t<input id=\"login-email\" type=\"text\" name=\"login-email\"/>\n";
responseStream << "\t\t\t</p>\n";
responseStream << "\t\t\t<p class=\"grd_small\">\n";
responseStream << "\t\t\t\t<label for=\"login-password\">Passwort</label>\n";
responseStream << "\t\t\t\t<input id=\"login-password\" type=\"password\" name=\"login-password\"/>\n";
responseStream << "\t\t\t</p>\n";
responseStream << "\t\t\t\n";
responseStream << "\t\t</fieldset>\n";
responseStream << "\t\t<input class=\"grd_bn_succeed\" type=\"submit\" name=\"submit\" value=\"Einloggen\">\n";
responseStream << "\t\t<p>Du hast noch keinen Account? Dann folge dem Link um dir einen anzulegen</p>\n";
responseStream << "\t\t<a href=\"/register\">Neuen Account anlegen</a>\n";
responseStream << "\t</div>\n";
responseStream << "</form>\n";
responseStream << "</body>\n";
responseStream << "</html>\n";
if (_compressResponse) _gzipStream.close();
}

View File

@ -0,0 +1,15 @@
#ifndef LoginPage_INCLUDED
#define LoginPage_INCLUDED
#include "Poco/Net/HTTPRequestHandler.h"
class LoginPage: public Poco::Net::HTTPRequestHandler
{
public:
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);
};
#endif // LoginPage_INCLUDED

View File

@ -0,0 +1,112 @@
#include "RegisterPage.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTMLForm.h"
#include "Poco/DeflatingStream.h"
#line 4 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp"
#include "../SingletonManager/SessionManager.h"
void RegisterPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
response.setChunkedTransferEncoding(true);
response.setContentType("text/html");
bool _compressResponse(request.hasToken("Accept-Encoding", "gzip"));
if (_compressResponse) response.set("Content-Encoding", "gzip");
Poco::Net::HTMLForm form(request, request.stream());
std::ostream& _responseStream = response.send();
Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1);
std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream;
responseStream << "\n";
#line 7 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp"
auto session = SessionManager::getInstance()->getNewSession();
bool userReturned = false;
if(!form.empty()) {
userReturned = session->createUser(
form.get("register-name"),
form.get("register-email"),
form.get("register-password"),
form.get("register-key-existing")
);
}
responseStream << "\n";
responseStream << "<!DOCTYPE html>\n";
responseStream << "<html>\n";
responseStream << "<head>\n";
responseStream << "<meta charset=\"UTF-8\">\n";
responseStream << "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n";
responseStream << "<title>Gradido Login Server: Register</title>\n";
responseStream << "<!--<link rel=\"stylesheet\" type=\"text/css\" href=\"css/styles.min.css\">-->\n";
responseStream << "<link rel=\"stylesheet\" type=\"text/css\" href=\"https://gradido2.dario-rekowski.de/css/styles.css\">\n";
responseStream << "<style type=\"text/css\" >\n";
responseStream << "input:not([type='radio']) {\n";
responseStream << "\twidth:200px;\n";
responseStream << "}\n";
responseStream << "label:not(.grd_radio_label) {\n";
responseStream << "\twidth:80px;\n";
responseStream << "\tdisplay:inline-block;\n";
responseStream << "}\n";
responseStream << "</style>\n";
responseStream << "</head>\n";
responseStream << "<body>\n";
responseStream << "<h1>Einen neuen Account anlegen</h1>\n";
responseStream << "\n";
responseStream << "<form method=\"POST\">\n";
responseStream << "\t<div class=\"grd_container\">\n";
responseStream << "\t";
#line 42 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp"
if(!form.empty() && !userReturned) { responseStream << "\n";
responseStream << "\t\t";
#line 43 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp"
responseStream << ( session->getErrorsHtml() );
responseStream << "\n";
responseStream << "\t";
#line 44 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp"
} responseStream << "\n";
responseStream << "\t\t<fieldset class=\"grd_container_small\">\n";
responseStream << "\t\t\t<legend>Account anlegen</legend>\n";
responseStream << "\t\t\t<p>Bitte gebe deine Daten um einen Account anzulegen</p>\n";
responseStream << "\t\t\t<p class=\"grd_small\">\n";
responseStream << "\t\t\t\t<label for=\"register-name\">Vorname</label>\n";
responseStream << "\t\t\t\t<input id=\"register-name\" type=\"text\" name=\"register-name\" value=\"";
#line 50 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp"
responseStream << ( !form.empty() ? form.get("register-name") : "" );
responseStream << "\"/>\n";
responseStream << "\t\t\t</p>\n";
responseStream << "\t\t\t<p class=\"grd_small\">\n";
responseStream << "\t\t\t\t<label for=\"register-email\">E-Mail</label>\n";
responseStream << "\t\t\t\t<input id=\"register-email\" type=\"email\" name=\"register-email\" value=\"";
#line 54 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp"
responseStream << ( !form.empty() ? form.get("register-email") : "" );
responseStream << "\"/>\n";
responseStream << "\t\t\t</p>\n";
responseStream << "\t\t\t<p class=\"grd_small\">\n";
responseStream << "\t\t\t\t<label for=\"register-password\">Passwort</label>\n";
responseStream << "\t\t\t\t<input id=\"register-password\" type=\"password\" name=\"register-password\"/>\n";
responseStream << "\t\t\t</p>\n";
responseStream << "\t\t\t<p>Hast du bereits schonmal ein Gradido Konto besessen?</p>\n";
responseStream << "\t\t\t<p class=\"grd_small\">\n";
responseStream << "\t\t\t\t<input id=\"register-key-new-yes\" type=\"radio\" name=\"register-key\" value=\"yes\" checked/>\n";
responseStream << "\t\t\t\t<label class=\"grd_radio_label\" for=\"register-key-new-yes\">Nein, bitte ein neues erstellen!</label>\n";
responseStream << "\t\t\t</p>\n";
responseStream << "\t\t\t<p class=\"grd_small\">\n";
responseStream << "\t\t\t\t<input id=\"register-key-new-no\" type=\"radio\" name=\"register-key\" value=\"no\"/>\n";
responseStream << "\t\t\t\t<label class=\"grd_radio_label\" for=\"register-key-new-no\">Ja, bitte wiederherstellen!</label>\n";
responseStream << "\t\t\t</p>\n";
responseStream << "\t\t\t<textarea style=\"width:100%;height:100px\" name=\"register-key-existing\">";
#line 69 "I:\\Code\\C++\\Eigene_Projekte\\Gradido_LoginServer\\src\\cpsp\\register.cpsp"
responseStream << ( !form.empty() ? form.get("register-key-existing") : "" );
responseStream << "</textarea>\n";
responseStream << "\t\t</fieldset>\n";
responseStream << "\t\t<input class=\"grd_bn_succeed\" type=\"submit\" name=\"submit\" value=\"Einloggen\">\n";
responseStream << "\t</div>\n";
responseStream << "</form>\n";
responseStream << "</body>\n";
responseStream << "</html>\n";
if (_compressResponse) _gzipStream.close();
}

View File

@ -0,0 +1,15 @@
#ifndef RegisterPage_INCLUDED
#define RegisterPage_INCLUDED
#include "Poco/Net/HTTPRequestHandler.h"
class RegisterPage: public Poco::Net::HTTPRequestHandler
{
public:
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);
};
#endif // RegisterPage_INCLUDED

638
src/cpp/MySQL/Binder.cpp Normal file
View File

@ -0,0 +1,638 @@
//
// MySQLException.cpp
//
// Library: Data/MySQL
// Package: MySQL
// Module: Binder
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/MySQL/Binder.h"
namespace Poco {
namespace Data {
namespace MySQL {
Binder::Binder()
{
}
Binder::~Binder()
{
for (std::vector<MYSQL_TIME*>::iterator it = _dates.begin(); it != _dates.end(); ++it)
{
delete *it;
*it = 0;
}
}
void Binder::bind(std::size_t pos, const Poco::Int8& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_TINY, &val, 0);
}
void Binder::bind(std::size_t pos, const Poco::UInt8& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_TINY, &val, 0, true);
}
void Binder::bind(std::size_t pos, const Poco::Int16& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_SHORT, &val, 0);
}
void Binder::bind(std::size_t pos, const Poco::UInt16& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_SHORT, &val, 0, true);
}
void Binder::bind(std::size_t pos, const Poco::Int32& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONG, &val, 0);
}
void Binder::bind(std::size_t pos, const Poco::UInt32& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONG, &val, 0, true);
}
void Binder::bind(std::size_t pos, const Poco::Int64& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0);
}
void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0, true);
}
#ifndef POCO_LONG_IS_64_BIT
void Binder::bind(std::size_t pos, const long& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONG, &val, 0);
}
void Binder::bind(std::size_t pos, const unsigned long& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONG, &val, 0, true);
}
#endif // POCO_LONG_IS_64_BIT
void Binder::bind(std::size_t pos, const bool& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_TINY, &val, 0);
}
void Binder::bind(std::size_t pos, const float& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_FLOAT, &val, 0);
}
void Binder::bind(std::size_t pos, const double& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_DOUBLE, &val, 0);
}
void Binder::bind(std::size_t pos, const char& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_TINY, &val, 0);
}
void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_STRING, val.c_str(), static_cast<int>(val.length()));
}
void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_BLOB, val.rawContent(), static_cast<int>(val.size()));
}
void Binder::bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_BLOB, val.rawContent(), static_cast<int>(val.size()));
}
void Binder::bind(std::size_t pos, const DateTime& val, Direction dir)
{
poco_assert(dir == PD_IN);
MYSQL_TIME mt = {0};
mt.year = val.year();
mt.month = val.month();
mt.day = val.day();
mt.hour = val.hour();
mt.minute = val.minute();
mt.second = val.second();
mt.second_part = val.millisecond() * 1000 + val.microsecond();
mt.time_type = MYSQL_TIMESTAMP_DATETIME;
_dates.push_back(new MYSQL_TIME(mt));
realBind(pos, MYSQL_TYPE_DATETIME, _dates.back(), sizeof(MYSQL_TIME));
}
void Binder::bind(std::size_t pos, const Date& val, Direction dir)
{
poco_assert(dir == PD_IN);
MYSQL_TIME mt = {0};
mt.year = val.year();
mt.month = val.month();
mt.day = val.day();
mt.time_type = MYSQL_TIMESTAMP_DATE;
_dates.push_back(new MYSQL_TIME(mt));
realBind(pos, MYSQL_TYPE_DATE, _dates.back(), sizeof(MYSQL_TIME));
}
void Binder::bind(std::size_t pos, const Time& val, Direction dir)
{
poco_assert(dir == PD_IN);
MYSQL_TIME mt = {0};
mt.hour = val.hour();
mt.minute = val.minute();
mt.second = val.second();
mt.time_type = MYSQL_TIMESTAMP_TIME;
_dates.push_back(new MYSQL_TIME(mt));
realBind(pos, MYSQL_TYPE_TIME, _dates.back(), sizeof(MYSQL_TIME));
}
void Binder::bind(std::size_t pos, const NullData&, Direction dir)
{
poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_NULL, 0, 0);
}
std::size_t Binder::size() const
{
return static_cast<std::size_t>(_bindArray.size());
}
MYSQL_BIND* Binder::getBindArray() const
{
if (_bindArray.size() == 0)
{
return 0;
}
return const_cast<MYSQL_BIND*>(&_bindArray[0]);
}
/*void Binder::updateDates()
{
for (std::size_t i = 0; i < _dates.size(); i++)
{
switch (_dates[i].mt.time_type)
{
case MYSQL_TIMESTAMP_DATE:
_dates[i].mt.year = _dates[i].link.date->year();
_dates[i].mt.month = _dates[i].link.date->month();
_dates[i].mt.day = _dates[i].link.date->day();
break;
case MYSQL_TIMESTAMP_DATETIME:
_dates[i].mt.year = _dates[i].link.dateTime->year();
_dates[i].mt.month = _dates[i].link.dateTime->month();
_dates[i].mt.day = _dates[i].link.dateTime->day();
_dates[i].mt.hour = _dates[i].link.dateTime->hour();
_dates[i].mt.minute = _dates[i].link.dateTime->minute();
_dates[i].mt.second = _dates[i].link.dateTime->second();
_dates[i].mt.second_part = _dates[i].link.dateTime->millisecond();
break;
case MYSQL_TIMESTAMP_TIME:
_dates[i].mt.hour = _dates[i].link.time->hour();
_dates[i].mt.minute = _dates[i].link.time->minute();
_dates[i].mt.second = _dates[i].link.time->second();
break;
}
}
}*/
///////////////////
//
// Private
//
////////////////////
void Binder::realBind(std::size_t pos, enum_field_types type, const void* buffer, int length, bool isUnsigned)
{
if (pos >= _bindArray.size())
{
std::size_t s = static_cast<std::size_t>(_bindArray.size());
_bindArray.resize(pos + 1);
std::memset(&_bindArray[s], 0, sizeof(MYSQL_BIND) * (_bindArray.size() - s));
}
MYSQL_BIND b = {0};
b.buffer_type = type;
b.buffer = const_cast<void*>(buffer);
b.buffer_length = length;
b.is_unsigned = isUnsigned;
_bindArray[pos] = b;
}
void Binder::bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::Int8>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::Int8>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::UInt8>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::UInt8>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::Int16>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::Int16>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::UInt16>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::UInt16>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::Int32>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::Int32>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::UInt32>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::UInt32>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::Int64>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::Int64>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::UInt64>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::UInt64>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<bool>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<bool>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<bool>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<float>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<float>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<float>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<double>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<double>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<double>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<char>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<char>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<char>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::Data::BLOB>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::Data::BLOB>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::Data::BLOB>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::Data::CLOB>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::Data::CLOB>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::Data::CLOB>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::DateTime>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::DateTime>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::DateTime>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::Data::Date>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::Data::Date>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::Data::Date>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::Data::Time>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::Data::Time>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::Data::Time>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<Poco::Data::NullData>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<Poco::Data::NullData>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<Poco::Data::NullData>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::vector<std::string>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::deque<std::string>& val, Direction dir)
{
throw NotImplementedException();
}
void Binder::bind(std::size_t pos, const std::list<std::string>& val, Direction dir)
{
throw NotImplementedException();
}
} } } // namespace Poco::Data::MySQL

View File

@ -0,0 +1,72 @@
//
// MySQLException.cpp
//
// Library: Data/MySQL
// Package: MySQL
// Module: Connector
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/MySQL/Connector.h"
#include "Poco/Data/MySQL/SessionImpl.h"
#include "Poco/Data/SessionFactory.h"
#include "Poco/Exception.h"
#include <mysql.h>
namespace Poco {
namespace Data {
namespace MySQL {
std::string Connector::KEY("mysql");
Connector::Connector()
{
}
Connector::~Connector()
{
}
const std::string& Connector::name() const
{
return KEY;
}
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString,
std::size_t timeout)
{
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString, timeout));
}
void Connector::registerConnector()
{
if (mysql_library_init(0, 0, 0) != 0)
{
throw Exception("mysql_library_init error");
}
Poco::Data::SessionFactory::instance().add(new Connector());
}
void Connector::unregisterConnector()
{
Poco::Data::SessionFactory::instance().remove(KEY);
mysql_library_end();
}
} } } // namespace Poco::Data::MySQL

641
src/cpp/MySQL/Extractor.cpp Normal file
View File

@ -0,0 +1,641 @@
//
// MySQLException.cpp
//
// Library: Data/MySQL
// Package: MySQL
// Module: Extractor
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/MySQL/Extractor.h"
#include "Poco/Data/Date.h"
#include "Poco/Data/Time.h"
namespace Poco {
namespace Data {
namespace MySQL {
Extractor::Extractor(StatementExecutor& st, ResultMetadata& md): _stmt(st), _metadata(md)
{
}
Extractor::~Extractor()
{
}
bool Extractor::extract(std::size_t pos, Poco::Int8& val)
{
return realExtractFixed(pos, MYSQL_TYPE_TINY, &val);
}
bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
{
return realExtractFixed(pos, MYSQL_TYPE_TINY, &val, true);
}
bool Extractor::extract(std::size_t pos, Poco::Int16& val)
{
return realExtractFixed(pos, MYSQL_TYPE_SHORT, &val);
}
bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
{
return realExtractFixed(pos, MYSQL_TYPE_SHORT, &val, true);
}
bool Extractor::extract(std::size_t pos, Poco::Int32& val)
{
return realExtractFixed(pos, MYSQL_TYPE_LONG, &val);
}
bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
{
return realExtractFixed(pos, MYSQL_TYPE_LONG, &val, true);
}
bool Extractor::extract(std::size_t pos, Poco::Int64& val)
{
return realExtractFixed(pos, MYSQL_TYPE_LONGLONG, &val);
}
bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
{
return realExtractFixed(pos, MYSQL_TYPE_LONGLONG, &val, true);
}
#ifndef POCO_LONG_IS_64_BIT
bool Extractor::extract(std::size_t pos, long& val)
{
return realExtractFixed(pos, MYSQL_TYPE_LONG, &val);
}
bool Extractor::extract(std::size_t pos, unsigned long& val)
{
return realExtractFixed(pos, MYSQL_TYPE_LONG, &val, true);
}
#endif
bool Extractor::extract(std::size_t pos, bool& val)
{
return realExtractFixed(pos, MYSQL_TYPE_TINY, &val);
}
bool Extractor::extract(std::size_t pos, float& val)
{
return realExtractFixed(pos, MYSQL_TYPE_FLOAT, &val);
}
bool Extractor::extract(std::size_t pos, double& val)
{
return realExtractFixed(pos, MYSQL_TYPE_DOUBLE, &val);
}
bool Extractor::extract(std::size_t pos, char& val)
{
return realExtractFixed(pos, MYSQL_TYPE_TINY, &val);
}
bool Extractor::extract(std::size_t pos, std::string& val)
{
if (_metadata.columnsReturned() <= pos)
throw MySQLException("Extractor: attempt to extract more parameters, than query result contain");
if (_metadata.isNull(static_cast<Poco::UInt32>(pos)))
return false;
//mysql reports TEXT types as FDT_BLOB when being extracted
MetaColumn::ColumnDataType columnType = _metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type();
if (columnType != Poco::Data::MetaColumn::FDT_STRING && columnType != Poco::Data::MetaColumn::FDT_BLOB)
throw MySQLException("Extractor: not a string");
val.assign(reinterpret_cast<const char*>(_metadata.rawData(pos)), _metadata.length(pos));
return true;
}
bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
{
if (_metadata.columnsReturned() <= pos)
throw MySQLException("Extractor: attempt to extract more parameters, than query result contain");
if (_metadata.isNull(static_cast<Poco::UInt32>(pos)))
return false;
if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type() != Poco::Data::MetaColumn::FDT_BLOB)
throw MySQLException("Extractor: not a blob");
val.assignRaw(_metadata.rawData(pos), _metadata.length(pos));
return true;
}
bool Extractor::extract(std::size_t pos, Poco::Data::CLOB& val)
{
if (_metadata.columnsReturned() <= pos)
throw MySQLException("Extractor: attempt to extract more parameters, than query result contain");
if (_metadata.isNull(static_cast<Poco::UInt32>(pos)))
return false;
if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type() != Poco::Data::MetaColumn::FDT_BLOB)
throw MySQLException("Extractor: not a blob");
val.assignRaw(reinterpret_cast<const char*>(_metadata.rawData(pos)), _metadata.length(pos));
return true;
}
bool Extractor::extract(std::size_t pos, DateTime& val)
{
MYSQL_TIME mt = {0};
if (!realExtractFixed(pos, MYSQL_TYPE_DATETIME, &mt))
return false;
val.assign(mt.year, mt.month, mt.day, mt.hour, mt.minute, mt.second, mt.second_part / 1000, mt.second_part % 1000);
return true;
}
bool Extractor::extract(std::size_t pos, Date& val)
{
MYSQL_TIME mt = {0};
if (!realExtractFixed(pos, MYSQL_TYPE_DATE, &mt))
return false;
val.assign(mt.year, mt.month, mt.day);
return true;
}
bool Extractor::extract(std::size_t pos, Time& val)
{
MYSQL_TIME mt = {0};
if (!realExtractFixed(pos, MYSQL_TYPE_TIME, &mt))
return false;
val.assign(mt.hour, mt.minute, mt.second);
return true;
}
bool Extractor::extract(std::size_t pos, Any& val)
{
return false;
}
bool Extractor::extract(std::size_t pos, Dynamic::Var& val)
{
return false;
}
bool Extractor::isNull(std::size_t col, std::size_t row)
{
poco_assert(row == POCO_DATA_INVALID_ROW);
if (_metadata.columnsReturned() <= col)
throw MySQLException("Extractor: attempt to extract more parameters, than query result contain");
if (_metadata.isNull(static_cast<Poco::UInt32>(col)))
return true;
return false;
}
void Extractor::reset()
{
AbstractExtractor::reset();
}
bool Extractor::realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, bool isUnsigned)
{
MYSQL_BIND bind = {0};
my_bool isNull = 0;
bind.is_null = &isNull;
bind.buffer_type = type;
bind.buffer = buffer;
bind.is_unsigned = isUnsigned;
if (!_stmt.fetchColumn(pos, &bind))
return false;
return isNull == 0;
}
//////////////
// Not implemented
//////////////
bool Extractor::extract(std::size_t , std::vector<Poco::Int8>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Poco::Int8>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Poco::Int8>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Poco::UInt8>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Poco::UInt8>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Poco::UInt8>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Poco::Int16>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Poco::Int16>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Poco::Int16>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Poco::UInt16>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Poco::UInt16>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Poco::UInt16>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Poco::Int32>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Poco::Int32>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Poco::Int32>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Poco::UInt32>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Poco::UInt32>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Poco::UInt32>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Poco::Int64>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Poco::Int64>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Poco::Int64>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Poco::UInt64>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Poco::UInt64>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Poco::UInt64>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
#ifndef POCO_LONG_IS_64_BIT
bool Extractor::extract(std::size_t , std::vector<long>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<long>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<long>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
#endif
bool Extractor::extract(std::size_t , std::vector<bool>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<bool>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<bool>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<float>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<float>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<float>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<double>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<double>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<double>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<char>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<char>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<char>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<std::string>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<std::string>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<std::string>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<BLOB>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<BLOB>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<BLOB>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<CLOB>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<CLOB>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<CLOB>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<DateTime>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<DateTime>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<DateTime>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Date>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Date>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Date>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Time>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Time>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Time>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Any>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Any>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Any>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::vector<Dynamic::Var>& )
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::deque<Dynamic::Var>& )
{
throw NotImplementedException("std::deque extractor must be implemented.");
}
bool Extractor::extract(std::size_t , std::list<Dynamic::Var>& )
{
throw NotImplementedException("std::list extractor must be implemented.");
}
} } } // namespace Poco::Data::MySQL

View File

@ -0,0 +1,138 @@
//
// MySQLException.cpp
//
// Library: Data/MySQL
// Package: MySQL
// Module: MySQLException
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/MySQL/MySQLException.h"
#include <mysql.h>
#include <stdio.h>
namespace Poco {
namespace Data {
namespace MySQL {
MySQLException::MySQLException(const std::string& msg) : Poco::Data::DataException(std::string("[MySQL]: ") + msg)
{
}
MySQLException::MySQLException(const MySQLException& exc) : Poco::Data::DataException(exc)
{
}
MySQLException::~MySQLException() throw()
{
}
/////
//
// ConnectionException
//
/////
ConnectionException::ConnectionException(const std::string& msg) : MySQLException(msg)
{
}
ConnectionException::ConnectionException(const std::string& text, MYSQL* h) : MySQLException(compose(text, h))
{
}
std::string ConnectionException::compose(const std::string& text, MYSQL* h)
{
std::string str;
str += "[Comment]: ";
str += text;
str += "\t[mysql_error]: ";
str += mysql_error(h);
str += "\t[mysql_errno]: ";
char buff[30];
sprintf(buff, "%d", mysql_errno(h));
str += buff;
str += "\t[mysql_sqlstate]: ";
str += mysql_sqlstate(h);
return str;
}
/////
//
// TransactionException
//
/////
TransactionException::TransactionException(const std::string& msg) : ConnectionException(msg)
{
}
TransactionException::TransactionException(const std::string& text, MYSQL* h) : ConnectionException(text, h)
{
}
/////
//
// StatementException
//
/////
StatementException::StatementException(const std::string& msg) : MySQLException(msg)
{
}
StatementException::StatementException(const std::string& text, MYSQL_STMT* h, const std::string& stmt) : MySQLException(compose(text, h, stmt))
{
}
std::string StatementException::compose(const std::string& text, MYSQL_STMT* h, const std::string& stmt)
{
std::string str;
str += "[Comment]: ";
str += text;
if (h != 0)
{
str += "\t[mysql_stmt_error]: ";
str += mysql_stmt_error(h);
str += "\t[mysql_stmt_errno]: ";
char buff[30];
sprintf(buff, "%d", mysql_stmt_errno(h));
str += buff;
str += "\t[mysql_stmt_sqlstate]: ";
str += mysql_stmt_sqlstate(h);
}
if (stmt.length() > 0)
{
str += "\t[statemnt]: ";
str += stmt;
}
return str;
}
} } } // namespace Poco::Data::MySQL

View File

@ -0,0 +1,160 @@
//
// MySQLException.cpp
//
// Library: Data/MySQL
// Package: MySQL
// Module: MySQLStatementImpl
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/MySQL/MySQLStatementImpl.h"
namespace Poco {
namespace Data {
namespace MySQL {
MySQLStatementImpl::MySQLStatementImpl(SessionImpl& h) :
Poco::Data::StatementImpl(h),
_stmt(h.handle()),
_pBinder(new Binder),
_pExtractor(new Extractor(_stmt, _metadata)),
_hasNext(NEXT_DONTKNOW)
{
}
MySQLStatementImpl::~MySQLStatementImpl()
{
}
std::size_t MySQLStatementImpl::columnsReturned() const
{
return _metadata.columnsReturned();
}
int MySQLStatementImpl::affectedRowCount() const
{
return _stmt.getAffectedRowCount();
}
const MetaColumn& MySQLStatementImpl::metaColumn(std::size_t pos) const
{
return _metadata.metaColumn(pos);
}
bool MySQLStatementImpl::hasNext()
{
if (_hasNext == NEXT_DONTKNOW)
{
if (_metadata.columnsReturned() == 0)
{
return false;
}
if (_stmt.fetch())
{
_hasNext = NEXT_TRUE;
return true;
}
_hasNext = NEXT_FALSE;
return false;
}
else if (_hasNext == NEXT_TRUE)
{
return true;
}
return false;
}
std::size_t MySQLStatementImpl::next()
{
if (!hasNext())
throw StatementException("No data received");
Poco::Data::AbstractExtractionVec::iterator it = extractions().begin();
Poco::Data::AbstractExtractionVec::iterator itEnd = extractions().end();
std::size_t pos = 0;
for (; it != itEnd; ++it)
{
(*it)->extract(pos);
pos += (*it)->numOfColumnsHandled();
}
_hasNext = NEXT_DONTKNOW;
return 1;
}
bool MySQLStatementImpl::canBind() const
{
bool ret = false;
if ((_stmt.state() >= StatementExecutor::STMT_COMPILED) && !bindings().empty())
ret = (*bindings().begin())->canBind();
return ret;
}
bool MySQLStatementImpl::canCompile() const
{
return (_stmt.state() < StatementExecutor::STMT_COMPILED);
}
void MySQLStatementImpl::compileImpl()
{
_metadata.reset();
_stmt.prepare(toString());
_metadata.init(_stmt);
if (_metadata.columnsReturned() > 0)
_stmt.bindResult(_metadata.row());
}
void MySQLStatementImpl::bindImpl()
{
Poco::Data::AbstractBindingVec& binds = bindings();
std::size_t pos = 0;
Poco::Data::AbstractBindingVec::iterator it = binds.begin();
Poco::Data::AbstractBindingVec::iterator itEnd = binds.end();
for (; it != itEnd && (*it)->canBind(); ++it)
{
(*it)->bind(pos);
pos += (*it)->numOfColumnsHandled();
}
_stmt.bindParams(_pBinder->getBindArray(), _pBinder->size());
_stmt.execute();
_hasNext = NEXT_DONTKNOW;
}
Poco::Data::AbstractExtractor::Ptr MySQLStatementImpl::extractor()
{
return _pExtractor;
}
Poco::Data::AbstractBinder::Ptr MySQLStatementImpl::binder()
{
return _pBinder;
}
} } } // namespace Poco::Data::MySQL

262
src/cpp/MySQL/Poco/Binder.h Normal file
View File

@ -0,0 +1,262 @@
//
// Binder.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: Binder
//
// Definition of the Binder class.
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_MySQL_Binder_INCLUDED
#define Data_MySQL_Binder_INCLUDED
#include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/AbstractBinder.h"
#include "Poco/Data/LOB.h"
#include "Poco/Data/MySQL/MySQLException.h"
#ifdef _WIN32
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "shlwapi.lib")
#endif
#include <mysql.h>
namespace Poco {
namespace Data {
namespace MySQL {
class MySQL_API Binder: public Poco::Data::AbstractBinder
/// Binds placeholders in the sql query to the provided values. Performs data types mapping.
{
public:
typedef SharedPtr<Binder> Ptr;
Binder();
/// Creates the Binder.
virtual ~Binder();
/// Destroys the Binder.
virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir);
/// Binds an Int8.
virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir);
/// Binds an UInt8.
virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir);
/// Binds an Int16.
virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir);
/// Binds an UInt16.
virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir);
/// Binds an Int32.
virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir);
/// Binds an UInt32.
virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir);
/// Binds an Int64.
virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir);
/// Binds an UInt64.
#ifndef POCO_LONG_IS_64_BIT
virtual void bind(std::size_t pos, const long& val, Direction dir = PD_IN);
/// Binds a long.
virtual void bind(std::size_t pos, const unsigned long& val, Direction dir = PD_IN);
/// Binds an unsigned long.
#endif // POCO_LONG_IS_64_BIT
virtual void bind(std::size_t pos, const bool& val, Direction dir);
/// Binds a boolean.
virtual void bind(std::size_t pos, const float& val, Direction dir);
/// Binds a float.
virtual void bind(std::size_t pos, const double& val, Direction dir);
/// Binds a double.
virtual void bind(std::size_t pos, const char& val, Direction dir);
/// Binds a single character.
virtual void bind(std::size_t pos, const std::string& val, Direction dir);
/// Binds a string.
virtual void bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir);
/// Binds a BLOB.
virtual void bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir);
/// Binds a CLOB.
virtual void bind(std::size_t pos, const DateTime& val, Direction dir);
/// Binds a DateTime.
virtual void bind(std::size_t pos, const Date& val, Direction dir);
/// Binds a Date.
virtual void bind(std::size_t pos, const Time& val, Direction dir);
/// Binds a Time.
virtual void bind(std::size_t pos, const NullData& val, Direction dir);
/// 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::deque<Poco::Int8>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<Poco::Int8>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<Poco::UInt8>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<Poco::UInt8>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<Poco::Int16>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<Poco::Int16>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<Poco::UInt16>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<Poco::UInt16>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<Poco::Int32>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<Poco::Int32>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<Poco::UInt32>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<Poco::UInt32>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<Poco::Int64>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<Poco::Int64>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<Poco::UInt64>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<Poco::UInt64>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<bool>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<bool>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<bool>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<float>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<float>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<float>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<double>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<double>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<double>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<char>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<char>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<char>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<BLOB>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<BLOB>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<CLOB>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<CLOB>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<CLOB>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<DateTime>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<DateTime>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<Date>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<Date>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<Date>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<Time>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<Time>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<Time>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<NullData>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<NullData>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<NullData>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::vector<std::string>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::deque<std::string>& val, Direction dir = PD_IN);
virtual void bind(std::size_t pos, const std::list<std::string>& val, Direction dir = PD_IN);
std::size_t size() const;
/// Return count of binded parameters
MYSQL_BIND* getBindArray() const;
/// Return array
//void updateDates();
/// Update linked times
private:
Binder(const Binder&);
/// Don't copy the binder
virtual void bind(std::size_t, const char* const&, Direction)
/// Binds a const char ptr.
/// This is a private no-op in this implementation
/// due to security risk.
{
}
void realBind(std::size_t pos, enum_field_types type, const void* buffer, int length, bool isUnsigned = false);
/// Common bind implementation
private:
std::vector<MYSQL_BIND> _bindArray;
std::vector<MYSQL_TIME*> _dates;
};
} } } // namespace Poco::Data::MySQL
#endif // Data_MySQL_Binder_INCLUDED

View File

@ -0,0 +1,61 @@
//
// Connector.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: Connector
//
// Definition of the Connector class.
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_MySQL_Connector_INCLUDED
#define Data_MySQL_Connector_INCLUDED
#include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/Connector.h"
namespace Poco {
namespace Data {
namespace MySQL {
class MySQL_API Connector: public Poco::Data::Connector
/// Connector instantiates MySQL SessionImpl objects.
{
public:
static std::string KEY;
Connector();
/// Creates the Connector.
virtual ~Connector();
/// Destroys the Connector.
virtual const std::string& name() const;
/// Returns the name associated with this connector.
virtual Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString,
std::size_t timeout = Poco::Data::SessionImpl::LOGIN_TIMEOUT_DEFAULT);
/// Creates a MySQL SessionImpl object and initializes it with the given connectionString.
static void registerConnector();
/// Registers the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory
static void unregisterConnector();
/// Unregisters the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory
};
} } } // namespace Poco::Data::MySQL
#endif // Data_MySQL_Connector_INCLUDED

View File

@ -0,0 +1,336 @@
//
// Extractor.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: Extractor
//
// Definition of the Extractor class.
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_MySQL_Extractor_INCLUDED
#define Data_MySQL_Extractor_INCLUDED
#include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/MySQL/StatementExecutor.h"
#include "Poco/Data/MySQL/ResultMetadata.h"
#include "Poco/Data/AbstractExtractor.h"
#include "Poco/Data/LOB.h"
namespace Poco {
namespace Dynamic {
class Var;
}
namespace Data {
namespace MySQL {
class MySQL_API Extractor: public Poco::Data::AbstractExtractor
/// Extracts and converts data values from the result row returned by MySQL.
/// If NULL is received, the incoming val value is not changed and false is returned
{
public:
typedef SharedPtr<Extractor> Ptr;
Extractor(StatementExecutor& st, ResultMetadata& md);
/// Creates the Extractor.
virtual ~Extractor();
/// Destroys the Extractor.
virtual bool extract(std::size_t pos, Poco::Int8& val);
/// Extracts an Int8.
virtual bool extract(std::size_t pos, Poco::UInt8& val);
/// Extracts an UInt8.
virtual bool extract(std::size_t pos, Poco::Int16& val);
/// Extracts an Int16.
virtual bool extract(std::size_t pos, Poco::UInt16& val);
/// Extracts an UInt16.
virtual bool extract(std::size_t pos, Poco::Int32& val);
/// Extracts an Int32.
virtual bool extract(std::size_t pos, Poco::UInt32& val);
/// Extracts an UInt32.
virtual bool extract(std::size_t pos, Poco::Int64& val);
/// Extracts an Int64.
virtual bool extract(std::size_t pos, Poco::UInt64& val);
/// Extracts an UInt64.
#ifndef POCO_LONG_IS_64_BIT
virtual bool extract(std::size_t pos, long& val);
/// Extracts a long. Returns false if null was received.
virtual bool extract(std::size_t pos, unsigned long& val);
/// Extracts an unsigned long. Returns false if null was received.
#endif
virtual bool extract(std::size_t pos, bool& val);
/// Extracts a boolean.
virtual bool extract(std::size_t pos, float& val);
/// Extracts a float.
virtual bool extract(std::size_t pos, double& val);
/// Extracts a double.
virtual bool extract(std::size_t pos, char& val);
/// Extracts a single character.
virtual bool extract(std::size_t pos, std::string& val);
/// Extracts a string.
virtual bool extract(std::size_t pos, Poco::Data::BLOB& val);
/// Extracts a BLOB.
virtual bool extract(std::size_t pos, Poco::Data::CLOB& val);
/// Extracts a CLOB.
virtual bool extract(std::size_t pos, DateTime& val);
/// Extracts a DateTime. Returns false if null was received.
virtual bool extract(std::size_t pos, Date& val);
/// Extracts a Date. Returns false if null was received.
virtual bool extract(std::size_t pos, Time& val);
/// Extracts a Time. Returns false if null was received.
virtual bool extract(std::size_t pos, Any& val);
/// Extracts an Any. Returns false if null was received.
virtual bool extract(std::size_t pos, Dynamic::Var& val);
/// Extracts a Dynamic::Var. Returns false if null was received.
virtual bool isNull(std::size_t col, std::size_t row);
/// Returns true if the value at [col,row] position is null.
virtual void reset();
/// Resets any information internally cached by the extractor.
////////////
// Not implemented extract functions
////////////
virtual bool extract(std::size_t pos, std::vector<Poco::Int8>& val);
/// Extracts an Int8 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::Int8>& val);
/// Extracts an Int8 deque.
virtual bool extract(std::size_t pos, std::list<Poco::Int8>& val);
/// Extracts an Int8 list.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt8>& val);
/// Extracts an UInt8 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt8>& val);
/// Extracts an UInt8 deque.
virtual bool extract(std::size_t pos, std::list<Poco::UInt8>& val);
/// Extracts an UInt8 list.
virtual bool extract(std::size_t pos, std::vector<Poco::Int16>& val);
/// Extracts an Int16 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::Int16>& val);
/// Extracts an Int16 deque.
virtual bool extract(std::size_t pos, std::list<Poco::Int16>& val);
/// Extracts an Int16 list.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt16>& val);
/// Extracts an UInt16 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt16>& val);
/// Extracts an UInt16 deque.
virtual bool extract(std::size_t pos, std::list<Poco::UInt16>& val);
/// Extracts an UInt16 list.
virtual bool extract(std::size_t pos, std::vector<Poco::Int32>& val);
/// Extracts an Int32 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::Int32>& val);
/// Extracts an Int32 deque.
virtual bool extract(std::size_t pos, std::list<Poco::Int32>& val);
/// Extracts an Int32 list.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt32>& val);
/// Extracts an UInt32 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt32>& val);
/// Extracts an UInt32 deque.
virtual bool extract(std::size_t pos, std::list<Poco::UInt32>& val);
/// Extracts an UInt32 list.
virtual bool extract(std::size_t pos, std::vector<Poco::Int64>& val);
/// Extracts an Int64 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::Int64>& val);
/// Extracts an Int64 deque.
virtual bool extract(std::size_t pos, std::list<Poco::Int64>& val);
/// Extracts an Int64 list.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt64>& val);
/// Extracts an UInt64 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt64>& val);
/// Extracts an UInt64 deque.
virtual bool extract(std::size_t pos, std::list<Poco::UInt64>& val);
/// Extracts an UInt64 list.
#ifndef POCO_LONG_IS_64_BIT
virtual bool extract(std::size_t pos, std::vector<long>& val);
/// Extracts a long vector.
virtual bool extract(std::size_t pos, std::deque<long>& val);
/// Extracts a long deque.
virtual bool extract(std::size_t pos, std::list<long>& val);
/// Extracts a long list.
#endif
virtual bool extract(std::size_t pos, std::vector<bool>& val);
/// Extracts a boolean vector.
virtual bool extract(std::size_t pos, std::deque<bool>& val);
/// Extracts a boolean deque.
virtual bool extract(std::size_t pos, std::list<bool>& val);
/// Extracts a boolean list.
virtual bool extract(std::size_t pos, std::vector<float>& val);
/// Extracts a float vector.
virtual bool extract(std::size_t pos, std::deque<float>& val);
/// Extracts a float deque.
virtual bool extract(std::size_t pos, std::list<float>& val);
/// Extracts a float list.
virtual bool extract(std::size_t pos, std::vector<double>& val);
/// Extracts a double vector.
virtual bool extract(std::size_t pos, std::deque<double>& val);
/// Extracts a double deque.
virtual bool extract(std::size_t pos, std::list<double>& val);
/// Extracts a double list.
virtual bool extract(std::size_t pos, std::vector<char>& val);
/// Extracts a character vector.
virtual bool extract(std::size_t pos, std::deque<char>& val);
/// Extracts a character deque.
virtual bool extract(std::size_t pos, std::list<char>& val);
/// Extracts a character list.
virtual bool extract(std::size_t pos, std::vector<std::string>& val);
/// Extracts a string vector.
virtual bool extract(std::size_t pos, std::deque<std::string>& val);
/// Extracts a string deque.
virtual bool extract(std::size_t pos, std::list<std::string>& val);
/// Extracts a string list.
virtual bool extract(std::size_t pos, std::vector<BLOB>& val);
/// Extracts a BLOB vector.
virtual bool extract(std::size_t pos, std::deque<BLOB>& val);
/// Extracts a BLOB deque.
virtual bool extract(std::size_t pos, std::list<BLOB>& val);
/// Extracts a BLOB list.
virtual bool extract(std::size_t pos, std::vector<CLOB>& val);
/// Extracts a CLOB vector.
virtual bool extract(std::size_t pos, std::deque<CLOB>& val);
/// Extracts a CLOB deque.
virtual bool extract(std::size_t pos, std::list<CLOB>& val);
/// Extracts a CLOB list.
virtual bool extract(std::size_t pos, std::vector<DateTime>& val);
/// Extracts a DateTime vector.
virtual bool extract(std::size_t pos, std::deque<DateTime>& val);
/// Extracts a DateTime deque.
virtual bool extract(std::size_t pos, std::list<DateTime>& val);
/// Extracts a DateTime list.
virtual bool extract(std::size_t pos, std::vector<Date>& val);
/// Extracts a Date vector.
virtual bool extract(std::size_t pos, std::deque<Date>& val);
/// Extracts a Date deque.
virtual bool extract(std::size_t pos, std::list<Date>& val);
/// Extracts a Date list.
virtual bool extract(std::size_t pos, std::vector<Time>& val);
/// Extracts a Time vector.
virtual bool extract(std::size_t pos, std::deque<Time>& val);
/// Extracts a Time deque.
virtual bool extract(std::size_t pos, std::list<Time>& val);
/// Extracts a Time list.
virtual bool extract(std::size_t pos, std::vector<Any>& val);
/// Extracts an Any vector.
virtual bool extract(std::size_t pos, std::deque<Any>& val);
/// Extracts an Any deque.
virtual bool extract(std::size_t pos, std::list<Any>& val);
/// Extracts an Any list.
virtual bool extract(std::size_t pos, std::vector<Dynamic::Var>& val);
/// Extracts a Dynamic::Var vector.
virtual bool extract(std::size_t pos, std::deque<Dynamic::Var>& val);
/// Extracts a Dynamic::Var deque.
virtual bool extract(std::size_t pos, std::list<Dynamic::Var>& val);
/// Extracts a Dynamic::Var list.
private:
bool realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, bool isUnsigned = false);
// Prevent VC8 warning "operator= could not be generated"
Extractor& operator=(const Extractor&);
private:
StatementExecutor& _stmt;
ResultMetadata& _metadata;
};
} } } // namespace Poco::Data::MySQL
#endif // Data_MySQL_Extractor_INCLUDED

View File

@ -0,0 +1,60 @@
//
// MySQL.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: MySQL
//
// Basic definitions for the MySQL library.
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef MySQL_MySQL_INCLUDED
#define MySQL_MySQL_INCLUDED
#include "Poco/Foundation.h"
//
// The following block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the ODBC_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// ODBC_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
//
#if defined(_WIN32) && defined(POCO_DLL)
#if defined(MySQL_EXPORTS)
#define MySQL_API __declspec(dllexport)
#else
#define MySQL_API __declspec(dllimport)
#endif
#endif
#if !defined(MySQL_API)
#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
#define MySQL_API __attribute__ ((visibility ("default")))
#else
#define MySQL_API
#endif
#endif
//
// Automatically link Data library.
//
#if defined(_MSC_VER)
#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(MySQL_EXPORTS)
#pragma comment(lib, "PocoDataMySQL" POCO_LIB_SUFFIX)
#endif
#endif
#endif // MySQL_MySQL_INCLUDED

View File

@ -0,0 +1,156 @@
//
// MySQLException.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: MySQLException
//
// Definition of the MySQLException class.
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_MySQL_MySQLException_INCLUDED
#define Data_MySQL_MySQLException_INCLUDED
#include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/DataException.h"
#include <typeinfo>
#include <string>
typedef struct st_mysql MYSQL;
typedef struct st_mysql_stmt MYSQL_STMT;
namespace Poco {
namespace Data {
namespace MySQL {
// End-user include this file and use in code ConnectionException/StatementException
// So it need not know
class MySQL_API MySQLException: public Poco::Data::DataException
/// Base class for all MySQL exceptions
{
public:
MySQLException(const std::string& msg);
/// Creates MySQLException.
MySQLException(const MySQLException& exc);
/// Creates MySQLException.
~MySQLException() throw();
/// Destroys MySQLexception.
MySQLException& operator=(const MySQLException& exc);
/// Assignment operator.
const char* name() const throw();
/// Returns exception name.
const char* className() const throw();
/// Returns the name of the exception class.
Poco::Exception* clone() const;
/// Creates an exact copy of the exception.
///
/// The copy can later be thrown again by
/// invoking rethrow() on it.
void rethrow() const;
/// (Re)Throws the exception.
///
/// This is useful for temporarily storing a
/// copy of an exception (see clone()), then
/// throwing it again.
};
class ConnectionException : public MySQLException
/// ConnectionException
{
public:
ConnectionException(const std::string& msg);
/// Creates ConnectionException from string.
ConnectionException(const std::string& text, MYSQL* h);
/// Creates ConnectionException from string and handle.
private:
static std::string compose(const std::string& text, MYSQL* h);
};
class TransactionException : public ConnectionException
/// TrabsactionException
{
public:
TransactionException(const std::string& msg);
/// Creates TransactionException from string.
TransactionException(const std::string& text, MYSQL* h);
/// Creates TransactionException from string and handle.
};
class StatementException : public MySQLException
/// StatementException
{
public:
StatementException(const std::string& msg);
/// Creates StatementException from string.
StatementException(const std::string& text, MYSQL_STMT* h, const std::string& stmt = "");
/// Creates StatementException from string and handle.
private:
static std::string compose(const std::string& text, MYSQL_STMT* h, const std::string& stmt);
};
//
// inlines
//
inline MySQLException& MySQLException::operator=(const MySQLException& exc)
{
Poco::Data::DataException::operator=(exc);
return *this;
}
inline const char* MySQLException::name() const throw()
{
return "MySQL";
}
inline const char* MySQLException::className() const throw()
{
return typeid(*this).name();
}
inline Poco::Exception* MySQLException::clone() const
{
return new MySQLException(*this);
}
inline void MySQLException::rethrow() const
{
throw *this;
}
} } } // namespace Poco::Data::MySQL
#endif //Data_MySQL_MySQLException_INCLUDED

View File

@ -0,0 +1,102 @@
//
// MySQLstatementImpl.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: MySQLstatementImpl
//
// Definition of the MySQLStatementImpl class.
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_MySQL_MySQLStatementImpl_INCLUDED
#define Data_MySQL_MySQLStatementImpl_INCLUDED
#include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/MySQL/SessionImpl.h"
#include "Poco/Data/MySQL/Binder.h"
#include "Poco/Data/MySQL/Extractor.h"
#include "Poco/Data/MySQL/StatementExecutor.h"
#include "Poco/Data/MySQL/ResultMetadata.h"
#include "Poco/Data/StatementImpl.h"
#include "Poco/SharedPtr.h"
#include "Poco/Format.h"
namespace Poco {
namespace Data {
namespace MySQL {
class MySQL_API MySQLStatementImpl: public Poco::Data::StatementImpl
/// Implements statement functionality needed for MySQL
{
public:
MySQLStatementImpl(SessionImpl& s);
/// Creates the MySQLStatementImpl.
~MySQLStatementImpl();
/// Destroys the MySQLStatementImpl.
protected:
virtual std::size_t columnsReturned() const;
/// Returns number of columns returned by query.
virtual int affectedRowCount() const;
/// Returns the number of affected rows.
/// Used to find out the number of rows affected by insert, delete or update.
virtual const MetaColumn& metaColumn(std::size_t pos) const;
/// Returns column meta data.
virtual bool hasNext();
/// Returns true if a call to next() will return data.
virtual std::size_t next();
/// Retrieves the next row from the resultset.
/// Will throw, if the resultset is empty.
virtual bool canBind() const;
/// Returns true if a valid statement is set and we can bind.
virtual bool canCompile() const;
/// Returns true if another compile is possible.
virtual void compileImpl();
/// Compiles the statement, doesn't bind yet
virtual void bindImpl();
/// Binds parameters
virtual Poco::Data::AbstractExtractor::Ptr extractor();
/// Returns the concrete extractor used by the statement.
virtual Poco::Data::AbstractBinder::Ptr binder();
/// Returns the concrete binder used by the statement.
private:
enum
{
NEXT_DONTKNOW,
NEXT_TRUE,
NEXT_FALSE
};
StatementExecutor _stmt;
ResultMetadata _metadata;
Binder::Ptr _pBinder;
Extractor::Ptr _pExtractor;
int _hasNext;
};
} } } // namespace Poco::Data::MySQL
#endif // Data_MySQL_MySQLStatementImpl_INCLUDED

View File

@ -0,0 +1,67 @@
//
// ResultMetadata.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: ResultMetadata
//
// Definition of the ResultMetadata class.
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_MySQL_ResultMetadata_INCLUDED
#define Data_MySQL_ResultMetadata_INCLUDED
#include <mysql.h>
#include <vector>
#include "Poco/Data/MetaColumn.h"
namespace Poco {
namespace Data {
namespace MySQL {
class ResultMetadata
/// MySQL result metadata
{
public:
void reset();
/// Resets the metadata.
void init(MYSQL_STMT* stmt);
/// Initializes the metadata.
std::size_t columnsReturned() const;
/// Returns the number of columns in resultset.
const MetaColumn& metaColumn(std::size_t pos) const;
/// Returns the reference to the specified metacolumn.
MYSQL_BIND* row();
/// Returns pointer to native row.
std::size_t length(std::size_t pos) const;
/// Returns the length.
const unsigned char* rawData(std::size_t pos) const;
/// Returns raw data.
bool isNull(std::size_t pos) const;
/// Returns true if value at pos is null.
private:
std::vector<MetaColumn> _columns;
std::vector<MYSQL_BIND> _row;
std::vector<char> _buffer;
std::vector<unsigned long> _lengths;
std::vector<my_bool> _isNull;
};
}}}
#endif //Data_MySQL_ResultMetadata_INCLUDED

View File

@ -0,0 +1,93 @@
//
// SesssionHandle.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: SessionHandle
//
// Definition of the SessionHandle class.
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_MySQL_SessionHandle_INCLUDED
#define Data_MySQL_SessionHandle_INCLUDED
#include <mysql.h>
#include "Poco/Data/MySQL/MySQLException.h"
namespace Poco {
namespace Data {
namespace MySQL {
class SessionHandle
/// MySQL session handle
{
public:
explicit SessionHandle(MYSQL* mysql);
/// Creates session handle
~SessionHandle();
/// Destroy handle, close connection
void init(MYSQL* mysql = 0);
/// Initializes the handle iff not initialized.
void options(mysql_option opt);
/// Set connection options
void options(mysql_option opt, bool b);
/// Set connection options
void options(mysql_option opt, const char* c);
/// Set connection options
void options(mysql_option opt, unsigned int i);
/// Set connection options
void connect(const char* host, const char* user, const char* password, const char* db, unsigned int port);
/// Connect to server
void close();
/// Close connection
void startTransaction();
/// Start transaction
void commit();
/// Commit transaction
void rollback();
/// Rollback transaction
operator MYSQL* ();
private:
SessionHandle(const SessionHandle&);
SessionHandle& operator=(const SessionHandle&);
private:
MYSQL* _pHandle;
};
//
// inlines
//
inline SessionHandle::operator MYSQL* ()
{
return _pHandle;
}
}}}
#endif // Data_MySQL_SessionHandle_INCLUDED

View File

@ -0,0 +1,230 @@
//
// SessionImpl.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: SessionImpl
//
// Definition of the SessionImpl class.
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_MySQL_SessionImpl_INCLUDED
#define Data_MySQL_SessionImpl_INCLUDED
#include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/AbstractSessionImpl.h"
#include "Poco/Data/MySQL/SessionHandle.h"
#include "Poco/Data/MySQL/StatementExecutor.h"
#include "Poco/Data/MySQL/ResultMetadata.h"
#include "Poco/Mutex.h"
namespace Poco {
namespace Data {
namespace MySQL {
class MySQL_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
/// Implements SessionImpl interface
{
public:
static const std::string MYSQL_READ_UNCOMMITTED;
static const std::string MYSQL_READ_COMMITTED;
static const std::string MYSQL_REPEATABLE_READ;
static const std::string MYSQL_SERIALIZABLE;
SessionImpl(const std::string& connectionString,
std::size_t loginTimeout = LOGIN_TIMEOUT_DEFAULT);
/// Creates the SessionImpl. Opens a connection to the database
///
/// Connection string format:
/// <str> == <assignment> | <assignment> ';' <str>
/// <assignment> == <name> '=' <value>
/// <name> == 'host' | 'port' | 'user' | 'password' | 'db' } 'compress' | 'auto-reconnect'
/// <value> == [~;]*
///
/// for compress and auto-reconnect correct values are true/false
/// for port - numeric in decimal notation
///
~SessionImpl();
/// Destroys the SessionImpl.
Poco::Data::StatementImpl* createStatementImpl();
/// Returns an MySQL StatementImpl
void open(const std::string& connection = "");
/// Opens a connection to the database.
void close();
/// Closes the connection.
bool isConnected();
/// Returns true if connected, false otherwise.
void setConnectionTimeout(std::size_t timeout);
/// Sets the session connection timeout value.
std::size_t getConnectionTimeout();
/// Returns the session connection timeout value.
void begin();
/// Starts a transaction
void commit();
/// Commits and ends a transaction
void rollback();
/// Aborts a transaction
bool canTransact();
/// Returns true if session has transaction capabilities.
bool isTransaction();
/// Returns true iff a transaction is a transaction is in progress, false otherwise.
void setTransactionIsolation(Poco::UInt32 ti);
/// Sets the transaction isolation level.
Poco::UInt32 getTransactionIsolation();
/// Returns the transaction isolation level.
bool hasTransactionIsolation(Poco::UInt32 ti);
/// Returns true iff the transaction isolation level corresponding
/// to the supplied bitmask is supported.
bool isTransactionIsolation(Poco::UInt32 ti);
/// Returns true iff the transaction isolation level corresponds
/// to the supplied bitmask.
void autoCommit(const std::string&, bool val);
/// Sets autocommit property for the session.
bool isAutoCommit(const std::string& name="");
/// Returns autocommit property value.
void setInsertId(const std::string&, const Poco::Any&);
/// Try to set insert id - do nothing.
Poco::Any getInsertId(const std::string&);
/// Get insert id
SessionHandle& handle();
// Get handle
const std::string& connectorName() const;
/// Returns the name of the connector.
private:
template <typename T>
inline T& getValue(MYSQL_BIND* pResult, T& val)
{
return val = *((T*) pResult->buffer);
}
template <typename T>
T& getSetting(const std::string& name, T& val)
/// Returns required setting.
/// Limited to one setting at a time.
{
StatementExecutor ex(_handle);
ResultMetadata metadata;
metadata.reset();
ex.prepare(Poco::format("SELECT @@%s", name));
metadata.init(ex);
if (metadata.columnsReturned() > 0)
ex.bindResult(metadata.row());
else
throw InvalidArgumentException("No data returned.");
ex.execute(); ex.fetch();
MYSQL_BIND* pResult = metadata.row();
return getValue<T>(pResult, val);
}
std::string _connector;
SessionHandle _handle;
bool _connected;
bool _inTransaction;
std::size_t _timeout;
Poco::FastMutex _mutex;
};
//
// inlines
//
inline bool SessionImpl::canTransact()
{
return true;
}
inline void SessionImpl::setInsertId(const std::string&, const Poco::Any&)
{
}
inline Poco::Any SessionImpl::getInsertId(const std::string&)
{
return Poco::Any(Poco::UInt64(mysql_insert_id(_handle)));
}
inline SessionHandle& SessionImpl::handle()
{
return _handle;
}
inline const std::string& SessionImpl::connectorName() const
{
return _connector;
}
inline bool SessionImpl::isTransaction()
{
return _inTransaction;
}
inline bool SessionImpl::isTransactionIsolation(Poco::UInt32 ti)
{
return getTransactionIsolation() == ti;
}
inline bool SessionImpl::isConnected()
{
return _connected;
}
inline std::size_t SessionImpl::getConnectionTimeout()
{
return _timeout;
}
template <>
inline std::string& SessionImpl::getValue(MYSQL_BIND* pResult, std::string& val)
{
val.assign((char*) pResult->buffer, pResult->buffer_length);
return val;
}
} } } // namespace Poco::Data::MySQL
#endif // Data_MySQL_SessionImpl_INCLUDED

View File

@ -0,0 +1,97 @@
//
// StatementExecutor.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: StatementExecutor
//
// Definition of the StatementExecutor class.
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_MySQL_StatementHandle_INCLUDED
#define Data_MySQL_StatementHandle_INCLUDED
#include <mysql.h>
#include "Poco/Data/MySQL/MySQLException.h"
namespace Poco {
namespace Data {
namespace MySQL {
class StatementExecutor
/// MySQL statement executor.
{
public:
enum State
{
STMT_INITED,
STMT_COMPILED,
STMT_EXECUTED
};
explicit StatementExecutor(MYSQL* mysql);
/// Creates the StatementExecutor.
~StatementExecutor();
/// Destroys the StatementExecutor.
int state() const;
/// Returns the current state.
void prepare(const std::string& query);
/// Prepares the statement for execution.
void bindParams(MYSQL_BIND* params, std::size_t count);
/// Binds the params.
void bindResult(MYSQL_BIND* result);
/// Binds result.
void execute();
/// Executes the statement.
bool fetch();
/// Fetches the data.
bool fetchColumn(std::size_t n, MYSQL_BIND *bind);
/// Fetches the column.
int getAffectedRowCount() const;
operator MYSQL_STMT* ();
/// Cast operator to native handle type.
private:
StatementExecutor(const StatementExecutor&);
StatementExecutor& operator=(const StatementExecutor&);
private:
MYSQL* _pSessionHandle;
MYSQL_STMT* _pHandle;
int _state;
int _affectedRowCount;
std::string _query;
};
//
// inlines
//
inline StatementExecutor::operator MYSQL_STMT* ()
{
return _pHandle;
}
}}}
#endif // Data_MySQL_StatementHandle_INCLUDED

View File

@ -0,0 +1,79 @@
//
// Utility.h
//
// Library: Data/MySQL
// Package: MySQL
// Module: Utility
//
// Definition of Utility.
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef MySQL_Utility_INCLUDED
#define MySQL_Utility_INCLUDED
#include "Poco/Data/MySQL/MySQL.h"
#include "Poco/Data/Session.h"
struct st_mysql;
typedef struct st_mysql MYSQL;
namespace Poco {
namespace Data {
namespace MySQL {
class MySQL_API Utility
/// Various utility functions for MySQL.
{
public:
static std::string serverInfo(MYSQL* pHandle);
/// Returns server info.
static std::string serverInfo(Poco::Data::Session& session);
/// Returns server info.
static unsigned long serverVersion(MYSQL* pHandle);
/// Returns server version.
static unsigned long serverVersion(Poco::Data::Session& session);
/// Returns server version.
static std::string hostInfo(MYSQL* pHandle);
/// Returns host info.
static std::string hostInfo(Poco::Data::Session& session);
/// Returns host info.
static bool hasMicrosecond();
/// Rturns true if microseconds are suported.
static MYSQL* handle(Poco::Data::Session& session);
/// Returns native MySQL handle for the session.
};
//
// inlines
//
inline MYSQL* Utility::handle(Session& session)
{
return Poco::AnyCast<MYSQL*>(session.getProperty("handle"));
}
} } } // namespace Poco::Data::MySQL
#endif // MySQL_Utility_INCLUDED

View File

@ -0,0 +1,239 @@
//
// MySQLException.cpp
//
// Library: Data/MySQL
// Package: MySQL
// Module: ResultMetadata
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/MySQL/ResultMetadata.h"
#include "Poco/Data/MySQL/MySQLException.h"
#include <cstring>
namespace
{
class ResultMetadataHandle
/// Simple exception-safe wrapper
{
public:
explicit ResultMetadataHandle(MYSQL_STMT* stmt)
{
h = mysql_stmt_result_metadata(stmt);
}
~ResultMetadataHandle()
{
if (h)
{
mysql_free_result(h);
}
}
operator MYSQL_RES* ()
{
return h;
}
private:
MYSQL_RES* h;
};
std::size_t fieldSize(const MYSQL_FIELD& field)
/// Convert field MySQL-type and field MySQL-length to actual field length
{
switch (field.type)
{
case MYSQL_TYPE_TINY: return sizeof(char);
case MYSQL_TYPE_SHORT: return sizeof(short);
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG: return sizeof(Poco::Int32);
case MYSQL_TYPE_FLOAT: return sizeof(float);
case MYSQL_TYPE_DOUBLE: return sizeof(double);
case MYSQL_TYPE_LONGLONG: return sizeof(Poco::Int64);
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
return sizeof(MYSQL_TIME);
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
return field.length;
default:
throw Poco::Data::MySQL::StatementException("unknown field type");
}
}
Poco::Data::MetaColumn::ColumnDataType fieldType(const MYSQL_FIELD& field)
/// Convert field MySQL-type to Poco-type
{
bool unsig = ((field.flags & UNSIGNED_FLAG) == UNSIGNED_FLAG);
switch (field.type)
{
case MYSQL_TYPE_TINY:
if (unsig) return Poco::Data::MetaColumn::FDT_UINT8;
return Poco::Data::MetaColumn::FDT_INT8;
case MYSQL_TYPE_SHORT:
if (unsig) return Poco::Data::MetaColumn::FDT_UINT16;
return Poco::Data::MetaColumn::FDT_INT16;
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
if (unsig) return Poco::Data::MetaColumn::FDT_UINT32;
return Poco::Data::MetaColumn::FDT_INT32;
case MYSQL_TYPE_FLOAT:
return Poco::Data::MetaColumn::FDT_FLOAT;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_DOUBLE:
return Poco::Data::MetaColumn::FDT_DOUBLE;
case MYSQL_TYPE_LONGLONG:
if (unsig) return Poco::Data::MetaColumn::FDT_UINT64;
return Poco::Data::MetaColumn::FDT_INT64;
case MYSQL_TYPE_DATE:
return Poco::Data::MetaColumn::FDT_DATE;
case MYSQL_TYPE_TIME:
return Poco::Data::MetaColumn::FDT_TIME;
case MYSQL_TYPE_DATETIME:
return Poco::Data::MetaColumn::FDT_TIMESTAMP;
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
return Poco::Data::MetaColumn::FDT_STRING;
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
return Poco::Data::MetaColumn::FDT_BLOB;
default:
return Poco::Data::MetaColumn::FDT_UNKNOWN;
}
}
} // namespace
namespace Poco {
namespace Data {
namespace MySQL {
void ResultMetadata::reset()
{
_columns.resize(0);
_row.resize(0);
_buffer.resize(0);
_lengths.resize(0);
_isNull.resize(0);
}
void ResultMetadata::init(MYSQL_STMT* stmt)
{
ResultMetadataHandle h(stmt);
if (!h)
{
// all right, it is normal
// querys such an "INSERT INTO" just does not have result at all
reset();
return;
}
std::size_t count = mysql_num_fields(h);
MYSQL_FIELD* fields = mysql_fetch_fields(h);
std::size_t commonSize = 0;
_columns.reserve(count);
{for (std::size_t i = 0; i < count; i++)
{
std::size_t size = fieldSize(fields[i]);
if (size == 0xFFFFFFFF) size = 0;
_columns.push_back(MetaColumn(
i, // position
fields[i].name, // name
fieldType(fields[i]), // type
size, // length
0, // TODO: precision
!IS_NOT_NULL(fields[i].flags) // nullable
));
commonSize += _columns[i].length();
}}
_buffer.resize(commonSize);
_row.resize(count);
_lengths.resize(count);
_isNull.resize(count);
std::size_t offset = 0;
for (std::size_t i = 0; i < count; i++)
{
std::memset(&_row[i], 0, sizeof(MYSQL_BIND));
unsigned int len = static_cast<unsigned int>(_columns[i].length());
_row[i].buffer_type = fields[i].type;
_row[i].buffer_length = len;
_row[i].buffer = (len > 0) ? (&_buffer[0] + offset) : 0;
_row[i].length = &_lengths[i];
_row[i].is_null = &_isNull[i];
_row[i].is_unsigned = (fields[i].flags & UNSIGNED_FLAG) > 0;
offset += _row[i].buffer_length;
}
}
std::size_t ResultMetadata::columnsReturned() const
{
return static_cast<std::size_t>(_columns.size());
}
const MetaColumn& ResultMetadata::metaColumn(std::size_t pos) const
{
return _columns[pos];
}
MYSQL_BIND* ResultMetadata::row()
{
return &_row[0];
}
std::size_t ResultMetadata::length(std::size_t pos) const
{
return _lengths[pos];
}
const unsigned char* ResultMetadata::rawData(std::size_t pos) const
{
return reinterpret_cast<const unsigned char*>(_row[pos].buffer);
}
bool ResultMetadata::isNull(std::size_t pos) const
{
return (_isNull[pos] != 0);
}
}}} // namespace Poco::Data::MySQL

View File

@ -0,0 +1,179 @@
//
// SesssionHandle.cpp
//
// Library: Data/MySQL
// Package: MySQL
// Module: SessionHandle
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/MySQL/SessionHandle.h"
#include "Poco/Data/DataException.h"
#include "Poco/SingletonHolder.h"
#ifdef POCO_OS_FAMILY_UNIX
#include <pthread.h>
#endif
#define POCO_MYSQL_VERSION_NUMBER ((NDB_VERSION_MAJOR<<16) | (NDB_VERSION_MINOR<<8) | (NDB_VERSION_BUILD&0xFF))
namespace Poco {
namespace Data {
namespace MySQL {
#ifdef POCO_OS_FAMILY_UNIX
class ThreadCleanupHelper
{
public:
ThreadCleanupHelper()
{
if (pthread_key_create(&_key, &ThreadCleanupHelper::cleanup) != 0)
throw Poco::SystemException("cannot create TLS key for mysql cleanup");
}
void init()
{
if (pthread_setspecific(_key, reinterpret_cast<void*>(1)))
throw Poco::SystemException("cannot set TLS key for mysql cleanup");
}
static ThreadCleanupHelper& instance()
{
return *_sh.get();
}
static void cleanup(void* data)
{
mysql_thread_end();
}
private:
pthread_key_t _key;
static Poco::SingletonHolder<ThreadCleanupHelper> _sh;
};
Poco::SingletonHolder<ThreadCleanupHelper> ThreadCleanupHelper::_sh;
#endif
SessionHandle::SessionHandle(MYSQL* mysql): _pHandle(0)
{
init(mysql);
#ifdef POCO_OS_FAMILY_UNIX
ThreadCleanupHelper::instance().init();
#endif
}
void SessionHandle::init(MYSQL* mysql)
{
if (!_pHandle)
{
_pHandle = mysql_init(mysql);
if (!_pHandle)
throw ConnectionException("mysql_init error");
}
}
SessionHandle::~SessionHandle()
{
close();
}
void SessionHandle::options(mysql_option opt)
{
if (mysql_options(_pHandle, opt, 0) != 0)
throw ConnectionException("mysql_options error", _pHandle);
}
void SessionHandle::options(mysql_option opt, bool b)
{
my_bool tmp = b;
if (mysql_options(_pHandle, opt, &tmp) != 0)
throw ConnectionException("mysql_options error", _pHandle);
}
void SessionHandle::options(mysql_option opt, const char* c)
{
if (mysql_options(_pHandle, opt, c) != 0)
throw ConnectionException("mysql_options error", _pHandle);
}
void SessionHandle::options(mysql_option opt, unsigned int i)
{
#if (POCO_MYSQL_VERSION_NUMBER < 0x050108)
const char* tmp = (const char *)&i;
#else
const void* tmp = (const void *)&i;
#endif
if (mysql_options(_pHandle, opt, tmp) != 0)
throw ConnectionException("mysql_options error", _pHandle);
}
void SessionHandle::connect(const char* host, const char* user, const char* password, const char* db, unsigned int port)
{
#ifdef HAVE_MYSQL_REAL_CONNECT
if (!mysql_real_connect(_pHandle, host, user, password, db, port, 0, 0))
throw ConnectionFailedException(mysql_error(_pHandle));
#else
if (!mysql_connect(_pHandle, host, user, password))
throw ConnectionFailedException(mysql_error(_pHandle))
#endif
}
void SessionHandle::close()
{
if (_pHandle)
{
mysql_close(_pHandle);
_pHandle = 0;
}
}
void SessionHandle::startTransaction()
{
int rc = mysql_autocommit(_pHandle, false);
if (rc != 0)
{
// retry if connection lost
int err = mysql_errno(_pHandle);
if (err == 2006 /* CR_SERVER_GONE_ERROR */ || err == 2013 /* CR_SERVER_LOST */)
{
rc = mysql_autocommit(_pHandle, false);
}
}
if (rc != 0) throw TransactionException("Start transaction failed.", _pHandle);
}
void SessionHandle::commit()
{
if (mysql_commit(_pHandle) != 0)
throw TransactionException("Commit failed.", _pHandle);
}
void SessionHandle::rollback()
{
if (mysql_rollback(_pHandle) != 0)
throw TransactionException("Rollback failed.", _pHandle);
}
}}} // Poco::Data::MySQL

View File

@ -0,0 +1,277 @@
//
// SessionImpl.cpp
//
// Library: Data/MySQL
// Package: MySQL
// Module: SessionImpl
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/MySQL/SessionImpl.h"
#include "Poco/Data/MySQL/MySQLStatementImpl.h"
#include "Poco/Data/Session.h"
#include "Poco/NumberParser.h"
#include "Poco/String.h"
namespace
{
std::string copyStripped(std::string::const_iterator from, std::string::const_iterator to)
{
// skip leading spaces
while ((from != to) && isspace(*from)) from++;
// skip trailing spaces
while ((from != to) && isspace(*(to - 1))) to--;
return std::string(from, to);
}
}
namespace Poco {
namespace Data {
namespace MySQL {
const std::string SessionImpl::MYSQL_READ_UNCOMMITTED = "READ UNCOMMITTED";
const std::string SessionImpl::MYSQL_READ_COMMITTED = "READ COMMITTED";
const std::string SessionImpl::MYSQL_REPEATABLE_READ = "REPEATABLE READ";
const std::string SessionImpl::MYSQL_SERIALIZABLE = "SERIALIZABLE";
SessionImpl::SessionImpl(const std::string& connectionString, std::size_t loginTimeout) :
Poco::Data::AbstractSessionImpl<SessionImpl>(connectionString, loginTimeout),
_handle(0),
_connected(false),
_inTransaction(false)
{
addProperty("insertId", &SessionImpl::setInsertId, &SessionImpl::getInsertId);
setProperty("handle", static_cast<MYSQL*>(_handle));
open();
}
void SessionImpl::open(const std::string& connect)
{
if (connect != connectionString())
{
if (isConnected())
throw InvalidAccessException("Session already connected");
if (!connect.empty())
setConnectionString(connect);
}
poco_assert_dbg (!connectionString().empty());
_handle.init();
unsigned int timeout = static_cast<unsigned int>(getLoginTimeout());
_handle.options(MYSQL_OPT_CONNECT_TIMEOUT, timeout);
std::map<std::string, std::string> options;
// Default values
options["host"] = "localhost";
options["port"] = "3306";
options["user"] = "";
options["password"] = "";
options["db"] = "";
options["compress"] = "";
options["auto-reconnect"] = "";
options["secure-auth"] = "";
options["character-set"] = "utf8";
const std::string& connString = connectionString();
for (std::string::const_iterator start = connString.begin();;)
{
std::string::const_iterator finish = std::find(start, connString.end(), ';');
std::string::const_iterator middle = std::find(start, finish, '=');
if (middle == finish)
throw MySQLException("create session: bad connection string format, can not find '='");
options[copyStripped(start, middle)] = copyStripped(middle + 1, finish);
if ((finish == connString.end()) || (finish + 1 == connString.end())) break;
start = finish + 1;
}
if (options["user"].empty())
throw MySQLException("create session: specify user name");
const char * db = NULL;
if (!options["db"].empty())
db = options["db"].c_str();
unsigned int port = 0;
if (!NumberParser::tryParseUnsigned(options["port"], port) || 0 == port || port > 65535)
throw MySQLException("create session: specify correct port (numeric in decimal notation)");
if (options["compress"] == "true")
_handle.options(MYSQL_OPT_COMPRESS);
else if (options["compress"] == "false")
;
else if (!options["compress"].empty())
throw MySQLException("create session: specify correct compress option (true or false) or skip it");
if (options["auto-reconnect"] == "true")
_handle.options(MYSQL_OPT_RECONNECT, true);
else if (options["auto-reconnect"] == "false")
_handle.options(MYSQL_OPT_RECONNECT, false);
else if (!options["auto-reconnect"].empty())
throw MySQLException("create session: specify correct auto-reconnect option (true or false) or skip it");
if (options["secure-auth"] == "true")
_handle.options(MYSQL_SECURE_AUTH, true);
else if (options["secure-auth"] == "false")
_handle.options(MYSQL_SECURE_AUTH, false);
else if (!options["secure-auth"].empty())
throw MySQLException("create session: specify correct secure-auth option (true or false) or skip it");
if (!options["character-set"].empty())
_handle.options(MYSQL_SET_CHARSET_NAME, options["character-set"].c_str());
// Real connect
_handle.connect(options["host"].c_str(),
options["user"].c_str(),
options["password"].c_str(),
db,
port);
addFeature("autoCommit",
&SessionImpl::autoCommit,
&SessionImpl::isAutoCommit);
_connected = true;
}
SessionImpl::~SessionImpl()
{
close();
}
Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
{
return new MySQLStatementImpl(*this);
}
void SessionImpl::begin()
{
Poco::FastMutex::ScopedLock l(_mutex);
if (_inTransaction)
throw Poco::InvalidAccessException("Already in transaction.");
_handle.startTransaction();
_inTransaction = true;
}
void SessionImpl::commit()
{
_handle.commit();
_inTransaction = false;
}
void SessionImpl::rollback()
{
_handle.rollback();
_inTransaction = false;
}
void SessionImpl::autoCommit(const std::string&, bool val)
{
StatementExecutor ex(_handle);
ex.prepare(Poco::format("SET autocommit=%d", val ? 1 : 0));
ex.execute();
}
bool SessionImpl::isAutoCommit(const std::string&)
{
int ac = 0;
return 1 == getSetting("autocommit", ac);
}
void SessionImpl::setTransactionIsolation(Poco::UInt32 ti)
{
std::string isolation;
switch (ti)
{
case Session::TRANSACTION_READ_UNCOMMITTED:
isolation = MYSQL_READ_UNCOMMITTED; break;
case Session::TRANSACTION_READ_COMMITTED:
isolation = MYSQL_READ_COMMITTED; break;
case Session::TRANSACTION_REPEATABLE_READ:
isolation = MYSQL_REPEATABLE_READ; break;
case Session::TRANSACTION_SERIALIZABLE:
isolation = MYSQL_SERIALIZABLE; break;
default:
throw Poco::InvalidArgumentException("setTransactionIsolation()");
}
StatementExecutor ex(_handle);
ex.prepare(Poco::format("SET SESSION TRANSACTION ISOLATION LEVEL %s", isolation));
ex.execute();
}
Poco::UInt32 SessionImpl::getTransactionIsolation()
{
std::string isolation;
getSetting("tx_isolation", isolation);
Poco::replaceInPlace(isolation, "-", " ");
if (MYSQL_READ_UNCOMMITTED == isolation)
return Session::TRANSACTION_READ_UNCOMMITTED;
else if (MYSQL_READ_COMMITTED == isolation)
return Session::TRANSACTION_READ_COMMITTED;
else if (MYSQL_REPEATABLE_READ == isolation)
return Session::TRANSACTION_REPEATABLE_READ;
else if (MYSQL_SERIALIZABLE == isolation)
return Session::TRANSACTION_SERIALIZABLE;
throw InvalidArgumentException("getTransactionIsolation()");
}
bool SessionImpl::hasTransactionIsolation(Poco::UInt32 ti)
{
return Session::TRANSACTION_READ_UNCOMMITTED == ti ||
Session::TRANSACTION_READ_COMMITTED == ti ||
Session::TRANSACTION_REPEATABLE_READ == ti ||
Session::TRANSACTION_SERIALIZABLE == ti;
}
void SessionImpl::close()
{
if (_connected)
{
_handle.close();
_connected = false;
}
}
void SessionImpl::setConnectionTimeout(std::size_t timeout)
{
_handle.options(MYSQL_OPT_READ_TIMEOUT, static_cast<unsigned int>(timeout));
_handle.options(MYSQL_OPT_WRITE_TIMEOUT, static_cast<unsigned int>(timeout));
_timeout = timeout;
}
}}}

View File

@ -0,0 +1,148 @@
//
// StatementExecutor.cpp
//
// Library: Data/MySQL
// Package: MySQL
// Module: StatementExecutor
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include <mysql.h>
#include "Poco/Data/MySQL/StatementExecutor.h"
#include "Poco/Format.h"
namespace Poco {
namespace Data {
namespace MySQL {
StatementExecutor::StatementExecutor(MYSQL* mysql)
: _pSessionHandle(mysql)
, _affectedRowCount(0)
{
if (!(_pHandle = mysql_stmt_init(mysql)))
throw StatementException("mysql_stmt_init error");
_state = STMT_INITED;
}
StatementExecutor::~StatementExecutor()
{
mysql_stmt_close(_pHandle);
}
int StatementExecutor::state() const
{
return _state;
}
void StatementExecutor::prepare(const std::string& query)
{
if (_state >= STMT_COMPILED)
{
_state = STMT_COMPILED;
return;
}
int rc = mysql_stmt_prepare(_pHandle, query.c_str(), static_cast<unsigned int>(query.length()));
if (rc != 0)
{
// retry if connection lost
int err = mysql_errno(_pSessionHandle);
if (err == 2006 /* CR_SERVER_GONE_ERROR */ || err == 2013 /* CR_SERVER_LOST */)
{
rc = mysql_stmt_prepare(_pHandle, query.c_str(), static_cast<unsigned int>(query.length()));
}
}
if (rc != 0) throw StatementException("mysql_stmt_prepare error", _pHandle, query);
_query = query;
_state = STMT_COMPILED;
}
void StatementExecutor::bindParams(MYSQL_BIND* params, std::size_t count)
{
if (_state < STMT_COMPILED)
throw StatementException("Statement is not compiled yet");
if (count != mysql_stmt_param_count(_pHandle))
throw StatementException("wrong bind parameters count", 0, _query);
if (count == 0) return;
if (mysql_stmt_bind_param(_pHandle, params) != 0)
throw StatementException("mysql_stmt_bind_param() error ", _pHandle, _query);
}
void StatementExecutor::bindResult(MYSQL_BIND* result)
{
if (_state < STMT_COMPILED)
throw StatementException("Statement is not compiled yet");
if (mysql_stmt_bind_result(_pHandle, result) != 0)
throw StatementException("mysql_stmt_bind_result error ", _pHandle, _query);
}
void StatementExecutor::execute()
{
if (_state < STMT_COMPILED)
throw StatementException("Statement is not compiled yet");
if (mysql_stmt_execute(_pHandle) != 0)
throw StatementException("mysql_stmt_execute error", _pHandle, _query);
_state = STMT_EXECUTED;
my_ulonglong affectedRows = mysql_affected_rows(_pSessionHandle);
if (affectedRows != ((my_ulonglong) - 1))
_affectedRowCount = static_cast<std::size_t>(affectedRows); //Was really a DELETE, UPDATE or INSERT statement
}
bool StatementExecutor::fetch()
{
if (_state < STMT_EXECUTED)
throw StatementException("Statement is not executed yet");
int res = mysql_stmt_fetch(_pHandle);
// we have specified zero buffers for BLOBs, so DATA_TRUNCATED is normal in this case
if ((res != 0) && (res != MYSQL_NO_DATA) && (res != MYSQL_DATA_TRUNCATED))
throw StatementException("mysql_stmt_fetch error", _pHandle, _query);
return (res == 0) || (res == MYSQL_DATA_TRUNCATED);
}
bool StatementExecutor::fetchColumn(std::size_t n, MYSQL_BIND *bind)
{
if (_state < STMT_EXECUTED)
throw StatementException("Statement is not executed yet");
int res = mysql_stmt_fetch_column(_pHandle, bind, static_cast<unsigned int>(n), 0);
if ((res != 0) && (res != MYSQL_NO_DATA))
throw StatementException(Poco::format("mysql_stmt_fetch_column(%z) error", n), _pHandle, _query);
return (res == 0);
}
int StatementExecutor::getAffectedRowCount() const
{
return _affectedRowCount;
}
}}}

66
src/cpp/MySQL/Utility.cpp Normal file
View File

@ -0,0 +1,66 @@
//
// Utility.cpp
//
// Library: Data/MySQL
// Package: MySQL
// Module: Utility
//
// Implementation of Utility
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Data/MySQL/Utility.h"
#include <mysql.h>
namespace Poco {
namespace Data {
namespace MySQL {
std::string Utility::serverInfo(MYSQL* pHandle)
{
std::string info(mysql_get_server_info(pHandle));
return info;
}
std::string Utility::serverInfo(Session& session)
{
std::string info(mysql_get_server_info(handle(session)));
return info;
}
unsigned long Utility::serverVersion(MYSQL* pHandle)
{
return mysql_get_server_version(pHandle);
}
unsigned long Utility::serverVersion(Session& session)
{
return mysql_get_server_version(handle(session));
}
std::string Utility::hostInfo(MYSQL* pHandle)
{
std::string info(mysql_get_host_info(pHandle));
return info;
}
std::string Utility::hostInfo(Session& session)
{
std::string info(mysql_get_host_info(handle(session)));
return info;
}
} } } // namespace Poco::Data::MySQL

View File

@ -0,0 +1,405 @@
#include "ConnectionManager.h"
#include "../Connections/MysqlConnection.h"
#include <sstream>
ConnectThread::ConnectThread(ConnectionManager* parent)
: Thread(true), initMysqlThread(false), mParent(parent)
{
}
ConnectThread::~ConnectThread()
{
}
int ConnectThread::ThreadFunction()
{
if (!initMysqlThread) {
if(mysql_thread_init()) {
printf("error by calling mysql thread init\n");
}
initMysqlThread = true;
}
mDataMutex.lock();
// clean up not longer used connections
while (mConnectionWaitingOnDestroy.size() > 0) {
auto con = mConnectionWaitingOnDestroy.front();
mConnectionWaitingOnDestroy.pop();
mDataMutex.unlock();
delete con;
mDataMutex.lock();
}
// creating new connections
while(mConnectionsWaitingOnConnectCall.size() > 0) {
auto con = mConnectionsWaitingOnConnectCall.front();
mConnectionsWaitingOnConnectCall.pop();
mDataMutex.unlock();
if(!con->connect()) {
//printf("[ConnectThread::ThreadFunction] error connecting with type: %s\n",
//Connection::getConnectionTypeName(con->getType()));
};
mParent->markAsAvailable(con);
mParent->condSignal();
mDataMutex.lock();
}
mDataMutex.unlock();
return 0;
}
void ConnectThread::cleanUpInThread()
{
if (initMysqlThread) {
mysql_thread_end();
initMysqlThread = false;
}
}
void ConnectThread::addConnectionConnect(Connection* connection)
{
mDataMutex.lock();
mConnectionsWaitingOnConnectCall.push(connection);
mDataMutex.unlock();
}
void ConnectThread::addConnectionDestroy(Connection* connection)
{
mDataMutex.lock();
mConnectionWaitingOnDestroy.push(connection);
mDataMutex.unlock();
}
// -----------------------------------------------------------------
// ConnectionManager
// -----------------------------------------------------------------
ConnectionManager* ConnectionManager::getInstance()
{
static ConnectionManager only;
return &only;
}
ConnectionManager::ConnectionManager()
: mConnectionEstablishThread(this), mInitalized(true)
{
}
ConnectionManager::~ConnectionManager()
{
if (mInitalized) {
deinitalize();
}
}
void ConnectionManager::deinitalize()
{
lock();
mInitalized = false;
unlock();
mConnectionEstablishThread.exitThread();
for (auto it = mConnections.begin(); it != mConnections.end(); it++)
{
auto freeConnections = it->second->mFreeConnections;
while (freeConnections.size() > 0) {
delete freeConnections.top();
freeConnections.pop();
}
auto cfg_ptr = it->second->cfg_ptr;
cfg_ptr->removeRef();
if (cfg_ptr->getRef() <= 0) {
delete cfg_ptr;
}
}
mConnections.clear();
mInitalized = false;
}
bool ConnectionManager::addConnectionPool(DRSimpleResourcePtr<Config>* cfg_ptr)
{
if (!mInitalized) {
printf("[ConnectionManager::%s] not initialized any more\n", __FUNCTION__);
return false;
}
if ((*cfg_ptr)->name == std::string("")) {
// getConnectionTypeName
ConnectionConfig* cfg = static_cast<ConnectionConfig*>((Config*)(*cfg_ptr));
(*cfg_ptr)->name = "Connect_";
(*cfg_ptr)->name += Connection::getConnectionTypeName(cfg->type);
if (cfg->type == CONN_MYSQL) {
DBConnectionConfig* db_cfg = static_cast<DBConnectionConfig*>((Config*)(*cfg_ptr));
(*cfg_ptr)->name += "_";
(*cfg_ptr)->name += db_cfg->db;
}
}
DHASH id = (*cfg_ptr)->getHash();
// check if collision
lock();
if (!mInitalized) {
printf("[ConnectionManager::%s] not initialized any more\n", __FUNCTION__);
return false;
}
auto it = mConnections.find(id);
if (it != mConnections.end()) {
unlock();
if ((*it->second->cfg_ptr)->name == (*cfg_ptr)->name) {
printf("connection %s already in there: %s\n", (*cfg_ptr)->name.data(), __FUNCTION__);
return false;
}
else {
printf("Hash Collision detected with %s and %s in %s\n",
(*cfg_ptr)->name.data(), (*it->second->cfg_ptr)->name.data(), __FUNCTION__);
return false;
}
}
unlock();
// try to create connection object
auto con = createConnection(cfg_ptr);
if (!con) {
printf("couldn't create connection with cfg: %s\n", (*cfg_ptr)->name.data());
return false;
}
// create pool
auto pool = new ConnectionPool;
//pool->cfg = cfg;
pool->cfg_ptr = cfg_ptr;
pool->cfg_ptr->addRef();
printf("create new connection pool for connection: %s\n", (*cfg_ptr)->name.data());
lock();
if (!mInitalized) {
printf("[ConnectionManager::%s] not initialized any more\n", __FUNCTION__);
return false;
}
mConnections.insert(std::pair<int, ConnectionPool*>(id, pool));
unlock();
// start connection
if(con) {
mConnectionEstablishThread.addConnectionConnect(con);
mConnectionEstablishThread.condSignal();
}
return true;
}
bool ConnectionManager::markAsAvailable(Connection* con)
{
if (!mInitalized) {
addError(new Error(__FUNCTION__, "not initialized any more"));
return false;
}
DHASH id = con->getHash();
lock();
if (!mInitalized) {
addError(new Error(__FUNCTION__, "not initialized any more"));
return false;
}
auto it = mConnections.find(id);
if (it == mConnections.end()) {
addError(new ParamError(__FUNCTION__, "couldn't find connection pool for id:", id));
delete con;
unlock();
return false;
}
else if (!con->isOpen()) {
if (con->errorCount() > 0) {
it->second->mErrorConnectingAttempts++;
addError(new ParamError(__FUNCTION__, "connection wasn't open and has errors, failed connecting attempt: ", it->second->mErrorConnectingAttempts));
getErrors(con);
unlock();
return false;
}
}
it->second->mFreeConnections.push(con);
checkTime(it->second);
unlock();
return true;
}
void ConnectionManager::checkTime(ConnectionPool* pool)
{
if (!mInitalized) {
addError(new Error(__FUNCTION__, "not initialized any more"));
return;
}
auto currentSize = pool->mFreeConnections.size();
// (re)start timer if at least three unused connections reached
if (pool->mFreeConnectionsCount < 3 && currentSize >= 3) {
pool->mConnectionFreeTimeout.reset();
}
if (currentSize >= 3 && pool->mConnectionFreeTimeout.seconds() > UNUSED_CONNECTION_TIMEOUT_SECONDS) {
// clean one connection and reset timer
auto con = pool->mFreeConnections.top();
pool->mFreeConnections.pop();
currentSize = pool->mFreeConnections.size();
mConnectionEstablishThread.addConnectionDestroy(con);
mConnectionEstablishThread.condSignal();
pool->mConnectionFreeTimeout.reset();
}
pool->mFreeConnectionsCount = currentSize;
}
Connection* ConnectionManager::createConnection(DRSimpleResourcePtr<Config>* cfg_ptr)
{
auto con_cfg = static_cast<ConnectionConfig*>((Config*)(*cfg_ptr));
switch (con_cfg->type) {
case CONN_DEFAULT: return new Connection(cfg_ptr);
case CONN_MYSQL: return new MysqlConnection(cfg_ptr);
}
return nullptr;
}
bool ConnectionManager::isConnectionPool(DHASH id)
{
if (!mInitalized) {
addError(new Error(__FUNCTION__, "not initialized any more"));
return false;
}
lock();
if (!mInitalized) {
addError(new Error(__FUNCTION__, "not initialized any more"));
return false;
}
auto it = mConnections.find(id);
if (it == mConnections.end()) {
unlock();
return false;
}
unlock();
return true;
}
Connection* ConnectionManager::getConnection(DHASH id)
{
if (!mInitalized) {
addError(new Error(__FUNCTION__, "not initialized any more"));
return nullptr;
}
lock();
if (!mInitalized) {
unlock();
addError(new Error(__FUNCTION__, "not initialized any more"));
return nullptr;
}
auto it = mConnections.find(id);
if (it == mConnections.end()) {
addError(new ParamError(__FUNCTION__, "couldn't find connection pool for id:", id));
unlock();
return nullptr;
}
Connection* result = nullptr;
auto pool = it->second;
if (pool->mFreeConnections.size() > 0) {
result = pool->mFreeConnections.top();
pool->mFreeConnections.pop();
checkTime(pool);
}
unlock();
// if pool is empty, create new connection
if (pool->mFreeConnections.size() == 0) {
auto con = createConnection(pool->cfg_ptr);
if (!con) {
addError(new ParamError(__FUNCTION__, "couldn't create connection with cfg:", (*pool->cfg_ptr)->name));
return nullptr;
}
mConnectionEstablishThread.addConnectionConnect(con);
mConnectionEstablishThread.condSignal();
}
// we have get a connection, return
if (result) {
return result;
}
// we haven't get a connection, so we wait
std::unique_lock<std::mutex> lk(mConnectCondMutex);
mConnectCond.wait(lk, [] {return 1; });
lock();
if (!mInitalized) {
unlock();
addError(new Error(__FUNCTION__, "not initialized any more"));
return nullptr;
}
if (pool->mFreeConnections.size() == 0) {
addError(new Error(__FUNCTION__, "no free connection after wait :/"));
unlock();
return nullptr;
}
result = pool->mFreeConnections.top();
pool->mFreeConnections.pop();
checkTime(pool);
unlock();
return result;
}
// int ConnectionManager::connectMysql(
// const char* db,
// const char* username /* = "root"*/,
// const char* pwd /* = nullptr*/,
// const char* url /* = "127.0.0.1" */,
// int port /*= 3306*/ )
// {
//mysqlx://mike:s3cr3t!@localhost:13009
/*std::stringstream urlStream;
urlStream << username;
if (pwd) {
urlStream << ":" << pwd;
}
urlStream << "@" << url;
urlStream << ":" << port;
*/
/*
mysqlx::Session* mysqlSession = nullptr;
try {
mysqlSession = new mysqlx::Session(url, port, username, pwd, db);
}
catch (const char* e) {
printf("[ConnectionManager::connectMysql] catch e: %s\n", e);
return -1;
}
mWorkingMutex.lock();
int handle = mMysqlConnections.size();
mMysqlConnections.insert(std::pair<int, mysqlx::Session*>(handle, mysqlSession));
return handle;
return 0;
}
/*
mysqlx::Session* ConnectionManager::getMysqlConnection(int handle)
{
mysqlx::Session* session = nullptr;
mWorkingMutex.lock();
auto it = mMysqlConnections.find(handle);
if (it != mMysqlConnections.end()) {
session = it->second;
}
mWorkingMutex.unlock();
return session;
}
*/

View File

@ -0,0 +1,104 @@
/*!
*
* \author: einhornimmond
*
* \date: 28.02.19
*
* \brief: manage Connections like mysql or socket connections to another server
*/
#ifndef DR_LUA_WEB_MODULE_CONNECTION_MANAGER_H
#define DR_LUA_WEB_MODULE_CONNECTION_MANAGER_H
#include "../LuaWebModule.h"
#include "../Connections/Connection.h"
#include "../CoreLib/Profiler.h"
#include "../CoreLib/Thread.h"
#include "../CoreLib/DRResourcePtr.h"
#include <queue>
#include <map>
#define UNUSED_CONNECTION_TIMEOUT_SECONDS 2
class ConnectionManager;
class ConnectThread : public Thread
{
public:
ConnectThread(ConnectionManager* parent);
virtual ~ConnectThread();
void addConnectionConnect(Connection* connection);
void addConnectionDestroy(Connection* connection);
protected:
std::mutex mDataMutex;
std::queue<Connection*> mConnectionsWaitingOnConnectCall;
std::queue<Connection*> mConnectionWaitingOnDestroy;
virtual int ThreadFunction();
virtual void cleanUpInThread();
bool initMysqlThread;
ConnectionManager* mParent;
};
class ConnectionManager : public ErrorList
{
friend ConnectThread;
public:
~ConnectionManager();
static ConnectionManager* getInstance();
bool addConnectionPool(DRSimpleResourcePtr<Config>* cfg);
bool markAsAvailable(Connection* con);
bool isConnectionPool(DHASH id);
static Connection* createConnection(DRSimpleResourcePtr<Config>* cfg);
inline Connection* getConnection(const char* name) { return getConnection(DRMakeStringHash(name)); }
Connection* getConnection(DHASH id);
inline void lock() { mWorkingMutex.lock(); }
inline void unlock() { mWorkingMutex.unlock(); }
void deinitalize();
protected:
ConnectionManager();
struct ConnectionPool {
ConnectionPool(): mFreeConnectionsCount(0), mErrorConnectingAttempts(0){}
DRSimpleResourcePtr<Config>* cfg_ptr;
std::stack<Connection*> mFreeConnections;
// used to measure how long at least two connections not used
Profiler mConnectionFreeTimeout;
// only for calculating connection timeout
int mFreeConnectionsCount;
int mErrorConnectingAttempts;
};
void checkTime(ConnectionPool* pool);
// connection Pool
std::map<int, ConnectionPool*> mConnections;
// access mutex
std::mutex mWorkingMutex;
inline void condSignal() { mConnectCond.notify_one(); }
// creating and destroying connections thread
ConnectThread mConnectionEstablishThread;
std::condition_variable mConnectCond;
std::mutex mConnectCondMutex;
bool mInitalized;
};
#endif //DR_LUA_WEB_MODULE_CONNECTION_MANAGER_H

View File

@ -0,0 +1,46 @@
#include "ErrorManager.h"
ErrorManager* ErrorManager::getInstance()
{
static ErrorManager only;
return &only;
}
ErrorManager::ErrorManager()
{
}
ErrorManager::~ErrorManager()
{
for (auto it = mErrorsMap.begin(); it != mErrorsMap.end(); it++) {
for (auto listIt = it->second->begin(); listIt != it->second->end(); listIt++) {
delete *listIt;
}
delete it->second;
}
mErrorsMap.clear();
}
void ErrorManager::addError(Error* error)
{
DHASH id = DRMakeStringHash(error->getFunctionName());
auto it = mErrorsMap.find(id);
std::list<Error*>* list = nullptr;
printf("[ErrorManager::addError] error with function: %s, %s\n", error->getFunctionName(), error->getMessage());
if (it == mErrorsMap.end()) {
list = new std::list<Error *>;
}
else {
list = it->second;
// check if hash collision
if (strcmp((*list->begin())->getFunctionName(), error->getFunctionName()) != 0) {
throw "[ErrorManager::addError] hash collision detected";
}
}
list->push_back(error);
}

View File

@ -0,0 +1,42 @@
/*!
*
* \author: einhornimmond
*
* \date: 28.02.19
*
* \brief: manage error log and store errors for retrieving from lua
*/
#ifndef DR_LUA_WEB_MODULE_ERROR_MANAGER_H
#define DR_LUA_WEB_MODULE_ERROR_MANAGER_H
#include <mutex>
#include <ios>
#include <list>
#include <map>
#include <cstring>
#include "../Error/Error.h"
#include "../CoreLib/DRHash.hpp"
class ErrorManager : public IErrorCollection
{
public:
~ErrorManager();
static ErrorManager* getInstance();
// will called delete on error
virtual void addError(Error* error);
protected:
ErrorManager();
// access mutex
std::mutex mWorkingMutex;
std::map<DHASH, std::list<Error*>*> mErrorsMap;
// how many errors should be stored
};
#endif //DR_LUA_WEB_MODULE_CONNECTION_MANAGER_H

View File

@ -0,0 +1,132 @@
#include "SessionManager.h"
SessionManager* SessionManager::getInstance()
{
static SessionManager only;
return &only;
}
SessionManager::SessionManager()
: mInitalized(true)
{
}
SessionManager::~SessionManager()
{
if (mInitalized) {
deinitalize();
}
}
void SessionManager::deinitalize()
{
mWorkingMutex.lock();
while (mEmptyRequestStack.size()) {
mEmptyRequestStack.pop();
}
for (auto it = mRequestSessionMap.begin(); it != mRequestSessionMap.end(); it++) {
delete it->second;
}
mRequestSessionMap.clear();
mInitalized = false;
mWorkingMutex.unlock();
}
MysqlSession* SessionManager::getNewMysqlSession(int* handle)
{
if (!mInitalized) {
printf("[SessionManager::%s] not initialized any more\n", __FUNCTION__);
return nullptr;
}
// lock
mWorkingMutex.lock();
// check if we have an existing session ready to use
if (mEmptyRequestStack.size() > 0) {
int local_handle = mEmptyRequestStack.top();
mEmptyRequestStack.pop();
auto resultIt = mRequestSessionMap.find(local_handle);
if (resultIt != mRequestSessionMap.end()) {
MysqlSession* result = resultIt->second;
mWorkingMutex.unlock();
if (handle) {
*handle = local_handle;
}
return result;
}
}
else {
// else create new RequestSession Object
int newHandle = mRequestSessionMap.size();
auto requestSession = new MysqlSession(newHandle);
mRequestSessionMap.insert(std::pair<int, MysqlSession*>(newHandle, requestSession));
mWorkingMutex.unlock();
if (handle) {
*handle = newHandle;
}
return requestSession;
}
return nullptr;
}
bool SessionManager::releseMysqlSession(int requestHandleSession)
{
if (!mInitalized) {
printf("[SessionManager::%s] not initialized any more\n", __FUNCTION__);
return false;
}
mWorkingMutex.lock();
auto it = mRequestSessionMap.find(requestHandleSession);
if (it == mRequestSessionMap.end()) {
printf("[SessionManager::releaseRequestSession] requestSession with handle: %d not found\n", requestHandleSession);
mWorkingMutex.unlock();
return false;
}
it->second->reset();
mEmptyRequestStack.push(requestHandleSession);
mWorkingMutex.unlock();
return true;
}
bool SessionManager::isExist(int requestHandleSession)
{
if (!mInitalized) {
printf("[SessionManager::%s] not initialized any more\n", __FUNCTION__);
return false;
}
bool result = false;
mWorkingMutex.lock();
auto it = mRequestSessionMap.find(requestHandleSession);
if (it != mRequestSessionMap.end()) {
result = true;
}
mWorkingMutex.unlock();
return result;
}
MysqlSession* SessionManager::getMysqlSession(int handle)
{
if (!mInitalized) {
printf("[SessionManager::%s] not initialized any more\n", __FUNCTION__);
return nullptr;
}
MysqlSession* result = nullptr;
mWorkingMutex.lock();
auto it = mRequestSessionMap.find(handle);
if (it != mRequestSessionMap.end()) {
result = it->second;
}
mWorkingMutex.unlock();
return result;
}

View File

@ -0,0 +1,50 @@
/*!
*
* \author: einhornimmond
*
* \date: 28.02.19
*
* \brief: manage different session from lua
*/
#ifndef DR_LUA_WEB_MODULE_SESSION_MANAGER_H
#define DR_LUA_WEB_MODULE_SESSION_MANAGER_H
#include "../Session/MysqlSession.h"
#include <mutex>
#include <map>
#include <stack>
class SessionManager
{
public:
~SessionManager();
static SessionManager* getInstance();
MysqlSession* getNewMysqlSession(int* handle = nullptr);
inline bool releseMysqlSession(MysqlSession* requestSession) {
return releseMysqlSession(requestSession->getHandle());
}
bool releseMysqlSession(int requestHandleSession);
bool isExist(int requestHandleSession);
MysqlSession* getMysqlSession(int handle);
void deinitalize();
protected:
SessionManager();
// access mutex
std::mutex mWorkingMutex;
// sessions storage
std::map<int, MysqlSession*> mRequestSessionMap;
std::stack<int> mEmptyRequestStack;
bool mInitalized;
};
#endif //DR_LUA_WEB_MODULE_SESSION_MANAGER_H

29
src/cpp/model/Error.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "Error.h"
Error::Error(const char* functionName, const char* message)
: mFunctionName(functionName), mMessage(message)
{
}
Error::~Error()
{
}
std::string Error::getString()
{
std::stringstream ss;
ss << mFunctionName << ": " << mMessage << std::endl;
return ss.str();
}
std::string ParamError::getString()
{
std::stringstream ss;
ss << mFunctionName << ": " << mMessage << " " << mParam << std::endl;
return ss.str();
}

59
src/cpp/model/Error.h Normal file
View File

@ -0,0 +1,59 @@
/*!
*
* \author: einhornimmond
*
* \date: 07.03.19
*
* \brief: error data
*/
#ifndef DR_LUA_WEB_MODULE_ERROR_ERROR_H
#define DR_LUA_WEB_MODULE_ERROR_ERROR_H
#include <string>
#include <sstream>
class Error
{
public:
Error(const char* functionName, const char* message);
~Error();
const char* getFunctionName() { return mFunctionName.data(); }
const char* getMessage() { return mMessage.data(); }
virtual std::string getString();
protected:
std::string mFunctionName;
std::string mMessage;
};
class ParamError : public Error
{
public:
ParamError(const char* functionName, const char* message, const char* param)
: Error(functionName, message), mParam(param) {}
ParamError(const char* functionName, const char* message, const std::string& param)
: Error(functionName, message), mParam(param) {}
ParamError(const char* functioName, const char* message, int param)
: Error(functioName, message) {
std::stringstream ss;
ss << param;
mParam = ss.str();
}
virtual std::string getString();
protected:
std::string mParam;
};
class IErrorCollection
{
public:
virtual void addError(Error*) = 0;
};
#endif // DR_LUA_WEB_MODULE_ERROR_ERROR_H

View File

@ -0,0 +1,66 @@
#include "ErrorList.h"
ErrorList::ErrorList()
{
}
ErrorList::~ErrorList()
{
while (mErrorStack.size() > 0) {
delete mErrorStack.top();
mErrorStack.pop();
}
}
void ErrorList::addError(Error* error)
{
mErrorStack.push(error);
}
Error* ErrorList::getLastError()
{
if (mErrorStack.size() == 0) {
return nullptr;
}
Error* error = mErrorStack.top();
if (error) {
mErrorStack.pop();
}
return error;
}
void ErrorList::clearErrors()
{
while (mErrorStack.size()) {
auto error = mErrorStack.top();
if (error) {
delete error;
}
mErrorStack.pop();
}
}
int ErrorList::getErrors(ErrorList* send)
{
Error* error = nullptr;
int iCount = 0;
while (error = send->getLastError()) {
addError(error);
iCount++;
}
return iCount;
}
void ErrorList::printErrors()
{
while (mErrorStack.size() > 0) {
auto error = mErrorStack.top();
mErrorStack.pop();
printf(error->getString().data());
delete error;
}
}

44
src/cpp/model/ErrorList.h Normal file
View File

@ -0,0 +1,44 @@
/*!
*
* \author: einhornimmond
*
* \date: 07.03.19
*
* \brief: error
*/
#ifndef DR_LUA_WEB_MODULE_ERROR_ERROR_LIST_H
#define DR_LUA_WEB_MODULE_ERROR_ERROR_LIST_H
#include "Error.h"
#include <stack>
class ErrorList : public IErrorCollection
{
public:
ErrorList();
~ErrorList();
// push error, error will be deleted in deconstructor
virtual void addError(Error* error);
// return error on top of stack, please delete after using
Error* getLastError();
inline size_t errorCount() { return mErrorStack.size(); }
// delete all errors
void clearErrors();
static int moveErrors(ErrorList* recv, ErrorList* send) {
return recv->getErrors(send);
}
int getErrors(ErrorList* send);
void printErrors();
protected:
std::stack<Error*> mErrorStack;
};
#endif // DR_LUA_WEB_MODULE_ERROR_ERROR_LIST_H

13
src/cpp/model/Session.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "Session.h"
Session::Session(int handle)
: mHandleId(handle)
{
}
Session::~Session()
{
}

29
src/cpp/model/Session.h Normal file
View File

@ -0,0 +1,29 @@
/*!
*
* \author: einhornimmond
*
* \date: 02.03.19
*
* \brief: store session data
*/
#ifndef DR_LUA_WEB_MODULE_SESSION_SESSION_H
#define DR_LUA_WEB_MODULE_SESSION_SESSION_H
#include "../Error/ErrorList.h"
class Session : public ErrorList
{
public:
Session(int handle);
~Session();
inline int getHandle() { return mHandleId; }
virtual void reset() = 0;
protected:
int mHandleId;
};
#endif // DR_LUA_WEB_MODULE_SESSION_SESSION_H

0
src/cpp/model/User.cpp Normal file
View File

0
src/cpp/model/User.h Normal file
View File