mirror of https://github.com/Icinga/icinga2.git
Implement shim for libmysqlclient and libpq
This commit is contained in:
parent
90496b5456
commit
2f953d6204
|
@ -139,13 +139,6 @@ set(HAVE_EDITLINE "${EDITLINE_FOUND}")
|
||||||
find_package(Termcap)
|
find_package(Termcap)
|
||||||
set(HAVE_TERMCAP "${TERMCAP_FOUND}")
|
set(HAVE_TERMCAP "${TERMCAP_FOUND}")
|
||||||
|
|
||||||
find_package(PostgreSQL)
|
|
||||||
|
|
||||||
if(PostgreSQL_FOUND)
|
|
||||||
link_directories(${PostgreSQL_LIBRARY_DIRS})
|
|
||||||
include_directories(${PostgreSQL_INCLUDE_DIRS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/lib
|
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/lib
|
||||||
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/lib
|
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/lib
|
||||||
|
|
|
@ -39,11 +39,25 @@ if(ICINGA2_WITH_MYSQL OR ICINGA2_WITH_PGSQL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ICINGA2_WITH_MYSQL)
|
if(ICINGA2_WITH_MYSQL)
|
||||||
|
find_package(MySQL)
|
||||||
|
|
||||||
|
if(MYSQL_FOUND)
|
||||||
add_subdirectory(db_ido_mysql)
|
add_subdirectory(db_ido_mysql)
|
||||||
|
add_subdirectory(mysql_shim)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "You have selected MySQL support, but MySQL could not be found. You can disable the MySQL IDO module using -DICINGA2_WITH_MYSQL=OFF.")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ICINGA2_WITH_PGSQL)
|
if(ICINGA2_WITH_PGSQL)
|
||||||
|
find_package(PostgreSQL)
|
||||||
|
|
||||||
|
if(PostgreSQL_FOUND)
|
||||||
add_subdirectory(db_ido_pgsql)
|
add_subdirectory(db_ido_pgsql)
|
||||||
|
add_subdirectory(pgsql_shim)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "You have selected PostgreSQL support, but PostgreSQL could not be found. You can disable the PostgreSQL IDO module using -DICINGA2_WITH_PGSQL=OFF.")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ICINGA2_WITH_DEMO)
|
if(ICINGA2_WITH_DEMO)
|
||||||
|
|
|
@ -31,7 +31,7 @@ set(base_SOURCES
|
||||||
convert.cpp datetime.cpp datetime.thpp datetime-script.cpp debuginfo.cpp dictionary.cpp dictionary-script.cpp
|
convert.cpp datetime.cpp datetime.thpp datetime-script.cpp debuginfo.cpp dictionary.cpp dictionary-script.cpp
|
||||||
configobject.cpp configobject.thpp configobject-script.cpp configtype.cpp configwriter.cpp dependencygraph.cpp
|
configobject.cpp configobject.thpp configobject-script.cpp configtype.cpp configwriter.cpp dependencygraph.cpp
|
||||||
exception.cpp fifo.cpp filelogger.cpp filelogger.thpp initialize.cpp json.cpp
|
exception.cpp fifo.cpp filelogger.cpp filelogger.thpp initialize.cpp json.cpp
|
||||||
json-script.cpp loader.cpp logger.cpp logger.thpp math-script.cpp
|
json-script.cpp library.cpp loader.cpp logger.cpp logger.thpp math-script.cpp
|
||||||
netstring.cpp networkstream.cpp number.cpp number-script.cpp object.cpp
|
netstring.cpp networkstream.cpp number.cpp number-script.cpp object.cpp
|
||||||
object-script.cpp objecttype.cpp primitivetype.cpp process.cpp ringbuffer.cpp scriptframe.cpp
|
object-script.cpp objecttype.cpp primitivetype.cpp process.cpp ringbuffer.cpp scriptframe.cpp
|
||||||
function.cpp function.thpp function-script.cpp
|
function.cpp function.thpp function-script.cpp
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "base/library.hpp"
|
||||||
|
#include "base/loader.hpp"
|
||||||
|
#include "base/logger.hpp"
|
||||||
|
#include "base/exception.hpp"
|
||||||
|
#include "base/application.hpp"
|
||||||
|
|
||||||
|
using namespace icinga;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the specified library.
|
||||||
|
*
|
||||||
|
* @param name The name of the library.
|
||||||
|
*/
|
||||||
|
Library::Library(const String& name)
|
||||||
|
{
|
||||||
|
String path;
|
||||||
|
#if defined(_WIN32)
|
||||||
|
path = name + ".dll";
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
path = "lib" + name + "." + Application::GetAppSpecVersion() + ".dylib";
|
||||||
|
#else /* __APPLE__ */
|
||||||
|
path = "lib" + name + ".so." + Application::GetAppSpecVersion();
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
Log(LogNotice, "Library")
|
||||||
|
<< "Loading library '" << path << "'";
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
HMODULE hModule = LoadLibrary(path.CStr());
|
||||||
|
|
||||||
|
if (!hModule) {
|
||||||
|
BOOST_THROW_EXCEPTION(win32_error()
|
||||||
|
<< boost::errinfo_api_function("LoadLibrary")
|
||||||
|
<< errinfo_win32_error(GetLastError())
|
||||||
|
<< boost::errinfo_file_name(path));
|
||||||
|
}
|
||||||
|
#else /* _WIN32 */
|
||||||
|
void *hModule = dlopen(path.CStr(), RTLD_NOW | RTLD_GLOBAL);
|
||||||
|
|
||||||
|
if (!hModule) {
|
||||||
|
BOOST_THROW_EXCEPTION(std::runtime_error("Could not load library '" + path + "': " + dlerror()));
|
||||||
|
}
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
Loader::ExecuteDeferredInitializers();
|
||||||
|
|
||||||
|
m_Handle.reset(new LibraryHandle(hModule), [](LibraryHandle *handle) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
FreeLibrary(*handle);
|
||||||
|
#else /* _WIN32 */
|
||||||
|
dlclose(*handle);
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Library::GetSymbolAddress(const String& name) const
|
||||||
|
{
|
||||||
|
if (!m_Handle)
|
||||||
|
BOOST_THROW_EXCEPTION(std::runtime_error("Invalid library handle"));
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
return GetProcAddress(*m_Handle.get(), name.CStr());
|
||||||
|
#else /* _WIN32 */
|
||||||
|
return dlsym(*m_Handle.get(), name.CStr());
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LIBRARY_H
|
||||||
|
#define LIBRARY_H
|
||||||
|
|
||||||
|
#include "base/i2-base.hpp"
|
||||||
|
#include "base/string.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace icinga
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
typedef void *LibraryHandle;
|
||||||
|
#else /* _WIN32 */
|
||||||
|
typedef HMODULE LibraryHandle;
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
class Library
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Library(void) = default;
|
||||||
|
Library(const String& name);
|
||||||
|
|
||||||
|
void *GetSymbolAddress(const String& name) const;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T GetSymbolAddress(const String& name) const
|
||||||
|
{
|
||||||
|
static_assert(!std::is_same<T, void *>::value, "T must not be void *");
|
||||||
|
|
||||||
|
return reinterpret_cast<T>(GetSymbolAddress(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<LibraryHandle> m_Handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LIBRARY_H */
|
|
@ -18,6 +18,9 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "base/loader.hpp"
|
#include "base/loader.hpp"
|
||||||
|
#include "base/logger.hpp"
|
||||||
|
#include "base/exception.hpp"
|
||||||
|
#include "base/application.hpp"
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
|
|
|
@ -842,7 +842,6 @@ ExpressionResult LibraryExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dh
|
||||||
|
|
||||||
Log(LogNotice, "config")
|
Log(LogNotice, "config")
|
||||||
<< "Ignoring explicit load request for library \"" << libres << "\".";
|
<< "Ignoring explicit load request for library \"" << libres << "\".";
|
||||||
//Loader::LoadExtensionLibrary(libres.GetValue());
|
|
||||||
|
|
||||||
return Empty;
|
return Empty;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,6 @@
|
||||||
# along with this program; if not, write to the Free Software Foundation
|
# along with this program; if not, write to the Free Software Foundation
|
||||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
find_package(MySQL)
|
|
||||||
|
|
||||||
if(MYSQL_FOUND)
|
|
||||||
mkclass_target(idomysqlconnection.ti idomysqlconnection.tcpp idomysqlconnection.thpp)
|
mkclass_target(idomysqlconnection.ti idomysqlconnection.tcpp idomysqlconnection.thpp)
|
||||||
|
|
||||||
set(db_ido_mysql_SOURCES
|
set(db_ido_mysql_SOURCES
|
||||||
|
@ -31,7 +28,8 @@ if(MYSQL_FOUND)
|
||||||
add_library(db_ido_mysql STATIC ${db_ido_mysql_SOURCES})
|
add_library(db_ido_mysql STATIC ${db_ido_mysql_SOURCES})
|
||||||
|
|
||||||
include_directories(${MYSQL_INCLUDE_DIR})
|
include_directories(${MYSQL_INCLUDE_DIR})
|
||||||
target_link_libraries(db_ido_mysql ${Boost_LIBRARIES} ${MYSQL_LIB} base config icinga db_ido)
|
|
||||||
|
target_link_libraries(db_ido_mysql ${Boost_LIBRARIES} base config icinga db_ido)
|
||||||
|
|
||||||
set_target_properties (
|
set_target_properties (
|
||||||
db_ido_mysql PROPERTIES
|
db_ido_mysql PROPERTIES
|
||||||
|
@ -56,6 +54,3 @@ if(MYSQL_FOUND)
|
||||||
)
|
)
|
||||||
|
|
||||||
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}" PARENT_SCOPE)
|
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}" PARENT_SCOPE)
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "You have selected MySQL support, but MySQL could not be found. You can disable the MySQL IDO module using -DICINGA2_WITH_MYSQL=OFF.")
|
|
||||||
endif()
|
|
||||||
|
|
|
@ -46,6 +46,14 @@ void IdoMysqlConnection::OnConfigLoaded(void)
|
||||||
ObjectImpl<IdoMysqlConnection>::OnConfigLoaded();
|
ObjectImpl<IdoMysqlConnection>::OnConfigLoaded();
|
||||||
|
|
||||||
m_QueryQueue.SetName("IdoMysqlConnection, " + GetName());
|
m_QueryQueue.SetName("IdoMysqlConnection, " + GetName());
|
||||||
|
|
||||||
|
Library shimLibrary{"mysql_shim"};
|
||||||
|
|
||||||
|
auto create_mysql_shim = shimLibrary.GetSymbolAddress<create_mysql_shim_ptr>("create_mysql_shim");
|
||||||
|
|
||||||
|
m_Mysql.reset(create_mysql_shim());
|
||||||
|
|
||||||
|
std::swap(m_Library, shimLibrary);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdoMysqlConnection::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
|
void IdoMysqlConnection::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
|
||||||
|
@ -98,7 +106,7 @@ void IdoMysqlConnection::Resume(void)
|
||||||
m_ReconnectTimer->Start();
|
m_ReconnectTimer->Start();
|
||||||
m_ReconnectTimer->Reschedule(0);
|
m_ReconnectTimer->Reschedule(0);
|
||||||
|
|
||||||
ASSERT(mysql_thread_safe());
|
ASSERT(m_Mysql->thread_safe());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdoMysqlConnection::Pause(void)
|
void IdoMysqlConnection::Pause(void)
|
||||||
|
@ -127,7 +135,7 @@ void IdoMysqlConnection::ExceptionHandler(boost::exception_ptr exp)
|
||||||
<< "Exception during database operation: " << DiagnosticInformation(exp);
|
<< "Exception during database operation: " << DiagnosticInformation(exp);
|
||||||
|
|
||||||
if (GetConnected()) {
|
if (GetConnected()) {
|
||||||
mysql_close(&m_Connection);
|
m_Mysql->close(&m_Connection);
|
||||||
|
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +154,7 @@ void IdoMysqlConnection::Disconnect(void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Query("COMMIT");
|
Query("COMMIT");
|
||||||
mysql_close(&m_Connection);
|
m_Mysql->close(&m_Connection);
|
||||||
|
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
}
|
}
|
||||||
|
@ -205,10 +213,10 @@ void IdoMysqlConnection::Reconnect(void)
|
||||||
|
|
||||||
if (GetConnected()) {
|
if (GetConnected()) {
|
||||||
/* Check if we're really still connected */
|
/* Check if we're really still connected */
|
||||||
if (mysql_ping(&m_Connection) == 0)
|
if (m_Mysql->ping(&m_Connection) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mysql_close(&m_Connection);
|
m_Mysql->close(&m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
reconnect = true;
|
reconnect = true;
|
||||||
}
|
}
|
||||||
|
@ -249,7 +257,7 @@ void IdoMysqlConnection::Reconnect(void)
|
||||||
sslCipher = (!isslCipher.IsEmpty()) ? isslCipher.CStr() : nullptr;
|
sslCipher = (!isslCipher.IsEmpty()) ? isslCipher.CStr() : nullptr;
|
||||||
|
|
||||||
/* connection */
|
/* connection */
|
||||||
if (!mysql_init(&m_Connection)) {
|
if (!m_Mysql->init(&m_Connection)) {
|
||||||
Log(LogCritical, "IdoMysqlConnection")
|
Log(LogCritical, "IdoMysqlConnection")
|
||||||
<< "mysql_init() failed: out of memory";
|
<< "mysql_init() failed: out of memory";
|
||||||
|
|
||||||
|
@ -257,14 +265,14 @@ void IdoMysqlConnection::Reconnect(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableSsl)
|
if (enableSsl)
|
||||||
mysql_ssl_set(&m_Connection, sslKey, sslCert, sslCa, sslCaPath, sslCipher);
|
m_Mysql->ssl_set(&m_Connection, sslKey, sslCert, sslCa, sslCaPath, sslCipher);
|
||||||
|
|
||||||
if (!mysql_real_connect(&m_Connection, host, user, passwd, db, port, socket_path, CLIENT_FOUND_ROWS | CLIENT_MULTI_STATEMENTS)) {
|
if (!m_Mysql->real_connect(&m_Connection, host, user, passwd, db, port, socket_path, CLIENT_FOUND_ROWS | CLIENT_MULTI_STATEMENTS)) {
|
||||||
Log(LogCritical, "IdoMysqlConnection")
|
Log(LogCritical, "IdoMysqlConnection")
|
||||||
<< "Connection to database '" << db << "' with user '" << user << "' on '" << host << ":" << port
|
<< "Connection to database '" << db << "' with user '" << user << "' on '" << host << ":" << port
|
||||||
<< "' " << (enableSsl ? "(SSL enabled) " : "") << "failed: \"" << mysql_error(&m_Connection) << "\"";
|
<< "' " << (enableSsl ? "(SSL enabled) " : "") << "failed: \"" << m_Mysql->error(&m_Connection) << "\"";
|
||||||
|
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error(mysql_error(&m_Connection)));
|
BOOST_THROW_EXCEPTION(std::runtime_error(m_Mysql->error(&m_Connection)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SetConnected(true);
|
SetConnected(true);
|
||||||
|
@ -286,7 +294,7 @@ void IdoMysqlConnection::Reconnect(void)
|
||||||
row = FetchRow(result);
|
row = FetchRow(result);
|
||||||
|
|
||||||
if (!row) {
|
if (!row) {
|
||||||
mysql_close(&m_Connection);
|
m_Mysql->close(&m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
|
|
||||||
Log(LogCritical, "IdoMysqlConnection", "Schema does not provide any valid version! Verify your schema installation.");
|
Log(LogCritical, "IdoMysqlConnection", "Schema does not provide any valid version! Verify your schema installation.");
|
||||||
|
@ -301,7 +309,7 @@ void IdoMysqlConnection::Reconnect(void)
|
||||||
SetSchemaVersion(version);
|
SetSchemaVersion(version);
|
||||||
|
|
||||||
if (Utility::CompareVersion(IDO_COMPAT_SCHEMA_VERSION, version) < 0) {
|
if (Utility::CompareVersion(IDO_COMPAT_SCHEMA_VERSION, version) < 0) {
|
||||||
mysql_close(&m_Connection);
|
m_Mysql->close(&m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
|
|
||||||
Log(LogCritical, "IdoMysqlConnection")
|
Log(LogCritical, "IdoMysqlConnection")
|
||||||
|
@ -358,7 +366,7 @@ void IdoMysqlConnection::Reconnect(void)
|
||||||
<< "Last update by '" << endpoint_name << "' was " << status_update_age << "s ago.";
|
<< "Last update by '" << endpoint_name << "' was " << status_update_age << "s ago.";
|
||||||
|
|
||||||
if (status_update_age < GetFailoverTimeout()) {
|
if (status_update_age < GetFailoverTimeout()) {
|
||||||
mysql_close(&m_Connection);
|
m_Mysql->close(&m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
SetShouldConnect(false);
|
SetShouldConnect(false);
|
||||||
|
|
||||||
|
@ -370,7 +378,7 @@ void IdoMysqlConnection::Reconnect(void)
|
||||||
Log(LogNotice, "IdoMysqlConnection")
|
Log(LogNotice, "IdoMysqlConnection")
|
||||||
<< "Local endpoint '" << my_endpoint->GetName() << "' is not authoritative, bailing out.";
|
<< "Local endpoint '" << my_endpoint->GetName() << "' is not authoritative, bailing out.";
|
||||||
|
|
||||||
mysql_close(&m_Connection);
|
m_Mysql->close(&m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -533,15 +541,15 @@ void IdoMysqlConnection::FinishAsyncQueries(void)
|
||||||
|
|
||||||
String query = querybuf.str();
|
String query = querybuf.str();
|
||||||
|
|
||||||
if (mysql_query(&m_Connection, query.CStr()) != 0) {
|
if (m_Mysql->query(&m_Connection, query.CStr()) != 0) {
|
||||||
std::ostringstream msgbuf;
|
std::ostringstream msgbuf;
|
||||||
String message = mysql_error(&m_Connection);
|
String message = m_Mysql->error(&m_Connection);
|
||||||
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
|
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
|
||||||
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
|
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
|
||||||
|
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
database_error()
|
database_error()
|
||||||
<< errinfo_message(mysql_error(&m_Connection))
|
<< errinfo_message(m_Mysql->error(&m_Connection))
|
||||||
<< errinfo_database_query(query)
|
<< errinfo_database_query(query)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -549,40 +557,40 @@ void IdoMysqlConnection::FinishAsyncQueries(void)
|
||||||
for (std::vector<IdoAsyncQuery>::size_type i = offset; i < offset + count; i++) {
|
for (std::vector<IdoAsyncQuery>::size_type i = offset; i < offset + count; i++) {
|
||||||
const IdoAsyncQuery& aq = queries[i];
|
const IdoAsyncQuery& aq = queries[i];
|
||||||
|
|
||||||
MYSQL_RES *result = mysql_store_result(&m_Connection);
|
MYSQL_RES *result = m_Mysql->store_result(&m_Connection);
|
||||||
|
|
||||||
m_AffectedRows = mysql_affected_rows(&m_Connection);
|
m_AffectedRows = m_Mysql->affected_rows(&m_Connection);
|
||||||
|
|
||||||
IdoMysqlResult iresult;
|
IdoMysqlResult iresult;
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
if (mysql_field_count(&m_Connection) > 0) {
|
if (m_Mysql->field_count(&m_Connection) > 0) {
|
||||||
std::ostringstream msgbuf;
|
std::ostringstream msgbuf;
|
||||||
String message = mysql_error(&m_Connection);
|
String message = m_Mysql->error(&m_Connection);
|
||||||
msgbuf << "Error \"" << message << "\" when executing query \"" << aq.Query << "\"";
|
msgbuf << "Error \"" << message << "\" when executing query \"" << aq.Query << "\"";
|
||||||
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
|
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
|
||||||
|
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
database_error()
|
database_error()
|
||||||
<< errinfo_message(mysql_error(&m_Connection))
|
<< errinfo_message(m_Mysql->error(&m_Connection))
|
||||||
<< errinfo_database_query(query)
|
<< errinfo_database_query(query)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
iresult = IdoMysqlResult(result, std::ptr_fun(mysql_free_result));
|
iresult = IdoMysqlResult(result, std::bind(&MysqlInterface::free_result, std::cref(m_Mysql), _1));
|
||||||
|
|
||||||
if (aq.Callback)
|
if (aq.Callback)
|
||||||
aq.Callback(iresult);
|
aq.Callback(iresult);
|
||||||
|
|
||||||
if (mysql_next_result(&m_Connection) > 0) {
|
if (m_Mysql->next_result(&m_Connection) > 0) {
|
||||||
std::ostringstream msgbuf;
|
std::ostringstream msgbuf;
|
||||||
String message = mysql_error(&m_Connection);
|
String message = m_Mysql->error(&m_Connection);
|
||||||
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
|
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
|
||||||
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
|
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
|
||||||
|
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
database_error()
|
database_error()
|
||||||
<< errinfo_message(mysql_error(&m_Connection))
|
<< errinfo_message(m_Mysql->error(&m_Connection))
|
||||||
<< errinfo_database_query(query)
|
<< errinfo_database_query(query)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -604,33 +612,33 @@ IdoMysqlResult IdoMysqlConnection::Query(const String& query)
|
||||||
|
|
||||||
IncreaseQueryCount();
|
IncreaseQueryCount();
|
||||||
|
|
||||||
if (mysql_query(&m_Connection, query.CStr()) != 0) {
|
if (m_Mysql->query(&m_Connection, query.CStr()) != 0) {
|
||||||
std::ostringstream msgbuf;
|
std::ostringstream msgbuf;
|
||||||
String message = mysql_error(&m_Connection);
|
String message = m_Mysql->error(&m_Connection);
|
||||||
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
|
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
|
||||||
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
|
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
|
||||||
|
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
database_error()
|
database_error()
|
||||||
<< errinfo_message(mysql_error(&m_Connection))
|
<< errinfo_message(m_Mysql->error(&m_Connection))
|
||||||
<< errinfo_database_query(query)
|
<< errinfo_database_query(query)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MYSQL_RES *result = mysql_store_result(&m_Connection);
|
MYSQL_RES *result = m_Mysql->store_result(&m_Connection);
|
||||||
|
|
||||||
m_AffectedRows = mysql_affected_rows(&m_Connection);
|
m_AffectedRows = m_Mysql->affected_rows(&m_Connection);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
if (mysql_field_count(&m_Connection) > 0) {
|
if (m_Mysql->field_count(&m_Connection) > 0) {
|
||||||
std::ostringstream msgbuf;
|
std::ostringstream msgbuf;
|
||||||
String message = mysql_error(&m_Connection);
|
String message = m_Mysql->error(&m_Connection);
|
||||||
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
|
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
|
||||||
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
|
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
|
||||||
|
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
database_error()
|
database_error()
|
||||||
<< errinfo_message(mysql_error(&m_Connection))
|
<< errinfo_message(m_Mysql->error(&m_Connection))
|
||||||
<< errinfo_database_query(query)
|
<< errinfo_database_query(query)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -638,14 +646,14 @@ IdoMysqlResult IdoMysqlConnection::Query(const String& query)
|
||||||
return IdoMysqlResult();
|
return IdoMysqlResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
return IdoMysqlResult(result, std::ptr_fun(mysql_free_result));
|
return IdoMysqlResult(result, std::bind(&MysqlInterface::free_result, std::cref(m_Mysql), _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
DbReference IdoMysqlConnection::GetLastInsertID(void)
|
DbReference IdoMysqlConnection::GetLastInsertID(void)
|
||||||
{
|
{
|
||||||
AssertOnWorkQueue();
|
AssertOnWorkQueue();
|
||||||
|
|
||||||
return DbReference(mysql_insert_id(&m_Connection));
|
return DbReference(m_Mysql->insert_id(&m_Connection));
|
||||||
}
|
}
|
||||||
|
|
||||||
int IdoMysqlConnection::GetAffectedRows(void)
|
int IdoMysqlConnection::GetAffectedRows(void)
|
||||||
|
@ -664,7 +672,7 @@ String IdoMysqlConnection::Escape(const String& s)
|
||||||
size_t length = utf8s.GetLength();
|
size_t length = utf8s.GetLength();
|
||||||
char *to = new char[utf8s.GetLength() * 2 + 1];
|
char *to = new char[utf8s.GetLength() * 2 + 1];
|
||||||
|
|
||||||
mysql_real_escape_string(&m_Connection, to, utf8s.CStr(), length);
|
m_Mysql->real_escape_string(&m_Connection, to, utf8s.CStr(), length);
|
||||||
|
|
||||||
String result = String(to);
|
String result = String(to);
|
||||||
|
|
||||||
|
@ -681,20 +689,20 @@ Dictionary::Ptr IdoMysqlConnection::FetchRow(const IdoMysqlResult& result)
|
||||||
MYSQL_FIELD *field;
|
MYSQL_FIELD *field;
|
||||||
unsigned long *lengths, i;
|
unsigned long *lengths, i;
|
||||||
|
|
||||||
row = mysql_fetch_row(result.get());
|
row = m_Mysql->fetch_row(result.get());
|
||||||
|
|
||||||
if (!row)
|
if (!row)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
lengths = mysql_fetch_lengths(result.get());
|
lengths = m_Mysql->fetch_lengths(result.get());
|
||||||
|
|
||||||
if (!lengths)
|
if (!lengths)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Dictionary::Ptr dict = new Dictionary();
|
Dictionary::Ptr dict = new Dictionary();
|
||||||
|
|
||||||
mysql_field_seek(result.get(), 0);
|
m_Mysql->field_seek(result.get(), 0);
|
||||||
for (field = mysql_fetch_field(result.get()), i = 0; field; field = mysql_fetch_field(result.get()), i++)
|
for (field = m_Mysql->fetch_field(result.get()), i = 0; field; field = m_Mysql->fetch_field(result.get()), i++)
|
||||||
dict->Set(field->name, String(row[i], row[i] + lengths[i]));
|
dict->Set(field->name, String(row[i], row[i] + lengths[i]));
|
||||||
|
|
||||||
return dict;
|
return dict;
|
||||||
|
|
|
@ -21,10 +21,11 @@
|
||||||
#define IDOMYSQLCONNECTION_H
|
#define IDOMYSQLCONNECTION_H
|
||||||
|
|
||||||
#include "db_ido_mysql/idomysqlconnection.thpp"
|
#include "db_ido_mysql/idomysqlconnection.thpp"
|
||||||
|
#include "mysql_shim/mysqlinterface.hpp"
|
||||||
#include "base/array.hpp"
|
#include "base/array.hpp"
|
||||||
#include "base/timer.hpp"
|
#include "base/timer.hpp"
|
||||||
#include "base/workqueue.hpp"
|
#include "base/workqueue.hpp"
|
||||||
#include <mysql.h>
|
#include "base/library.hpp"
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
@ -74,6 +75,9 @@ private:
|
||||||
|
|
||||||
WorkQueue m_QueryQueue;
|
WorkQueue m_QueryQueue;
|
||||||
|
|
||||||
|
Library m_Library;
|
||||||
|
std::unique_ptr<MysqlInterface, MysqlInterfaceDeleter> m_Mysql;
|
||||||
|
|
||||||
MYSQL m_Connection;
|
MYSQL m_Connection;
|
||||||
int m_AffectedRows;
|
int m_AffectedRows;
|
||||||
unsigned int m_MaxPacketSize;
|
unsigned int m_MaxPacketSize;
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
# along with this program; if not, write to the Free Software Foundation
|
# along with this program; if not, write to the Free Software Foundation
|
||||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
if(PostgreSQL_FOUND)
|
|
||||||
mkclass_target(idopgsqlconnection.ti idopgsqlconnection.tcpp idopgsqlconnection.thpp)
|
mkclass_target(idopgsqlconnection.ti idopgsqlconnection.tcpp idopgsqlconnection.thpp)
|
||||||
|
|
||||||
set(db_ido_pgsql_SOURCES
|
set(db_ido_pgsql_SOURCES
|
||||||
|
@ -28,7 +27,9 @@ if(PostgreSQL_FOUND)
|
||||||
|
|
||||||
add_library(db_ido_pgsql STATIC ${db_ido_pgsql_SOURCES})
|
add_library(db_ido_pgsql STATIC ${db_ido_pgsql_SOURCES})
|
||||||
|
|
||||||
target_link_libraries(db_ido_pgsql ${Boost_LIBRARIES} ${PostgreSQL_LIBRARIES} base config icinga db_ido)
|
include_directories(${PostgreSQL_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
target_link_libraries(db_ido_pgsql ${Boost_LIBRARIES} base config icinga db_ido)
|
||||||
|
|
||||||
set_target_properties (
|
set_target_properties (
|
||||||
db_ido_pgsql PROPERTIES
|
db_ido_pgsql PROPERTIES
|
||||||
|
@ -53,6 +54,3 @@ if(PostgreSQL_FOUND)
|
||||||
)
|
)
|
||||||
|
|
||||||
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}" PARENT_SCOPE)
|
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}" PARENT_SCOPE)
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "You have selected PostgreSQL support, but PostgreSQL could not be found. You can disable the PostgreSQL IDO module using -DICINGA2_WITH_PGSQL=OFF.")
|
|
||||||
endif()
|
|
||||||
|
|
|
@ -50,6 +50,14 @@ void IdoPgsqlConnection::OnConfigLoaded(void)
|
||||||
ObjectImpl<IdoPgsqlConnection>::OnConfigLoaded();
|
ObjectImpl<IdoPgsqlConnection>::OnConfigLoaded();
|
||||||
|
|
||||||
m_QueryQueue.SetName("IdoPgsqlConnection, " + GetName());
|
m_QueryQueue.SetName("IdoPgsqlConnection, " + GetName());
|
||||||
|
|
||||||
|
Library shimLibrary{"pgsql_shim"};
|
||||||
|
|
||||||
|
auto create_pgsql_shim = shimLibrary.GetSymbolAddress<create_pgsql_shim_ptr>("create_pgsql_shim");
|
||||||
|
|
||||||
|
m_Pgsql.reset(create_pgsql_shim());
|
||||||
|
|
||||||
|
std::swap(m_Library, shimLibrary);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdoPgsqlConnection::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
|
void IdoPgsqlConnection::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
|
||||||
|
@ -102,7 +110,7 @@ void IdoPgsqlConnection::Resume(void)
|
||||||
m_ReconnectTimer->Start();
|
m_ReconnectTimer->Start();
|
||||||
m_ReconnectTimer->Reschedule(0);
|
m_ReconnectTimer->Reschedule(0);
|
||||||
|
|
||||||
ASSERT(PQisthreadsafe());
|
ASSERT(m_Pgsql->isthreadsafe());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdoPgsqlConnection::Pause(void)
|
void IdoPgsqlConnection::Pause(void)
|
||||||
|
@ -126,7 +134,7 @@ void IdoPgsqlConnection::ExceptionHandler(boost::exception_ptr exp)
|
||||||
<< "Exception during database operation: " << DiagnosticInformation(exp);
|
<< "Exception during database operation: " << DiagnosticInformation(exp);
|
||||||
|
|
||||||
if (GetConnected()) {
|
if (GetConnected()) {
|
||||||
PQfinish(m_Connection);
|
m_Pgsql->finish(m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,7 +153,7 @@ void IdoPgsqlConnection::Disconnect(void)
|
||||||
|
|
||||||
Query("COMMIT");
|
Query("COMMIT");
|
||||||
|
|
||||||
PQfinish(m_Connection);
|
m_Pgsql->finish(m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +201,7 @@ void IdoPgsqlConnection::Reconnect(void)
|
||||||
Query("SELECT 1");
|
Query("SELECT 1");
|
||||||
return;
|
return;
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
PQfinish(m_Connection);
|
m_Pgsql->finish(m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
reconnect = true;
|
reconnect = true;
|
||||||
}
|
}
|
||||||
|
@ -216,14 +224,14 @@ void IdoPgsqlConnection::Reconnect(void)
|
||||||
passwd = (!ipasswd.IsEmpty()) ? ipasswd.CStr() : nullptr;
|
passwd = (!ipasswd.IsEmpty()) ? ipasswd.CStr() : nullptr;
|
||||||
db = (!idb.IsEmpty()) ? idb.CStr() : nullptr;
|
db = (!idb.IsEmpty()) ? idb.CStr() : nullptr;
|
||||||
|
|
||||||
m_Connection = PQsetdbLogin(host, port, nullptr, nullptr, db, user, passwd);
|
m_Connection = m_Pgsql->setdbLogin(host, port, nullptr, nullptr, db, user, passwd);
|
||||||
|
|
||||||
if (!m_Connection)
|
if (!m_Connection)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PQstatus(m_Connection) != CONNECTION_OK) {
|
if (m_Pgsql->status(m_Connection) != CONNECTION_OK) {
|
||||||
String message = PQerrorMessage(m_Connection);
|
String message = m_Pgsql->errorMessage(m_Connection);
|
||||||
PQfinish(m_Connection);
|
m_Pgsql->finish(m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
|
|
||||||
Log(LogCritical, "IdoPgsqlConnection")
|
Log(LogCritical, "IdoPgsqlConnection")
|
||||||
|
@ -240,7 +248,7 @@ void IdoPgsqlConnection::Reconnect(void)
|
||||||
/* explicitely require legacy mode for string escaping in PostgreSQL >= 9.1
|
/* explicitely require legacy mode for string escaping in PostgreSQL >= 9.1
|
||||||
* changing standard_conforming_strings to on by default
|
* changing standard_conforming_strings to on by default
|
||||||
*/
|
*/
|
||||||
if (PQserverVersion(m_Connection) >= 90100)
|
if (m_Pgsql->serverVersion(m_Connection) >= 90100)
|
||||||
result = Query("SET standard_conforming_strings TO off");
|
result = Query("SET standard_conforming_strings TO off");
|
||||||
|
|
||||||
String dbVersionName = "idoutils";
|
String dbVersionName = "idoutils";
|
||||||
|
@ -249,7 +257,7 @@ void IdoPgsqlConnection::Reconnect(void)
|
||||||
Dictionary::Ptr row = FetchRow(result, 0);
|
Dictionary::Ptr row = FetchRow(result, 0);
|
||||||
|
|
||||||
if (!row) {
|
if (!row) {
|
||||||
PQfinish(m_Connection);
|
m_Pgsql->finish(m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
|
|
||||||
Log(LogCritical, "IdoPgsqlConnection", "Schema does not provide any valid version! Verify your schema installation.");
|
Log(LogCritical, "IdoPgsqlConnection", "Schema does not provide any valid version! Verify your schema installation.");
|
||||||
|
@ -262,7 +270,7 @@ void IdoPgsqlConnection::Reconnect(void)
|
||||||
SetSchemaVersion(version);
|
SetSchemaVersion(version);
|
||||||
|
|
||||||
if (Utility::CompareVersion(IDO_COMPAT_SCHEMA_VERSION, version) < 0) {
|
if (Utility::CompareVersion(IDO_COMPAT_SCHEMA_VERSION, version) < 0) {
|
||||||
PQfinish(m_Connection);
|
m_Pgsql->finish(m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
|
|
||||||
Log(LogCritical, "IdoPgsqlConnection")
|
Log(LogCritical, "IdoPgsqlConnection")
|
||||||
|
@ -316,7 +324,7 @@ void IdoPgsqlConnection::Reconnect(void)
|
||||||
<< "Last update by '" << endpoint_name << "' was " << status_update_age << "s ago.";
|
<< "Last update by '" << endpoint_name << "' was " << status_update_age << "s ago.";
|
||||||
|
|
||||||
if (status_update_age < GetFailoverTimeout()) {
|
if (status_update_age < GetFailoverTimeout()) {
|
||||||
PQfinish(m_Connection);
|
m_Pgsql->finish(m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
SetShouldConnect(false);
|
SetShouldConnect(false);
|
||||||
|
|
||||||
|
@ -328,7 +336,7 @@ void IdoPgsqlConnection::Reconnect(void)
|
||||||
Log(LogNotice, "IdoPgsqlConnection")
|
Log(LogNotice, "IdoPgsqlConnection")
|
||||||
<< "Local endpoint '" << my_endpoint->GetName() << "' is not authoritative, bailing out.";
|
<< "Local endpoint '" << my_endpoint->GetName() << "' is not authoritative, bailing out.";
|
||||||
|
|
||||||
PQfinish(m_Connection);
|
m_Pgsql->finish(m_Connection);
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -437,10 +445,10 @@ IdoPgsqlResult IdoPgsqlConnection::Query(const String& query)
|
||||||
|
|
||||||
IncreaseQueryCount();
|
IncreaseQueryCount();
|
||||||
|
|
||||||
PGresult *result = PQexec(m_Connection, query.CStr());
|
PGresult *result = m_Pgsql->exec(m_Connection, query.CStr());
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
String message = PQerrorMessage(m_Connection);
|
String message = m_Pgsql->errorMessage(m_Connection);
|
||||||
Log(LogCritical, "IdoPgsqlConnection")
|
Log(LogCritical, "IdoPgsqlConnection")
|
||||||
<< "Error \"" << message << "\" when executing query \"" << query << "\"";
|
<< "Error \"" << message << "\" when executing query \"" << query << "\"";
|
||||||
|
|
||||||
|
@ -451,17 +459,17 @@ IdoPgsqlResult IdoPgsqlConnection::Query(const String& query)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *rowCount = PQcmdTuples(result);
|
char *rowCount = m_Pgsql->cmdTuples(result);
|
||||||
m_AffectedRows = atoi(rowCount);
|
m_AffectedRows = atoi(rowCount);
|
||||||
|
|
||||||
if (PQresultStatus(result) == PGRES_COMMAND_OK) {
|
if (m_Pgsql->resultStatus(result) == PGRES_COMMAND_OK) {
|
||||||
PQclear(result);
|
m_Pgsql->clear(result);
|
||||||
return IdoPgsqlResult();
|
return IdoPgsqlResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PQresultStatus(result) != PGRES_TUPLES_OK) {
|
if (m_Pgsql->resultStatus(result) != PGRES_TUPLES_OK) {
|
||||||
String message = PQresultErrorMessage(result);
|
String message = m_Pgsql->resultErrorMessage(result);
|
||||||
PQclear(result);
|
m_Pgsql->clear(result);
|
||||||
|
|
||||||
Log(LogCritical, "IdoPgsqlConnection")
|
Log(LogCritical, "IdoPgsqlConnection")
|
||||||
<< "Error \"" << message << "\" when executing query \"" << query << "\"";
|
<< "Error \"" << message << "\" when executing query \"" << query << "\"";
|
||||||
|
@ -473,7 +481,7 @@ IdoPgsqlResult IdoPgsqlConnection::Query(const String& query)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return IdoPgsqlResult(result, std::ptr_fun(PQclear));
|
return IdoPgsqlResult(result, std::bind(&PgsqlInterface::clear, std::cref(m_Pgsql), _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
DbReference IdoPgsqlConnection::GetSequenceValue(const String& table, const String& column)
|
DbReference IdoPgsqlConnection::GetSequenceValue(const String& table, const String& column)
|
||||||
|
@ -508,7 +516,7 @@ String IdoPgsqlConnection::Escape(const String& s)
|
||||||
size_t length = utf8s.GetLength();
|
size_t length = utf8s.GetLength();
|
||||||
char *to = new char[utf8s.GetLength() * 2 + 1];
|
char *to = new char[utf8s.GetLength() * 2 + 1];
|
||||||
|
|
||||||
PQescapeStringConn(m_Connection, to, utf8s.CStr(), length, nullptr);
|
m_Pgsql->escapeStringConn(m_Connection, to, utf8s.CStr(), length, nullptr);
|
||||||
|
|
||||||
String result = String(to);
|
String result = String(to);
|
||||||
|
|
||||||
|
@ -521,20 +529,20 @@ Dictionary::Ptr IdoPgsqlConnection::FetchRow(const IdoPgsqlResult& result, int r
|
||||||
{
|
{
|
||||||
AssertOnWorkQueue();
|
AssertOnWorkQueue();
|
||||||
|
|
||||||
if (row >= PQntuples(result.get()))
|
if (row >= m_Pgsql->ntuples(result.get()))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
int columns = PQnfields(result.get());
|
int columns = m_Pgsql->nfields(result.get());
|
||||||
|
|
||||||
Dictionary::Ptr dict = new Dictionary();
|
Dictionary::Ptr dict = new Dictionary();
|
||||||
|
|
||||||
for (int column = 0; column < columns; column++) {
|
for (int column = 0; column < columns; column++) {
|
||||||
Value value;
|
Value value;
|
||||||
|
|
||||||
if (!PQgetisnull(result.get(), row, column))
|
if (!m_Pgsql->getisnull(result.get(), row, column))
|
||||||
value = PQgetvalue(result.get(), row, column);
|
value = m_Pgsql->getvalue(result.get(), row, column);
|
||||||
|
|
||||||
dict->Set(PQfname(result.get(), column), value);
|
dict->Set(m_Pgsql->fname(result.get(), column), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dict;
|
return dict;
|
||||||
|
|
|
@ -21,10 +21,11 @@
|
||||||
#define IDOPGSQLCONNECTION_H
|
#define IDOPGSQLCONNECTION_H
|
||||||
|
|
||||||
#include "db_ido_pgsql/idopgsqlconnection.thpp"
|
#include "db_ido_pgsql/idopgsqlconnection.thpp"
|
||||||
|
#include "pgsql_shim/pgsqlinterface.hpp"
|
||||||
#include "base/array.hpp"
|
#include "base/array.hpp"
|
||||||
#include "base/timer.hpp"
|
#include "base/timer.hpp"
|
||||||
#include "base/workqueue.hpp"
|
#include "base/workqueue.hpp"
|
||||||
#include <libpq-fe.h>
|
#include "base/library.hpp"
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
@ -66,6 +67,9 @@ private:
|
||||||
|
|
||||||
WorkQueue m_QueryQueue;
|
WorkQueue m_QueryQueue;
|
||||||
|
|
||||||
|
Library m_Library;
|
||||||
|
std::unique_ptr<PgsqlInterface, PgsqlInterfaceDeleter> m_Pgsql;
|
||||||
|
|
||||||
PGconn *m_Connection;
|
PGconn *m_Connection;
|
||||||
int m_AffectedRows;
|
int m_AffectedRows;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Icinga 2
|
||||||
|
# Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/)
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation
|
||||||
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
include_directories(${MYSQL_INCLUDE_DIR})
|
||||||
|
|
||||||
|
set(mysql_shim_SOURCES
|
||||||
|
mysql_shim.def
|
||||||
|
mysqlinterface.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
if(ICINGA2_UNITY_BUILD)
|
||||||
|
mkunity_target(mysql_shim mysql_shim mysql_shim_SOURCES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(mysql_shim SHARED ${mysql_shim_SOURCES})
|
||||||
|
|
||||||
|
include(GenerateExportHeader)
|
||||||
|
generate_export_header(mysql_shim)
|
||||||
|
|
||||||
|
target_link_libraries(mysql_shim ${MYSQL_LIB})
|
||||||
|
|
||||||
|
set_target_properties (
|
||||||
|
mysql_shim PROPERTIES
|
||||||
|
FOLDER Lib
|
||||||
|
VERSION ${SPEC_VERSION}
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
TARGETS mysql_shim
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/icinga2
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
LIBRARY mysql_shim
|
||||||
|
EXPORTS
|
||||||
|
create_mysql_shim
|
|
@ -0,0 +1,131 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "mysql_shim/mysqlinterface.hpp"
|
||||||
|
|
||||||
|
using namespace icinga;
|
||||||
|
|
||||||
|
struct MysqlInterfaceImpl : public MysqlInterface
|
||||||
|
{
|
||||||
|
void Destroy(void) override
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_ulonglong affected_rows(MYSQL *mysql) const override
|
||||||
|
{
|
||||||
|
return mysql_affected_rows(mysql);
|
||||||
|
}
|
||||||
|
|
||||||
|
void close(MYSQL *sock) const override
|
||||||
|
{
|
||||||
|
return mysql_close(sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *error(MYSQL *mysql) const override
|
||||||
|
{
|
||||||
|
return mysql_error(mysql);
|
||||||
|
}
|
||||||
|
|
||||||
|
MYSQL_FIELD *fetch_field(MYSQL_RES *result) const override
|
||||||
|
{
|
||||||
|
return mysql_fetch_field(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long *fetch_lengths(MYSQL_RES *result) const override
|
||||||
|
{
|
||||||
|
return mysql_fetch_lengths(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MYSQL_ROW fetch_row(MYSQL_RES *result) const override
|
||||||
|
{
|
||||||
|
return mysql_fetch_row(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int field_count(MYSQL *mysql) const override
|
||||||
|
{
|
||||||
|
return mysql_field_count(mysql);
|
||||||
|
}
|
||||||
|
|
||||||
|
MYSQL_FIELD_OFFSET field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset) const override
|
||||||
|
{
|
||||||
|
return mysql_field_seek(result, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_result(MYSQL_RES *result) const override
|
||||||
|
{
|
||||||
|
mysql_free_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MYSQL *init(MYSQL *mysql) const override
|
||||||
|
{
|
||||||
|
return mysql_init(mysql);
|
||||||
|
}
|
||||||
|
|
||||||
|
my_ulonglong insert_id(MYSQL *mysql) const override
|
||||||
|
{
|
||||||
|
return mysql_insert_id(mysql);
|
||||||
|
}
|
||||||
|
|
||||||
|
int next_result(MYSQL *mysql) const override
|
||||||
|
{
|
||||||
|
return mysql_next_result(mysql);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ping(MYSQL *mysql) const override
|
||||||
|
{
|
||||||
|
return mysql_ping(mysql);
|
||||||
|
}
|
||||||
|
|
||||||
|
int query(MYSQL *mysql, const char *q) const override
|
||||||
|
{
|
||||||
|
return mysql_query(mysql, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
MYSQL *real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
|
||||||
|
const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag) const override
|
||||||
|
{
|
||||||
|
return mysql_real_connect(mysql, host, user, passwd, db, port, unix_socket, clientflag);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length) const override
|
||||||
|
{
|
||||||
|
return mysql_real_escape_string(mysql, to, from, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bool ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher) const override
|
||||||
|
{
|
||||||
|
return mysql_ssl_set(mysql, key, cert, ca, capath, cipher);
|
||||||
|
}
|
||||||
|
|
||||||
|
MYSQL_RES *store_result(MYSQL *mysql) const override
|
||||||
|
{
|
||||||
|
return mysql_store_result(mysql);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int thread_safe(void) const override
|
||||||
|
{
|
||||||
|
return mysql_thread_safe();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MysqlInterface *create_mysql_shim(void)
|
||||||
|
{
|
||||||
|
return new MysqlInterfaceImpl();
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MYSQLINTERFACE_H
|
||||||
|
#define MYSQLINTERFACE_H
|
||||||
|
|
||||||
|
#include "mysql_shim/mysql_shim_export.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <mysql.h>
|
||||||
|
|
||||||
|
namespace icinga
|
||||||
|
{
|
||||||
|
|
||||||
|
struct MysqlInterface
|
||||||
|
{
|
||||||
|
MysqlInterface(const MysqlInterface&) = delete;
|
||||||
|
MysqlInterface& operator=(MysqlInterface&) = delete;
|
||||||
|
|
||||||
|
virtual void Destroy(void) = 0;
|
||||||
|
|
||||||
|
virtual my_ulonglong affected_rows(MYSQL *mysql) const = 0;
|
||||||
|
virtual void close(MYSQL *sock) const = 0;
|
||||||
|
virtual const char *error(MYSQL *mysql) const = 0;
|
||||||
|
virtual MYSQL_FIELD *fetch_field(MYSQL_RES *result) const = 0;
|
||||||
|
virtual unsigned long *fetch_lengths(MYSQL_RES *result) const = 0;
|
||||||
|
virtual MYSQL_ROW fetch_row(MYSQL_RES *result) const = 0;
|
||||||
|
virtual unsigned int field_count(MYSQL *mysql) const = 0;
|
||||||
|
virtual MYSQL_FIELD_OFFSET field_seek(MYSQL_RES *result,
|
||||||
|
MYSQL_FIELD_OFFSET offset) const = 0;
|
||||||
|
virtual void free_result(MYSQL_RES *result) const = 0;
|
||||||
|
virtual MYSQL *init(MYSQL *mysql) const = 0;
|
||||||
|
virtual my_ulonglong insert_id(MYSQL *mysql) const = 0;
|
||||||
|
virtual int next_result(MYSQL *mysql) const = 0;
|
||||||
|
virtual int ping(MYSQL *mysql) const = 0;
|
||||||
|
virtual int query(MYSQL *mysql, const char *q) const = 0;
|
||||||
|
virtual MYSQL *real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
|
||||||
|
const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag) const = 0;
|
||||||
|
virtual unsigned long real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length) const = 0;
|
||||||
|
virtual my_bool ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher) const = 0;
|
||||||
|
virtual MYSQL_RES *store_result(MYSQL *mysql) const = 0;
|
||||||
|
virtual unsigned int thread_safe(void) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MysqlInterface(void) = default;
|
||||||
|
~MysqlInterface(void) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MysqlInterfaceDeleter
|
||||||
|
{
|
||||||
|
void operator()(MysqlInterface *ifc) const
|
||||||
|
{
|
||||||
|
ifc->Destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
MYSQL_SHIM_EXPORT icinga::MysqlInterface *create_mysql_shim(void);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef icinga::MysqlInterface *(*create_mysql_shim_ptr)(void);
|
||||||
|
|
||||||
|
#endif /* MYSQLINTERFACE_H */
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Icinga 2
|
||||||
|
# Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/)
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation
|
||||||
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
link_directories(${PostgreSQL_LIBRARY_DIRS})
|
||||||
|
include_directories(${PostgreSQL_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
set(pgsql_shim_SOURCES
|
||||||
|
pgsql_shim.def
|
||||||
|
pgsqlinterface.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
if(ICINGA2_UNITY_BUILD)
|
||||||
|
mkunity_target(pgsql_shim pgsql_shim pgsql_shim_SOURCES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(pgsql_shim SHARED ${pgsql_shim_SOURCES})
|
||||||
|
|
||||||
|
include(GenerateExportHeader)
|
||||||
|
generate_export_header(pgsql_shim)
|
||||||
|
|
||||||
|
target_link_libraries(pgsql_shim ${PostgreSQL_LIBRARIES})
|
||||||
|
|
||||||
|
set_target_properties (
|
||||||
|
pgsql_shim PROPERTIES
|
||||||
|
FOLDER Lib
|
||||||
|
VERSION ${SPEC_VERSION}
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
TARGETS pgsql_shim
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/icinga2
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
LIBRARY pgsql_shim
|
||||||
|
EXPORTS
|
||||||
|
create_pgsql_shim
|
|
@ -0,0 +1,120 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "pgsql_shim/pgsqlinterface.hpp"
|
||||||
|
|
||||||
|
using namespace icinga;
|
||||||
|
|
||||||
|
struct PgsqlInterfaceImpl : public PgsqlInterface
|
||||||
|
{
|
||||||
|
void Destroy(void) override
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear(PGresult *res) const override
|
||||||
|
{
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *cmdTuples(PGresult *res) const override
|
||||||
|
{
|
||||||
|
return PQcmdTuples(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *errorMessage(const PGconn *conn) const override
|
||||||
|
{
|
||||||
|
return PQerrorMessage(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t escapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error) const override
|
||||||
|
{
|
||||||
|
return PQescapeStringConn(conn, to, from, length, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
PGresult *exec(PGconn *conn, const char *query) const override
|
||||||
|
{
|
||||||
|
return PQexec(conn, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void finish(PGconn *conn) const override
|
||||||
|
{
|
||||||
|
PQfinish(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *fname(const PGresult *res, int field_num) const override
|
||||||
|
{
|
||||||
|
return PQfname(res, field_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getisnull(const PGresult *res, int tup_num, int field_num) const override
|
||||||
|
{
|
||||||
|
return PQgetisnull(res, tup_num, field_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *getvalue(const PGresult *res, int tup_num, int field_num) const override
|
||||||
|
{
|
||||||
|
return PQgetvalue(res, tup_num, field_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
int isthreadsafe(void) const override
|
||||||
|
{
|
||||||
|
return PQisthreadsafe();
|
||||||
|
}
|
||||||
|
|
||||||
|
int nfields(const PGresult *res) const override
|
||||||
|
{
|
||||||
|
return PQnfields(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ntuples(const PGresult *res) const override
|
||||||
|
{
|
||||||
|
return PQntuples(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *resultErrorMessage(const PGresult *res) const override
|
||||||
|
{
|
||||||
|
return PQresultErrorMessage(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecStatusType resultStatus(const PGresult *res) const override
|
||||||
|
{
|
||||||
|
return PQresultStatus(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
int serverVersion(const PGconn *conn) const override
|
||||||
|
{
|
||||||
|
return PQserverVersion(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
PGconn *setdbLogin(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd) const override
|
||||||
|
{
|
||||||
|
return PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, login, pwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnStatusType status(const PGconn *conn) const override
|
||||||
|
{
|
||||||
|
return PQstatus(conn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PgsqlInterface *create_pgsql_shim(void)
|
||||||
|
{
|
||||||
|
return new PgsqlInterfaceImpl();
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef PGSQLINTERFACE_H
|
||||||
|
#define PGSQLINTERFACE_H
|
||||||
|
|
||||||
|
#include "pgsql_shim/pgsql_shim_export.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <libpq-fe.h>
|
||||||
|
|
||||||
|
namespace icinga
|
||||||
|
{
|
||||||
|
|
||||||
|
struct PgsqlInterface
|
||||||
|
{
|
||||||
|
PgsqlInterface(const PgsqlInterface&) = delete;
|
||||||
|
PgsqlInterface& operator=(PgsqlInterface&) = delete;
|
||||||
|
|
||||||
|
virtual void Destroy(void) = 0;
|
||||||
|
|
||||||
|
virtual void clear(PGresult *res) const = 0;
|
||||||
|
virtual char *cmdTuples(PGresult *res) const = 0;
|
||||||
|
virtual char *errorMessage(const PGconn *conn) const = 0;
|
||||||
|
virtual size_t escapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error) const = 0;
|
||||||
|
virtual PGresult *exec(PGconn *conn, const char *query) const = 0;
|
||||||
|
virtual void finish(PGconn *conn) const = 0;
|
||||||
|
virtual char *fname(const PGresult *res, int field_num) const = 0;
|
||||||
|
virtual int getisnull(const PGresult *res, int tup_num, int field_num) const = 0;
|
||||||
|
virtual char *getvalue(const PGresult *res, int tup_num, int field_num) const = 0;
|
||||||
|
virtual int isthreadsafe(void) const = 0;
|
||||||
|
virtual int nfields(const PGresult *res) const = 0;
|
||||||
|
virtual int ntuples(const PGresult *res) const = 0;
|
||||||
|
virtual char *resultErrorMessage(const PGresult *res) const = 0;
|
||||||
|
virtual ExecStatusType resultStatus(const PGresult *res) const = 0;
|
||||||
|
virtual int serverVersion(const PGconn *conn) const = 0;
|
||||||
|
virtual PGconn *setdbLogin(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd) const = 0;
|
||||||
|
virtual ConnStatusType status(const PGconn *conn) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PgsqlInterface(void) = default;
|
||||||
|
~PgsqlInterface(void) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PgsqlInterfaceDeleter
|
||||||
|
{
|
||||||
|
void operator()(PgsqlInterface *ifc) const
|
||||||
|
{
|
||||||
|
ifc->Destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
PGSQL_SHIM_EXPORT icinga::PgsqlInterface *create_pgsql_shim(void);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef icinga::PgsqlInterface *(*create_pgsql_shim_ptr)(void);
|
||||||
|
|
||||||
|
#endif /* PGSQLINTERFACE_H */
|
Loading…
Reference in New Issue